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

📄 mjoy.asm

📁 用于AVR的USB
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		ror		temp1			; get lowest bit to top
		andi	temp1,0b11100000
		or		temp3, temp1
		sts		JoystickBufferBegin+5,temp3 

;;;;;;;;;;;;;;;;;;;;;;;;;

; Process Hat switch
		mov		temp0, temp2
		lsl		temp0
		swap	temp0
		andi	temp0, 0b00001111
		ldi		ZH, high(HatValues << 1)
		ldi		ZL, low(HatValues << 1)
		ldi		temp1, 0
		add		ZL, temp0
		adc		ZH, temp1
		lpm		temp0, Z		; read value from memory mapping
		sts		JoystickBufferBegin+6,temp0 
		call 	RestoreUpperRegisters
		ldi		temp3,JoystickReport2Size		;Joystick report size

SendJoystickReport:
		ldi		temp0, JoystickReportID		; flip report ID
		eor		JoystickFlags, temp0

		rcall CheckAxisRanges

	; simulate call to AddCRCOut
	; simply push point of return onto stack
		ldi		temp0, low(AddCRCOutReturn)	;ROMpointer to descriptor
		push	temp0
		ldi		temp0,  high(AddCRCOutReturn)
		push	temp0
		
		
		ldi	USBBufptrY,JoystickBufferBegin
		ldi	ByteCount,2		;length of output buffer (only SOP and PID)
		add	ByteCount,temp3		;+ number of bytes
		push	USBBufptrY
		push	ByteCount
		rjmp	AddCRCOut_2		;addition of CRC to buffer


ReadButtonsRow:
		nop							; for synchronization
		in		temp0,PIND
		andi	temp0,0b01111011 	;mask out PD2 and PD7 which is INT0 and Column 4
		in		temp1,PINB
		andi	temp1,0b00000100	;extract bit PB2
		or 		temp0,temp1			;merge values
		com		temp0
		andi	temp0,0b01111111
		ret



;*********************************************************************		
;* Start the ADC conversion cycle
;*
;* Input: 	r18 	- number of ADC channel
;*
;* Registers used:
;*			r18
;*********************************************************************
StartADC10: 
		andi r18, 0b00000111
		sts	ADCChanStarted,r18	; set last ADC  channel number
		ori	 r18, 0b01000000	;AVCC refernce, clear ADLAR for 10 bit conversion
		out ADMUX, r18
		sbi		ADCSRA, ADSC	; start conversion
		ret

;*********************************************************************		
;* Read 10bit unsigned value from ADC
;*
;* Input: 	r16 	- number of ADC channel
;*
;* Output:	r17:r16	- 10bit ADC value
;* Registers used:
;*			r16, r17
;*********************************************************************
ReadADC10: 
		lds	r17, ADCChanStarted
		cp	r16, r17
		breq	WaitForADC10	; if conversion was started earlier then go and wait for the result
		andi r16, 0b00000111	; otherwise start the conversion
		ori	 r16, 0b01000000	;AVCC refernce, clear ADLAR for 10 bit conversion
		out ADMUX, r16
		sbi		ADCSRA, ADSC	; start conversion
WaitForADC10:
		sbic	ADCSRA, ADSC
		rjmp	WaitForADC10
		ldi r16, 0xFF
		sts	ADCChanStarted,r16	; reset last ADC  channel number
		in	r16,ADCL
		in	r17,ADCH
		ret






;*********************************************************************		
;* Initialize 8 bit asymmetrical Axis data from EEPROM
;*
;* Input: 	Z 		- address of 8 bit asymmetric axis structure
;*			Y	 	- EEPROM address
;*********************************************************************
Init8AsymAxis:

		; Reset Update Counter	
		ldi	r16,0
		std Z + s_UpdateCntL, r16
		std Z + s_UpdateCntH, r16
		lds	r16, EEPROMFlags
		tst	r16
		brne	LoadDefaults8

		; ADC Min
		movw	r19:r18, ZH:ZL 	; backup structure pointer
		movw	r21:r20, YH:YL 	; backup structure pointer
		adiw 	ZH:ZL, s_EEPROMStructStart	; point to start od EEPROM part
		ldi	r17, Asym8EEStructSize
		call LoadStructFromEEPROM

		movw ZH:ZL, r19:r18		; restore structure pointer
		movw YH:YL, r21:r20		; restore structure pointer

		; check if eeprom is valid
		ldd r16, Z + s_MaxH
		cpi	r16, 4
		brlo	RetInit8
		; out of range
		; load range defaults 
LoadDefaults8:
		ldi	r16, 0
		std Z + s_MaxL, r16
		std Z + s_MaxH, r16
		ldi r16, 3
		std Z + s_MinL, r16
		ldi r16, 0xFF
		std Z + s_MinH, r16

; Calculate Initial Coeficient
RetInit8:
		call CalcCoef
		ret




;*********************************************************************		
;* Initialize 10 bit symmetrical Axis data from EEPROM
;*
;* Input: 	R17:R16	- 10bit unsigned ADC input value (center)
;*			Z 		- address of 10 bit symmetric axis structure
;*			Y	 - EEPROM address
;*********************************************************************
Init10SymAxis:
		; store ADC Center value
		std Z + s_CenterH, r17
		std Z + s_CenterL, r16

		; Reset Update Counter	
		ldi	r16,0
		std Z + s_UpdateCntL, r16
		std Z + s_UpdateCntH, r16
		lds	r16, EEPROMFlags
		tst	r16
		brne	LoadDefaults10
	
		; ADC Min
		movw	r19:r18, ZH:ZL 	; backup structure pointer
		movw	r21:r20, YH:YL 	; backup structure pointer
		adiw 	ZH:ZL, s_EEPROMStructStart	; point to start od EEPROM part
		ldi	r17, Sym10EEStructSize
		call LoadStructFromEEPROM
		movw ZH:ZL, r19:r18		; restore structure pointer
		movw YH:YL, r21:r20		; restore structure pointer

		; check if eeprom is valid
		ldd r16, Z + s_MaxH
		cpi	r16, 4
		brlo	ContInit10
		; out of range

LoadDefaults10:
		; load range defaults 
		ldi	r16, 0
		std Z + s_MaxL, r16
		std Z + s_MaxH, r16
		ldi r16, 3
		std Z + s_MinL, r16
		ldi r16, 0xFF
		std Z + s_MinH, r16


ContInit10:

		ldd	r17, Z + s_CenterH
		ldd r16, Z + s_CenterL

		; Check if  Center is in the range and update accordingly
		; chek Lower Margin
		ldd r19, Z + s_MinH
		ldd r18, Z + s_MinL
		cp	r16, r18			; check if value exceeds  MINIMUM range
		cpc	r17, r19
		brsh	Init10Check_Max
		std Z + s_MinH, r17
		std Z + s_MinL, r16
		ldi r17, 0				; mark that update was made
		ldi	r16, 1
		std Z + s_UpdateCntH, r17
		std Z + s_UpdateCntL, r16


Init10Check_Max:
		ldd r19, Z + s_MaxH
		ldd r18, Z + s_MaxL
		cp	r18, r16		; check if value exceeds MAXIMUM  range
		cpc	r19, r17
		brsh	Init10Check_End
		std Z + s_MaxH, r17
		std Z + s_MaxL, r16
		ldi r17, 0				; mark that update was made
		ldi	r16, 1
		std Z + s_UpdateCntH, r17
		std Z + s_UpdateCntL, r16

		;call CalcPosCoef


Init10Check_End:


; Calculate Initial Coeficients
		call CalcNegCoef
		call CalcPosCoef
		ret

;************************************************************************
; Process 10 bit symmetric axis ADC value scaling it by appropriate coeficients
;
; Input: 	Z - address of 10 bit symmetric axis structure  (size = 10)
; 			r17:r16 - 10 bit unsigned value from ADC
; Output; 	r17:r16 - 10 bit signed value
;************************************************************************
Process10SymAxis:


; Step 1 : Check Min and Max ranges. If the value exceeds any of them update it 
									;and recalculate coeficients
		ldd r19, Z + s_MinH
		ldd r18, Z + s_MinL
		cp	r16, r18			; check if value exceeds  MINIMUM range
		cpc	r17, r19
		brsh	Check_Max
		std Z + s_MinH, r17
		std Z + s_MinL, r16
		sts  ADCValueH, r17 ; backup ADC value
		sts  ADCValueL, r16
		ldi r17, 0				; mark that update was made
		ldi	r16, 1
		std Z + s_UpdateCntH, r17
		std Z + s_UpdateCntL, r16
		call CalcNegCoef
		lds r17, ADCValueH	; restore ADC value
		lds r16, ADCValueL


Check_Max:
		ldd r19, Z + s_MaxH
		ldd r18, Z + s_MaxL
		cp	r18, r16		; check if value exceeds MAXIMUM  range
		cpc	r19, r17
		brsh	Check_End
		std Z + s_MaxH, r17
		std Z + s_MaxL, r16
		sts  ADCValueH, r17 ; backup ADC value
		sts  ADCValueL, r16
		ldi r17, 0				; mark that update was made
		ldi	r16, 1
		std Z + s_UpdateCntH, r17
		std Z + s_UpdateCntL, r16
		call CalcPosCoef
		lds r17, ADCValueH	; restore ADC value
		lds r16, ADCValueL

Check_End:
		
; Step 2 : Offset
		ldd r19, Z + s_CenterH
		ldd r18, Z + s_CenterL
		sub r16, r18		; subtract 16-bit center offset value
		sbc r17, r19


; Step 3 : Multiply by coeficient
		movw r23:r22, r17:r16
		sbrs r23,7
		rjmp TakePosCoef
		sbr	r25,128		; mark negative range

		; negate the number
		com	r22
		com r23
		subi r22, $FF
		sbci r23, $FF

		ldd r21, Z + s_NegCoefH	; negative range coeficient
		ldd r20, Z + s_NegCoefL
		rjmp MulCoef

TakePosCoef:
		cbr	r25,128		; mark positive range
		ldd r21, Z + s_PosCoefH	;positive range coeficient
		ldd r20, Z + s_PosCoefL

MulCoef:				
		call mul16x16_16

; Step 4: Divide by 128
		lsl r16		
		rol r17
		rol r18
		mov r16, r17
		mov r17, r18	; the result is in r17:r16 register
		andi	r17, 1
		sbrs r25,7			;check if value was negative
		rjmp Scaling_End

		; negate the number
		com	r16
		com r17
		subi r16, $FF
		sbci r17, $FF
		andi r17, $01		; make it 10bit signed value
		sbr	r17, 2
		
Scaling_End:

		; result is in r17:r16
		ret 


;************************************************************************
; Process 8 bit asymmetric axis ADC value scaling it by appropriate coeficients
;
; Input: 	Z - address of 8 bit ssymmetric axis structure (size = 6)
; 			r17:r16 - 10 bit unsigned value from ADC
; Output; 	r16 - 8 bit signed value
;************************************************************************
Process8AsymAxis:


; Step 1 : Check Min and Max ranges. If the value exceeds any of them update it 
									;and recalculate coeficients
		cbr	r20,	1 			; clear update bit
		ldd r19, Z + s_MinH
		ldd r18, Z + s_MinL
		cp	r16, r18			; check if value exceeds  MINIMUM range
		cpc	r17, r19
		brsh	Check_Max8
		std Z + s_MinH, r17
		std Z + s_MinL, r16
		sbr	r20, 	1		; update required



Check_Max8:
		ldd r19, Z + s_MaxH
		ldd r18, Z + s_MaxL
		cp	r18, r16		; check if value exceeds MAXIMUM  range
		cpc	r19, r17
		brsh	Check_End8
		std Z + s_MaxH, r17
		std Z + s_MaxL, r16
		sbr	r20, 	1		; update required

Check_End8:
		sbrs	r20,0		; skip recalculation if update is not required
		rjmp	Proc8Offset
		sts  ADCValueH, r17 ; backup ADC value
		sts  ADCValueL, r16
		ldi r17, 0				; mark that update was made
		ldi	r16, 1
		std Z + s_UpdateCntH, r17
		std Z + s_UpdateCntL, r16
		call CalcCoef
		lds r17, ADCValueH	; restore ADC value
		lds r16, ADCValueL
		
; Step 2 : Offset

Proc8Offset:
		ldd r19, Z + s_MinH
		ldd r18, Z + s_MinL
		sub r16, r18		; subtract 16-bit minimum value
		sbc r17, r19


; Step 3 : Multiply by coeficient
		movw r23:r22, r17:r16
		ldd r21, Z + s_CoefH	; range coeficient
		ldd r20, Z + s_CoefL
		movw	r19:r18, r1:r0	; backup r1, r0
		call mul16x16_16
		mov r16, r17	; the result is in r16 register
		movw	r1:r0, r19:r18	; restore r1, r0
		; result is 8 bit signed value in r16 register
		subi	r16, 128
		ret 


;************************************************************************
; Process 10 bit asymmetric axis ADC value scaling it by appropriate coeficients
;
; Input: 	Z - address of 8 bit ssymmetric axis structure (size = 6)
; 			r17:r16 - 10 bit unsigned value from ADC
; Output; 	r17:r16 - 10 bit signed value
;************************************************************************
Process10AsymAxis:


; Step 1 : Check Min and Max ranges. If the value exceeds any of them update it 
									;and recalculate coeficients
		cbr	r20,	1 			; clear update bit
		ldd r19, Z + s_MinH
		ldd r18, Z + s_MinL
		cp	r16, r18			; check if value exceeds  MINIMUM range
		cpc	r17, r19
		brsh	Check_MaxA10
		std Z + s_MinH, r17
		std Z + s_MinL, r16
		sbr	r20, 	1		; update required

⌨️ 快捷键说明

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