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

📄 mjoy.asm

📁 用于AVR的USB
💻 ASM
📖 第 1 页 / 共 5 页
字号:
;***************************************************************************
;* U S B   S T A C K   F O R   T H E   A V R   F A M I L Y
;* 
;* File Name            :"MJoy.asm"
;* Title                :MJoy  - USB Joystick based on USB stack
;* Date                 :1.17.2004
;* Version              :1.2
;* Target MCU           :ATmega8
;* Assembler			:Atmel AVR Studio
;* AUTHOR		:	Mindaugas Milasauskas	
;*					Lithuania
;*					mindaug@mindaugas.com
;*					http://www.mindaugas.com
;* Based on code of: 
;*					Ing. Igor Cesko
;* 			 		Slovakia
;* 				 	cesko@internet.sk
;* 			 		http://www.cesko.host.sk
;*
;* DESCRIPTION:
;*  USB protocol implementation into MCU with noUSB interface:
;*  Device:
;*  MJoy USB Joystick
;*
;* The timing is adapted for 12 MHz crystal
;*
;*
;*	Release Notes:
;*
;*	v1.2:	Second public release
;*			6 axis (4 x 10 bit + 2 x 8 bit), 24 buttons, 1 hat (uses 4 buttons)
;*			Added autocalibration
;*			Changed layout of HID descriptor
;*			Changed USB Vendor ID to make MJoy appear on top of the game devices list
;*			Optimized HatSwitch Code
;*			Rudder and Throttle axis ar now 10bit
;*			Changed axis Dial, Slider to Rx, Z
;*			Optimized partially non-blocking ADC reading
;*
;*
;*	v1.1:	First public release
;*			6 axis - 2x10bit axis + 4x8bit axis
;*			24 buttons
;*			1 hat (uses 4 buttons)
;*			
;*	v1.0:	Very first lab release with 2x10bit axis and 4 buttons
;*
;*
;***************************************************************************
.include "m8def.inc"
.equ	UCR			=UCSRB
.equ	UBRR			=UBRRL
.equ	EEAR			=EEARL
.equ	USR			=UCSRA
.equ	E2END			=127
.equ	RAMSIZE			=159
.equ	RAMEND_MJ			=255

.equ	inputport		=PINB
.equ	outputport		=PORTB
.equ	USBdirection		=DDRB
.equ	DATAplus		=1		;signal D+ on PB1
.equ	DATAminus		=0		;signal D- on PB0 - give on this pin pull-up 1.5kOhm
.equ	USBpinmask		=0b11111100	;mask low 2 bit (D+,D-) on PB
.equ	USBpinmaskDplus		=~(1<<DATAplus)	;mask D+ bit on PB
.equ	USBpinmaskDminus	=~(1<<DATAminus);mask D- bit on PB


.equ	SOPbyte			=0b10000000	;Start of Packet byte
.equ	DATA0PID		=0b11000011	;PID for DATA0 field
.equ	DATA1PID		=0b01001011	;PID for DATA1 field
.equ	OUTPID			=0b11100001	;PID for OUT field
.equ	INPID			=0b01101001	;PID for IN field
.equ	SOFPID			=0b10100101	;PID for SOF field
.equ	SETUPPID		=0b00101101	;PID for SETUP field
.equ	ACKPID			=0b11010010	;PID for ACK field
.equ	NAKPID			=0b01011010	;PID for NAK field
.equ	STALLPID		=0b00011110	;PID for STALL field
.equ	PREPID			=0b00111100	;PID for FOR field

.equ	nSOPbyte		=0b00000001	;Start of Packet byte - reverse order
.equ	nDATA0PID		=0b11000011	;PID for DATA0 field - reverse order
.equ	nDATA1PID		=0b11010010	;PID for DATA1 field - reverse order
.equ	nOUTPID			=0b10000111	;PID for OUT field - reverse order
.equ	nINPID			=0b10010110	;PID for IN field - reverse order
.equ	nSOFPID			=0b10100101	;PID for SOF field - reverse order
.equ	nSETUPPID		=0b10110100	;PID for SETUP field - reverse order
.equ	nACKPID			=0b01001011	;PID for ACK field - reverse order
.equ	nNAKPID			=0b01011010	;PID for NAK field - reverse order
.equ	nSTALLPID		=0b01111000	;PID for STALL field - reverse order
.equ	nPREPID			=0b00111100	;PID for FOR field - reverse order

.equ	nNRZITokenPID		=~0b10000000	;PID mask for Token packet (IN,OUT,SOF,SETUP) - reverse order NRZI
.equ	nNRZISOPbyte		=~0b10101011	;Start of Packet byte - reverse order NRZI
.equ	nNRZIDATA0PID		=~0b11010111	;PID for DATA0 field - reverse order NRZI
.equ	nNRZIDATA1PID		=~0b11001001	;PID for DATA1 field - reverse order NRZI
.equ	nNRZIOUTPID		=~0b10101111	;PID for OUT field - reverse order NRZI
.equ	nNRZIINPID		=~0b10110001	;PID for IN field - reverse order NRZI
.equ	nNRZISOFPID		=~0b10010011	;PID for SOF field - reverse order NRZI
.equ	nNRZISETUPPID		=~0b10001101	;PID for SETUP field - reverse order NRZI
.equ	nNRZIACKPID		=~0b00100111	;PID for ACK field - reverse order NRZI
.equ	nNRZINAKPID		=~0b00111001	;PID for NAK field - reverse order NRZI
.equ	nNRZISTALLPID		=~0b00000111	;PID for STALL field - reverse order NRZI
.equ	nNRZIPREPID		=~0b01111101	;PID for FOR field - reverse order NRZI
.equ	nNRZIADDR0		=~0b01010101	;Address = 0 - reverse order NRZI

						;status bytes - State
.equ	BaseState		=0		;
.equ	SetupState		=1		;
.equ	InState			=2		;
.equ	OutState		=3		;
.equ	SOFState		=4		;
.equ	DataState		=5		;

						;Flags of action
.equ	DoNone					=0
.equ	DoReceiveOutData			=1
.equ	DoReceiveSetupData			=2
.equ	DoPrepareOutContinuousBuffer		=3
.equ	DoReadySendAnswer			=4
.equ	DoPrepareJoystickAnswer			=5
.equ	DoReadySendJoystickAnswer			=6

			; Joystick flags
.equ	JoystickDataRequest		=1
.equ	JoystickDataRequestBit		=0
.equ	JoystickDataReady		=2
.equ	JoystickDataReadyBit		=1
.equ	JoystickDataProcessing	=4
.equ	JoystickDataProcessingBit	=2
.equ	JoystickLastDataPID		=8
.equ	JoystickLastDataPIDBit		=3
.equ	JoystickReportID		=0b00010000
.equ	JoystickReportIDBit			=4

.equ	CRC16poly		=0b1000000000000101	;CRC16 polynomial

.equ	Sym10StructSize	=12
.equ	Sym10EEStructSize	=4
.equ	Asym8StructSize =8
.equ	Asym8EEStructSize =4

.equ	XAxisChannel	= 0
.equ	YAxisChannel	= 1
.equ	RudderAxisChannel	= 2
.equ	ThrottleAxisChannel	= 3
.equ	ZAxisChannel		= 4
.equ	RxAxisChannel	= 5

.equ	MAXUSBBYTES		=14			;maximum bytes in USB input message
.equ	NumberOfFirstBits	=10			;how many first bits allowed be longer
.equ	NoFirstBitsTimerOffset	=256-12800*12/1024	;Timeout 12.8ms (12800us) to terminate after firsts bits

.equ	InputBufferBegin	=RAMEND_MJ-RAMSIZE				;compare of receiving shift buffer
.equ	InputShiftBufferBegin	=InputBufferBegin+MAXUSBBYTES		;compare of receiving buffera

.equ	OutputBufferBegin	=RAMEND_MJ-MAXUSBBYTES-2	;compare of transmitting buffer
.equ	AckBufferBegin		=OutputBufferBegin-3	;compare of transmitting buffer Ack
.equ	NakBufferBegin		=AckBufferBegin-3	;compare of transmitting buffer Nak
.equ	ConfigByte		=NakBufferBegin-1	;0=unconfigured state
.equ	AnswerArray		=ConfigByte-8		;8 byte answer array
.equ	JoystickBufferBegin	= AnswerArray - MAXUSBBYTES
.equ	JoyOutputBufferLength = JoystickBufferBegin - 1
.equ	JoyOutBitStuffNumber = JoyOutputBufferLength - 1
.equ	BkpOutputBufferLength = JoyOutBitStuffNumber - 1
.equ	BkpOutBitStuffNumber = BkpOutputBufferLength - 1
.equ	JoyVal = BkpOutBitStuffNumber - 1
.equ	ADCChanStarted		=JoyVal - 1
.equ	ADCValueH		=ADCChanStarted - 1
.equ	ADCValueL		=ADCValueH -1

.equ	RegistersBackup = ADCValueL-32

.equ	EEPROMFlags = RegistersBackup-1

.equ	StackBegin		=EEPROMFlags-1		;low reservoir (stack is big cca 54 byte)


.equ	XAxisRAM 			=RAMEND - Sym10StructSize
.equ	YAxisRAM 			=XAxisRAM - Sym10StructSize
.equ	RudderAxisRAM 		=YAxisRAM - Sym10StructSize
.equ	ThrottleAxisRAM 	=RudderAxisRAM - Sym10StructSize
.equ	ZAxisRAM 			=ThrottleAxisRAM - Asym8StructSize
.equ	RxAxisRAM 			=ZAxisRAM - Asym8StructSize



.def	JoystickFlags		=R1		; Endpoint 1 interrupt status flags for joystick reports
.def	backupbitcount		=R2		;backup bitcount register in INT0 disconnected
.def	RAMread			=R3		;if reading from SRAM
.def	backupSREGTimer		=R4		;backup Flag register in Timer interrupt
.def	backupSREG		=R5		;backup Flag register in INT0 interrupt
.def	ACC			=R6		;accumulator
.def	lastBitstufNumber	=R7		;position in bitstuffing
.def	OutBitStuffNumber	=R8		;how many bits to send last byte - bitstuffing
.def	BitStuffInOut		=R9		;if insertion or deleting of bitstuffing
.def	TotalBytesToSend	=R10		;how many bytes to send
.def	TransmitPart		=R11		;order number of transmitting part
.def	InputBufferLength	=R12		;length prepared in input USB buffer
.def	OutputBufferLength	=R13		;length answers prepared in USB buffer
.def	MyUpdatedAddress	=R14		;my USB address for update
.def	MyAddress		=R15		;my USB address


.def	ActionFlag		=R16		;what to do in main program loop
.def	temp3			=R17		;temporary register
.def	temp2			=R18		;temporary register
.def	temp1			=R19		;temporary register
.def	temp0			=R20		;temporary register
.def	bitcount		=R21		;counter of bits in byte
.def	ByteCount		=R22		;counter of maximum number of received bytes
.def	inputbuf		=R23		;receiver register 
.def	shiftbuf		=R24		;shift receiving register 
.def	State			=R25		;state byte of status of state machine
;.def	XL				=R26		;XL register - pointer to buffer of received IR codes
;.def	XH				=R27
.def	USBBufptrY		=R28		;YL register - pointer to USB buffer input/output
.def	ROMBufptrZ		=R30		;ZL register - pointer to buffer of ROM data


;requirements on descriptors
.equ	GET_STATUS		=0
.equ	CLEAR_FEATURE		=1
.equ	SET_FEATURE		=3
.equ	SET_ADDRESS		=5
.equ	GET_DESCRIPTOR		=6
.equ	SET_DESCRIPTOR		=7
.equ	GET_CONFIGURATION	=8
.equ	SET_CONFIGURATION	=9
.equ	GET_INTERFACE		=10
.equ	SET_INTERFACE		=11
.equ	SYNCH_FRAME		=12

; Class requests
.equ 	GET_REPORT		=1
.equ 	GET_IDLE		=2
.equ 	GET_PROTOCOL	=3
.equ 	SET_REPORT		=9
.equ 	SET_IDLE		=10
.equ 	SET_PROTOCOL	=11

;Standard descriptor types
.equ	DEVICE			=1
.equ	CONFIGURATION		=2
.equ	STRING			=3
.equ	INTERFACE		=4
.equ	ENDPOINT		=5

; Class Descriptor Types
.equ	CLASS_HID		=0x21
.equ	CLASS_Report	=0x22
.equ	CLASS_Physical	=0x23

;databits
.equ	DataBits5		=0
.equ	DataBits6		=1
.equ	DataBits7		=2
.equ	DataBits8		=3

;parity
.equ	ParityNone		=0
.equ	ParityOdd		=1
.equ	ParityEven		=2
.equ	ParityMark		=3
.equ	ParitySpace		=4

;stopbits
.equ	StopBit1		=0
.equ	StopBit2		=1

;user function start number
.equ	USER_FNC_NUMBER		=100


.equ	UpdEEThd	= 1500	; 15 seconds to wait before EEPROM write	
							; this is the threshold determining how many cycles to pass before
							; writing axis data to EEPROM. It determines the delay before 
							; writing which is Delay = CyclePeriod * UpdEEThd

; The structure of Joystick Axis data; All values are offsets
.equ	s_UpdateCntH	=0		; Update counter to avoid too many writes to EEPROM
.equ	s_UpdateCntL	=1

.equ	s_EEPROMStructStart		=2		; 16 bit unsigned minimum registered ADC input value
.equ	s_MinH 			=2		; 16 bit unsigned minimum registered ADC input value
.equ	s_MinL 			=3		; 
.equ	s_MaxH 			=4		; 16 bit unsigned maximum registered ADC input value
.equ	s_MaxL 			=5		; 
.equ	s_CoefH 		=6		; 16 bit unsigned asymmetric axis range coeficient
.equ	s_CoefL 		=7

.equ	s_NegCoefH 		=6		; 16 bit unsigned axis negative range coeficient
.equ	s_NegCoefL 		=7
.equ	s_CenterH 		=8		; 16 bit unsigned axis center / offset value
.equ	s_CenterL 		=9		;		 ( not used for asymmetric axes )
.equ	s_PosCoefH 		=10		; 16 bit unsigned axis negative range coeficient
.equ	s_PosCoefL 		=11		;		 ( not used for asymmetric axes )





;------------------------------------------------------------------------------------------
;********************************************************************
;* ;* Interrupt table
;********************************************************************
.cseg
;------------------------------------------------------------------------------------------
.org 0						;after reset
		rjmp	reset
;------------------------------------------------------------------------------------------
.org INT0addr					;external interrupt INT0
		rjmp	INT0handler
;------------------------------------------------------------------------------------------

.org ERDYaddr
		reti
;------------------------------------------------------------------------------------------
;********************************************************************
;*  Init program
;********************************************************************
;------------------------------------------------------------------------------------------
reset:			;initialization of processor and variables to right values
		ldi	temp0,StackBegin	;initialization of stack
		out	SPL,temp0

		clr	XH				;RS232 pointer
		clr	YH				;USB pointer
		clr	ZH				;ROM pointer
		clr	JoystickFlags
		ldi		temp0,JoystickDataReady
		or		JoystickFlags,temp0 


		clr	MyUpdatedAddress	;new address USB -  non-decoded
		rcall	InitACKBufffer		;initialization of ACK buffer
		rcall	InitNAKBufffer		;initialization of NAK buffer
		rcall	InitJoystickBufffer		;initialization of Joystick buffer

		rcall	USBReset		;initialization of USB addresses
		
		ldi	temp0,0b00000100	;set pull-up on PORTB
		out	PORTB,temp0
		ldi	temp0,0b11000000	;set pull-up on PORTC
		out	PORTC,temp0
		ldi	temp0,0b01111011	;set pull-up on PORTD
		out	PORTD,temp0

		ldi	temp0,0b00000000	;set input on PORTD
		out	DDRD,temp0

		clr	temp0			;
		out	EEARH,temp0		;zero EEPROM index

	; prepare ADC
		ldi	temp0, 0b10000110	;ADC enable
								; no start yet
								; Single Conversion mode
								; no interrupts
								;set ADC prescaler to 12MHz / 64 = 187.5kHz
		out ADCSRA,temp0	

		ldi	temp0, 0b01000000	;AVCC refernce, PortC 0 - X
								; clear ADLAR for 10 bit conversion
		out ADMUX, temp0

;-- initialize all joystick axes
		;check if recalibration is needed

		ldi		temp3, 0
	; Read row 1
		sbi		DDRB,3
		cbi		PORTB,3
		rcall	ReadButtonsRow
		sbi		PORTB,3
		cbi		DDRB,3			;return to tristate
		add		temp3,temp0

	; Read row 2
		sbi		DDRB,4
		cbi		PORTB,4
		rcall	ReadButtonsRow
		sbi		PORTB,4
		cbi		DDRB,4			;return to tristate
		add		temp3,temp0

	;Read row 3
		sbi		DDRB,5
		cbi		PORTB,5
		rcall	ReadButtonsRow
		sbi		PORTB,5
		cbi		DDRB,5			;return to tristate
		add		temp3,temp0


	;Read row 4
		sbi		DDRD,7
		cbi		PORTD,7
		rcall	ReadButtonsRow
		sbi		PORTD,7
		cbi		DDRC,7			;return to tristate
		add		temp3,temp0

		tst		temp3
		brne	RecalibNeeded
		ldi		temp0, 0
		rjmp	Cont2
RecalibNeeded:
		ldi		temp0, 1
Cont2:
		sts		EEPROMFlags, temp0
		
		cbi EECR,EERIE
		rcall	InitJoystickAxis

		
		ldi	temp0,0x0F		;INT0 - respond to leading edge
		out	MCUCR,temp0		;
		ldi	temp0,1<<INT0		;enable external interrupt INT0
		out	GIMSK,temp0
;------------------------------------------------------------------------------------------
;********************************************************************
;*  Main program
;********************************************************************
		sei					;enable interrupts globally
Main:
		sbis	inputport,DATAminus	;waiting till change D- to 0
		rjmp	CheckUSBReset		;and check, if isn't USB reset

		cpi	ActionFlag,DoReceiveSetupData
		breq	ProcReceiveSetupData
		cpi	ActionFlag,DoPrepareOutContinuousBuffer
		breq	ProcPrepareOutContinuousBuffer
		sbrc	JoystickFlags,JoystickDataRequestBit
		rcall	ProcJoystickRequest
		
		rjmp	Main

⌨️ 快捷键说明

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