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

📄 max3420e_evkit2_democode.asm

📁 MAX的USB3420E芯片的技术应用文档
💻 ASM
📖 第 1 页 / 共 2 页
字号:
//---------------------------------------------------------------------------
// Copyright (C) 2006 Maxim Integrated Products, Inc. All Rights Reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY,  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL MAXIM INTEGRATED PRODUCTS INC. BE LIABLE FOR ANY CLAIM, DAMAGES
// OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//---------------------------------------------------------------------------
;
; Atmel AtTiny2313 Firmware for Maxim 3420E EVKIT-2
;
; MAX3420E HID Keyboard emulator. 
;
; At power on, if any of the pushbuttons 0-3 (SW1-SW4) is pressed, enter a test loop
; that reads the pushbuttons and copies their states to the four LEDS 0-3 (D1-D4). The
; LEDS are active-high, and the pushbuttons are active-low, so pressing a pushbutton 
; should turn the corresponding LED off. When finished with this test, press buttons
; 0 and 3 simultaneously to proceed to the USB sample application.
;
; The sample application (which automatically runs if no buttons are pressed at power-on)
; implements a HID keyboard emulator. Pressing the SEND button (button 3) starts and stops
; typing an abbreviated version of the MAX3420E data sheet into any Windows window that
; can accept text and which currently has the focus. CAUTION--This includes any open
; window, such as email, a Word document, program editor, etc. Be sure you have a simple 
; app like Notepad or Wordpad open and active before pushing the SEND button.
;
; Buttons:
; 0	(not used)
; 1	(not used)
; 2	(not used)
; 3	Start/Stop sending characters as keyboard
;
; Lights:
; 0	Blinks to show program is running
; 1	MAX3420E detected a USB bus reset			 
; 2	SUSPEND (PC stopped USB activity)
; 3	SEND light. Toggles when pushbutton 3 pressed.
;
.include "tn2313def_lth.inc"
.include "USB_constants.inc"
.include "HID_KB_2313_Descriptors_and_Data.inc"
.include "MAX3420E_Macros.inc"
;
; AtTiny2313 PORT B bit assignments 
;
.EQU	MOSI	=	5	; out
.EQU	MISO	=	6	; in
.EQU	SCK		=	7	; out
.EQU	INTR	=	3	; in
.EQU	SSN		=	4	; out
;
.EQU	BUTTC	 	= 250	; time constant to check pushbuttons
.EQU	BLINKTC		= 150	; decremented every buttime

; Assign names to registers. R0-R15 for variables that are not loaded with immediate values.

.DEF	configval		= R0	; Initialize to 0, set to contents of host Set_Config request
.DEF	dat				= R3
.DEF	rval			= R4
.DEF	desclen			= R5	; descriptor length, read from ROM
	
; Registers that require load-immediate addressing

.DEF	flags			= R16;	; flags b7=inhibit_send, b6=RWU_enabled, b5=Suspended, b4=ep3stall
.equ	Send_Flag		= 7
.equ	bmSend_Flag		= 0b10000000	; for eor instruction		
.equ	RWU_enabled		= 6
.equ	Suspended		= 5
.equ	ep3stall		= 4
.equ	setclrfeature	= 3
.equ	UNIflag			= 2		; Unicode string descriptor requested
.equ	butstate		= 1		; send/stop button state
.equ	keyupflag		= 0		; send keys-up after every keystroke

.DEF	button_time		= R17	; Time delay for polling the pushbuttons. 0-255.
.DEF	MAX_Reg 		= R18	; Used by rreg and wreg
.DEF	MAX_Dat 		= R19	; Used by rreg and wreg
.DEF	bitcount		= R20	; used by rreg & wreg
.DEF	temp			= R21	; ditto
.DEF	pMessage		= R22	; Message pointer
.DEF	reqlen			= R23	; Requested length
.DEF	blink_time		= R24	; Time between light blinks. This 8 bit timer runs 0-255
;
; R25 is reserved for SRAM macros.
; R26 is reserved for the WAIT_TICK macro (not used in this app)
; Note: R26-27=X, R28-29=Y, R30-31=Z
; This program uses only Z as an index register, so R26-R29 are free.
;
.DSEG
SUD:	.BYTE 8		; 8 setup bytes

.CSEG
.ORG 0				; Interrupt Vectors
rjmp	RESET		; RESET
reti				; INT0
reti				; INT1
reti				; TIM1_CAPT
reti				; TIM1_COMPA
reti				; TIM1_OVF
reti				; TIM0_OVF
reti				; USART0_RXC
reti				; USART0_DRE
reti				; USART0_TXC
reti				; ANA_COMP
reti				; PCINT (8 more interrupt vectors but we aren't using them)
;
;------------------------------------------------------
RESET:
;
	ldi		R16,LOW(RAMEND)
	out		SPL,r16					; set stack pointer to top of RAM
	clr		flags					; initalze all flag bits
	clr		configval				; we're initially unconfigured
;
	SCK_LO							; initialize the SPI outputs before enabling them as outputs
	SS_HI
	MOSI_LO
	ldi		r20,0b10110000			; AtTiny2313: bits 7,5,4 are SPI outputs, bits 6 (MISO),3 (INT) are inputs
	out		DDRB,r20				; make them so
	WREGI	rPINCTL,(bmFDUPSPI+bmPOSINT+1)	; Must do this to set up SPI full duplex before accessing any regs. GPX = VBDetect
	rcall	Reset_MAX
;
; At power on, check for any button press. If so, enter a test loop that copies button states to the 
; four LEDS attached to the MAX3420E GP0 pins. If not, proceed directly to the HID Keyboard application.
;
	mRREG	rIOPINS					; GPIN3 GPIN2 GPIN1 GPIN0 GPOUT3 GPOUT2 GPOUT1 GPOUT0
	andi	MAX_dat,0b11110000		; consider only the input pins
	cpi		MAX_dat,0b11110000		; all up?
	breq	doApp					; go right to the app if nothing pressed. Otherwise, drop thru to button/light test.
;
testbuts:
	mRREG	rIOPINS					
	swap	MAX_dat
	mWREG	rIOPINS,MAX_dat			; PB's & LEDS: 1=off, 0=on
	andi	MAX_dat,0b00001111
	cpi		MAX_dat,0b00000110		; pressing both (active low) buttons 0 & 3 stop this test
	brne	testbuts
;
doApp:
	WREGI	rIOPINS,0x00			; all lights off
	WREGI	rUSBCTL,bmCONNECT
;
Initialize:
	WREGI	rEPIEN,(bmSUDAVIE+bmIN3BAVIE)
	WREGI	rUSBIEN,(bmUSBRESIE)	; NOTE: The suspend interrupt is enabled when we are configured as a USB device (Set_Configuration)
	WREGI	rCPUCTL,bmIE			; enable the INT output pin
	ldi		blink_time,BLINKTC
;
	ldi		pMessage,LOW(KB_Message*2); Initialize a pointer to the message to type
	rcall	send_keystroke			; preload the first KB bytes to clear the IN3BAVIRQ
;
; ******************************************************************************
; Endless loop to check for blink timer, suspend interrupt, and any USB requests
;
mainloop:
	sbis	pinb,3					; MAX3420E INT bit tied to PORTB.3 & configured for pos edge
	rjmp	L5

; Check for Setup Data Available IRQ
	mRREG	rEPIRQ
	mov		rval,MAX_Dat		
	sbrs	rval,5					; EPIRQ reg bit 5 is SUDAVIRQ
	rjmp	L2
	WREGI	rEPIRQ,bmSUDAVIRQ		; clear the IRQ bit
	rcall	Do_SETUP

; Check for EP3 Buffer Available IRQ
L2:	sbrs	rval,4					; EPIRQ reg bit 4 is IN3BAVIRQ
	rjmp	L3
	rcall	send_keystroke

; Check for USB reset IRQ
L3:	mRREG	rUSBIRQ
	mov		rval,MAX_Dat
	sbrs	rval,3					; USBIRQ reg bit 3 is URESIRQ
	rjmp	L4	
	WREGI	rUSBIRQ,bmUSBRESIRQ		; clear the IRQ bit
	WREGI	rIOPINS,0x02			; L1 on
	ldi		MAX_Reg,rUSBIRQ
LR1:rcall	rreg
	andi	MAX_Dat,bmUSBRESDNIRQ	; check for reset done
	breq	LR1
	WREGI	rUSBIRQ,bmUSBRESDNIRQ	; clear the IRQ
	WREGI	rIOPINS,0x00			; all lights off
	rjmp	Initialize				; re-enable the interrupts			

; Check for SUSPEND IRQ only if we're configured

L4:	tst		configval
	breq	L5						; skip if we're not configured
	sbrs	rval,4					; USBIRQ reg bit 4 is SUSPEND IRQ
	rjmp	L5
	rcall	Suspend					; stays in this subroutine until RESUME by host
;
L5:	dec		button_time
	brne	mainloop				; check buttons if timer expires
;
; Check the button. GPIN-3 = toggle send/stop	(was GPIN-1 for AtTiny13)
;
	mRREG	rIOPINS
	bst		MAX_Dat,7				; T <- GPI-3
	brtc	but_down				; active low--branch if button down
;
	bst		flags,butstate			; T<-butstate. Button is up--was it up (1) last time?
	brts	L7						; yes--do nothing
	SETFLAG	butstate				; no--just show it's up now
	rjmp	L7
but_down:
	bst		flags,butstate			; button is down--was it down (0) last time?
	brtc	L7						; yes--do nothing
	CLRFLAG	butstate				; no--update it and toggle the SEND light
;
; Toggle the Send_Flag
;
	ldi		temp,bmSend_Flag		; Send_Flag is bit 7 of flags reg
	eor		flags,temp				; toggle the send bit
	bst		flags,Send_Flag			; Send_Flag -> T
	bld		MAX_Dat,3				; MAX_Dat.3 <- T
	mWREG	rIOPINS,Max_Dat			; update the SEND light (GPO-3)
;
; Blink a light whenever the blink_count hits zero
;
L7:	dec		blink_time
	brne	L8
	ldi		blink_time,BLINKTC
	seT
	sbrc	MAX_Dat,0				; check GPOUT0: IOPINS.0 (in MAX_Dat)
	clT
	bld		MAX_Dat,0
	rcall	wreg
L8:	rjmp	mainloop
;
; *******************************************************************************		
Suspend:
	WREGI	rUSBIRQ,(bmSUSPIRQ+bmBUSACTIRQ)	; clear the IRQ bit & remove bus activity remnants
	WREGI	rUSBIEN,BMBUSACTIE		; only check for this interrupt
	WREGI	rIOPINS,0b00000100		; turn on GPO-2 light (only) to show SUSPEND
;
; Now wait for the BUSACT IRQ
;
s1:	sbis	pinb,3		; MAX3420E INT bit tied to PORTB.3 & configured for pos edge
	rjmp	s1			; skip this if INT happened						; 
;						
suspend_done:
	WREGI	rUSBIEN,(bmUSBRESIE+bmSUSPENDIE) ;disable BUSACTIE and re-enable BUSRES and SUSPEND IE's
	ldi		MAX_Reg,rIOPINS
	rcall	rreg
	andi	MAX_Dat,0b11111011		; turn off GPO-2 (SUSPEND) light
	rcall	wreg	
	ret				
;
; ----------------------------------------------------------------------
; Reset the MAX3420E. Set the CHIPRES bit, delay, clear the CHIPRES bit. 
; Then wait for OSCOK IRQ to assert.
; ----------------------------------------------------------------------
Reset_MAX:
	WREGI	rUSBCTL,bmCHIPRES
	ldi		MAX_Dat,0			; remove the chip reset
	rcall	wreg
;
; Resetting the chip stops the oscillator. Wait for it to stabilize
; by checking the OSCOK interrupt. Note: no need to first clear this
; IRQ because the chip reset does it.
;
	ldi		MAX_Reg,rUSBIRQ		; the OSCOKIRQ bit lives in this register
rm2:
	rcall	rreg
	andi	MAX_Dat,bmOSCOKIRQ
	breq	rm2
	WREGI	rUSBIRQ,bmOSCOKIRQ	; clear the OSC IRQ bit
	ret
; --------------------
; USB Request routines
; --------------------
;
Do_SETUP:						; Copy 8 setup bytes into SUD array in RAM
	ldi		MAX_Reg,rSUDFIFO
	ldi		ZL,LOW(SUD)
	ldi		ZH,0
	ldi		temp,8				; fetch 8 bytes
su1:
	rcall	rreg				; result in MAX_Dat
	st		Z+,MAX_Dat
	dec		temp
	brne	su1
;
; Respond to standard requests only (HID KB data requests are be requested via IN requests to EP3-IN)
;
	lds		temp,SUD+bmRequestType
	andi	temp,0b01100000		; check b6-b5 for request type
	cpi		temp,0b00000000		; 00 is standard request
	breq	std_request			; don't need to check for 01, class request since we have the INT IN endpoint for data
		
stall:							; vendor request (10) or undefined.
	ldi		MAX_Reg,rEPSTALLS
	ldi		MAX_Dat,0x23
	rjmp	wreg				; return from there. DON'T set ACKSTAT bit.
;
std_request:
	lds		temp,SUD+bRequest
	cpi		temp,13				; make sure it's 0-12
	brcc	stall					; carry set for 12-13, clear for 13-13
	ldi		ZH,HIGH(sr_jump_table)
	ldi		ZL,LOW(sr_jump_table)
	add		ZL,temp
	brcc	nc
	inc		ZH
nc:	ijmp						; PC=Z+temp
;
sr_jump_table:					; Standard Request Jump Table
	rjmp	Get_Status			; 0
	rjmp	Clear_Feature		; 1
	rjmp	stall				; 2--Reserved (Stall)
	rjmp	Set_Feature			; 3
	rjmp	stall				; 4--Reserved (Stall)
	rjmp	as					; 5--Set_Address: do nothing but complete the CTL xfr
	rjmp	Get_Descriptor		; 6
	rjmp	stall				; 7--Set_Descriptor (Stall)
	rjmp	Get_Configuration	; 8
	rjmp	Set_Configuration	; 9
	rjmp	Get_Interface		; 10
	rjmp	Set_Interface		; 11
	rjmp	stall				; 12--Sync_Frame (Stall)
;	
Set_Feature:
	SETFLAG	setclrfeature
	rjmp	feature
Clear_Feature:
	CLRFLAG	setclrfeature		; fall through to 'feature'
;
; ----------------------------------------------------------------
; GET/SET_Feature Request.The 'setclrfeature' flag says which one.
; ----------------------------------------------------------------
feature:						; check for bmRequestType = 0x02 AND wValueL = 0 AND wIndexL = 0x83
	lds		temp,SUD+bmRequestType
	cpi		temp,0x02			; dir is h->p, recipient is EP ?
	brne	stall
	lds		temp,SUD+wValueL
	cpi		temp,0				; wValueL is feature selector, 00 is EP halt
	brne	stall
	lds		temp,SUD+wIndexL
	cpi		temp,0x83			; 83 is value for EP3-IN
	brne	stall				; we only support EP-STALL 
;
; It's a Set/Clr_Feature--endpoint halt request
;
	ldi		MAX_Reg,rEPSTALLS	; get the existing stall bits
	rcall	rreg				; value in MAX_Dat
	SKIP_ON_FLAG setclrfeature	

⌨️ 快捷键说明

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