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

📄 mjoy.asm

📁 用于AVR的USB
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		pop	R26
		pop	temp3
		pop	temp2
EndInt0HandlerPOP:
		pop	USBBufptrY
		pop	ByteCount
		mov	bitcount,backupbitcount	;restore bitcount register
EndInt0HandlerPOP2:
		pop	temp1
		pop	temp0
		out	SREG,backupSREG
		ldi	shiftbuf,1<<INTF0	;zero interruptu flag INTF0
		out	GIFR,shiftbuf
		reti				;otherwise finish (was only SOF - every millisecond)

USBBeginPacket:
		mov	backupbitcount,bitcount	;backup bitcount register
		in	shiftbuf,inputport	;if yes load it as zero bit directly to shift register
USBloopBegin:
		push	ByteCount		;additional backup of registers (save of time)
		push	USBBufptrY
		ldi	bitcount,6		;initialization of bits counter in byte
		ldi	ByteCount,MAXUSBBYTES	;initialization of max number of received bytes in packet
		ldi	USBBufptrY,InputShiftBufferBegin	;set the input buffer
USBloop1_6:
		in	inputbuf,inputport
		cbr	inputbuf,USBpinmask	;unmask low 2 bits
		breq	USBloopEnd		;if they are zeros - end of USB packet
		ror	inputbuf		;transfer Data+ to shift register
		rol	shiftbuf
		dec	bitcount		;decrement bits counter
		brne	USBloop1_6		;if it isn't zero - repeat filling of shift register
		nop				;otherwise is necessary copy shift register to buffer
USBloop7:
		in	inputbuf,inputport
		cbr	inputbuf,USBpinmask	;unmask low 2 bits
		breq	USBloopEnd		;if they are zeros - end of USB packet
		ror	inputbuf		;transfer Data+ to shift register
		rol	shiftbuf
		ldi	bitcount,7		;initialization of bits counter in byte
		st	Y+,shiftbuf		;copy shift register into buffer and increment pointer to buffer
USBloop0:					;and start receiving next byte
		in	shiftbuf,inputport	;zero bit directly to shift register
		cbr	shiftbuf,USBpinmask	;unmask low 2 bits
		breq	USBloopEnd		;if they are zeros - end of USB packet
		dec	bitcount		;decrement bits counter
		nop				;
		dec	ByteCount		;if not reached maximum buffer
		brne	USBloop1_6		;then receive next

		rjmp	EndInt0HandlerPOP	;otherwise repeat back from begin

USBloopEnd:
		cpi	USBBufptrY,InputShiftBufferBegin+3	;if at least 3 byte not received
		brcs	EndInt0HandlerPOP	;then finish
		lds	temp0,InputShiftBufferBegin+0	;identifier of packet to temp0
		lds	temp1,InputShiftBufferBegin+1	;address to temp1
		brne	TestDataPacket		;if is length different from 3 - then this can be only DataPaket
TestIOPacket:
	
		andi	temp1,0xFE		;MMM mask out bit 0 of address to avoid conflict with endpoint 1
	
		cp	temp1,MyAddress		;if this isn't assigned (address) for me 
		brne	TestDataPacket		;then this can be still DataPacket
TestSetupPacket:			;test to SETUP packet
		cpi	temp0,nNRZISETUPPID
		brne	TestOutPacket		;if this isn't Setup PID - decode other packet
		ldi	State,SetupState
		rjmp	EndInt0HandlerPOP	;if this is Setup PID - receive consecutive Data packet
TestOutPacket:				;test for OUT packet
		cpi	temp0,nNRZIOUTPID
		brne	TestInPacket		;if this isn't Out PID - decode other packet
		ldi	State,OutState
		rjmp	EndInt0HandlerPOP	;if this is Out PID - receive consecutive Data packet
TestInPacket:				;test on IN packet
		cpi	temp0,nNRZIINPID
		brne	TestDataPacket		;if this isn't In PID - decode other packet
		rjmp	AnswerToInRequest
TestDataPacket:				;	test for DATA0 and DATA1 packet
		cpi	temp0,nNRZIDATA0PID
		breq	Data0Packet		;if this isn't Data0 PID - decode other packet
		cpi	temp0,nNRZIDATA1PID
		brne	NoMyPacked		;if this isn't Data1 PID - decode other packet
Data0Packet:
		cpi	State,SetupState	;if was state Setup
		breq	ReceiveSetupData	;receive it
		cpi	State,OutState		;if was state Out
		breq	ReceiveOutData		;receive it
NoMyPacked:
		ldi	State,BaseState		;zero state
		rjmp	EndInt0HandlerPOP	;and receive consecutive Data packet

AnswerToInRequest:
		push	temp2			;backup next registers and continue
		push	temp3
		push	R26
		push	ACC


; this might be  Endpoint1 interrupt query
		lds		temp1,InputShiftBufferBegin+1	;address to temp1
		lds		temp2,InputShiftBufferBegin+2	;endpoint and CRC to temp2
		
		ror		temp1 ; move bit 0 to carry
		ror		temp2 ; bring bit 7 to carry
		swap	temp2
		sbrs	temp1, 0	; check bit 1 (6) of address
		rjmp	AddrBit6Zero
		com		temp2
AddrBit6Zero:
		andi	temp2, 0x0F
		cpi		temp2, 0x0A
		breq	ProcessEndpoint0
		cpi		temp2, 0x05
		breq	ProcessEndpoint1
		rjmp 	EndInt0Handler


ProcessEndpoint0:
		cpi		ActionFlag,DoReadySendAnswer	;if isn't prepared answer
		brne	NoReadySend		;then send NAK
		rcall	SendPreparedUSBAnswer	;transmitting answer back
		and		MyUpdatedAddress,MyUpdatedAddress	;if is MyUpdatedAddress nonzero
		brne	SetMyNewUSBAddress_2	;then is necessary to change USB address
		ldi		State,InState
		ldi		ActionFlag,DoPrepareOutContinuousBuffer
		rjmp	EndInt0Handler		;and repeat - wait for next response from USB
ReceiveSetupData:
		push	temp2			;backup next registers and continue
		push	temp3
		push	R26
		push	ACC
		rcall	SendACK			;accept Setup Data packet
		rcall	FinishReceiving		;finish receiving
		ldi		ActionFlag,DoReceiveSetupData
		rjmp	EndInt0Handler
ReceiveOutData:
		push	temp2			;backup next registers and continue
		push	temp3
		push	R26
		push	ACC
		cpi		ActionFlag,DoReceiveSetupData	;if is currently in process command Setup
		breq	NoReadySend		;then send NAK
		rcall	SendACK			;accept Out packet
		clr		ActionFlag
		rjmp	EndInt0Handler
NoReadySend:
		rcall	SendNAK			;still I am not ready to answer
		rjmp	EndInt0Handler		;and repeat - wait for next response from USB

SetMyNewUSBAddress_2:
		rjmp SetMyNewUSBAddress








;*******************************************************************************************
;*
;*	 ENDPOINT 1
;*
;*******************************************************************************************

ProcessEndpoint1:		; on Endpoint1 In we have interrupt handler which is sending reports of joystick data


	; Check if we have joystick data ready
		sbrs	JoystickFlags, JoystickDataReadyBit
		rjmp	NoJoystickDataReady

	; Backup Control pipe buffer pointers to save Control pipe state
		mov	temp0, OutputBufferLength
		sts BkpOutputBufferLength,temp0

		mov temp0, OutBitStuffNumber
		sts BkpOutBitStuffNumber,temp0



	; Retrieve Joystick buffer parameters
		lds 	temp0,JoyOutBitStuffNumber
		mov 	OutBitStuffNumber, temp0

		lds		ByteCount,JoyOutputBufferLength		;length of answer
		ldi		USBBufptrY,JoystickBufferBegin		;pointer to start of transmition buffer
		rcall	SendUSBBuffer	


	; Restore Control pipe buffer pointers
		lds		temp0, BkpOutputBufferLength
		mov		OutputBufferLength, temp0
		lds		temp0, BkpOutBitStuffNumber
		mov		 OutBitStuffNumber,temp0

		; flip data PID
		lds		temp0, JoystickBufferBegin + 1
		cpi		temp0, DATA0PID
		breq	FlipToDATA1PID
		ldi		temp0, DATA0PID
		rjmp	FlipDone
FlipToDATA1PID:
		ldi		temp0, DATA1PID
FlipDone:
		sts		JoystickBufferBegin + 1,temp0

		ldi		temp0,JoystickDataRequest
		or		JoystickFlags,temp0 ;JoystickDataRequest	; request new joystick data

		rjmp	EndInt0Handler		;and complete

NoJoystickDataReady:
	;  	rcall	SendNAK			;still I am not ready to answer
  	  	rjmp	EndInt0Handler		;and repeat - wait for next response from USB
	

;--END--ENDPOINT1





;------------------------------------------------------------------------------------------
SetMyNewUSBAddress:		;set new USB address in NRZI coded
		clr	MyAddress		;original answer state - of my nNRZI USB address
		ldi	temp2,0b00000001	;mask for xoring
		ldi	temp3,8			;bits counter
SetMyNewUSBAddressLoop:
		mov	temp0,MyAddress		;remember final answer
		ror	MyUpdatedAddress	;to carry transmitting bit LSB (in direction firstly LSB then MSB)
		brcs	NoXORBit		;if one - don't change state
		eor	temp0,temp2		;otherwise state will be changed according to last bit of answer
NoXORBit:
		ror	temp0			;last bit of changed answer to carry
		rol	MyAddress		;and from carry to final answer to the LSB place (and reverse LSB and MSB order)
		dec	temp3			;decrement bits counter
		brne	SetMyNewUSBAddressLoop	;if bits counter isn't zero repeat transmitting with next bit
		clr	MyUpdatedAddress	;zero addresses as flag of its next unchanging
		
		; mask out bit 0 to avoid conflict with endpoints
		mov	temp2, MyAddress
		andi	temp2,0xFE
		mov MyAddress, temp2

		rjmp	EndInt0Handler
;------------------------------------------------------------------------------------------
FinishReceiving:		;corrective actions for receive termination
		cpi	bitcount,7		;transfer to buffer also last not completed byte
		breq	NoRemainingBits		;if were all bytes transfered, then nothing transfer
		inc	bitcount
ShiftRemainingBits:
		rol	shiftbuf		;shift remaining not completed bits on right position
		dec	bitcount
		brne	ShiftRemainingBits
		st	Y+,shiftbuf		;and copy shift register bo buffer - not completed byte
NoRemainingBits:
		mov	ByteCount,USBBufptrY
		subi	ByteCount,InputShiftBufferBegin-1	;in ByteCount is number of received bytes (including not completed bytes)

		mov	InputBufferLength,ByteCount		;and save for use in main program
		ldi	USBBufptrY,InputShiftBufferBegin	;pointer to begin of receiving shift buffer
		ldi	R26,InputBufferBegin+1		;data buffer (leave out SOP)
		push	XH					;save RS232BufptrX Hi index
		clr	XH
MoveDataBuffer:
		ld	temp0,Y+
		st	X+,temp0
		dec	ByteCount
		brne	MoveDataBuffer

		pop	XH					;restore RS232BufptrX Hi index
		ldi	ByteCount,nNRZISOPbyte
		sts	InputBufferBegin,ByteCount		;like received SOP - it is not copied from shift buffer
		ret
;------------------------------------------------------------------------------------------
;********************************************************************
;*  Other procedures
;********************************************************************
;------------------------------------------------------------------------------------------
USBReset:		;iinitialization of USB state engine
		ldi	temp0,nNRZIADDR0	;initialization of USB address
		mov	MyAddress,temp0
		clr	State			;initialization of state engine
		clr	BitStuffInOut
		clr	OutBitStuffNumber
		clr	ActionFlag
		clr	RAMread			;will be reading from ROM
		sts	ConfigByte,RAMread	;unconfigured state
		ret
;------------------------------------------------------------------------------------------
SendPreparedUSBAnswer:	;transmitting by NRZI coding OUT buffer with length OutputBufferLength to USB
		mov	ByteCount,OutputBufferLength		;length of answer
SendUSBAnswer:	;transmitting by NRZI coding OUT buffer to USB
		ldi	USBBufptrY,OutputBufferBegin		;pointer to begin of transmitting buffer
SendUSBBuffer:	;transmitting by NRZI coding given buffer to USB
		ldi	temp1,0			;incrementing pointer (temporary variable)
		mov	temp3,ByteCount		;byte counter: temp3 = ByteCount
		ldi	temp2,0b00000011	;mask for xoring
		ld	inputbuf,Y+		;load first byte to inputbuf and increment pointer to buffer
						;USB as output:
		cbi	outputport,DATAplus	;down DATAPLUS : idle state of USB port
		sbi	outputport,DATAminus	;set DATAMINUS : idle state of USB port
		sbi	USBdirection,DATAplus	;DATAPLUS as output
		sbi	USBdirection,DATAminus	;DATAMINUS as output

		in	temp0,outputport	;idle state of USB port to temp0
SendUSBAnswerLoop:
		ldi	bitcount,7		;bits counter
SendUSBAnswerByteLoop:
		nop				;delay because timing
		ror	inputbuf		;to carry transmiting bit (in direction first LSB then MSB)
		brcs	NoXORSend		;if that it is one - don't change USB state
		eor	temp0,temp2		;iotherwise state will be changed
NoXORSend:
		out	outputport,temp0	;send out to USB
		dec	bitcount		;decrement bits counter - according to carry flag
		brne	SendUSBAnswerByteLoop	; if bits counter isn't zero - repeat transmiting with next bit
		sbrs	inputbuf,0		;if is transmiting bit one - don't change USB state
		eor	temp0,temp2		;otherwise state will be changed
NoXORSendLSB:
		dec	temp3			;decrement bytes counter
		ld	inputbuf,Y+		;load next byte and increment pointer to buffer
		out	outputport,temp0	;transmit to USB
		brne	SendUSBAnswerLoop	;repeat for all buffer (till temp3=0)

		mov	bitcount,OutBitStuffNumber	;bits counter for bitstuff
		cpi	bitcount,0		;if not be needed bitstuff
		breq	ZeroBitStuf
SendUSBAnswerBitstuffLoop:
		ror	inputbuf		;to carry transmiting bit (in direction first LSB then MSB)
		brcs	NoXORBitstuffSend	;if is one - don't change state on USB
		eor	temp0,temp2		;otherwise state will be changed
NoXORBitstuffSend:
		out	outputport,temp0	;transmit to USB
		nop				;delay because of timing
		dec	bitcount		;decrement bits counter - according to carry flag
		brne	SendUSBAnswerBitstuffLoop	;if bits counter isn't zero - repeat transmiting with next bit
		ld	inputbuf,Y		;delay 2 cycle
ZeroBitStuf:
		nop				;delay 1 cycle
		cbr	temp0,3
		out	outputport,temp0	;transmit EOP on USB
		
		ldi	bitcount,5		;delay counter: EOP shouls exists 2 bits (16 cycle at 12MHz)
SendUSBWaitEOP:
		dec	bitcount
		brne	SendUSBWaitEOP
		
		sbi	outputport,DATAminus	;set DATAMINUS : idle state on USB port
		sbi	outputport,DATAminus	;delay 2 cycle: Idle should exists 1 bit (8 cycle at 12MHz)
		cbi	USBdirection,DATAplus	;DATAPLUS as input
		cbi	USBdirection,DATAminus	;DATAMINUS as input
		cbi	outputport,DATAminus	;reset DATAMINUS : the third state on USB port
		ret
;------------------------------------------------------------------------------------------
ToggleDATAPID:
		lds	temp0,OutputBufferBegin+1	;load last PID
		cpi	temp0,DATA1PID			;if last was DATA1PID byte
		ldi	temp0,DATA0PID
		breq	SendData0PID			;then send zero answer with DATA0PID
		ldi	temp0,DATA1PID			;otherwise send zero answer with DATA1PID
SendData0PID:
		sts	OutputBufferBegin+1,temp0	;DATA0PID byte
		ret
;------------------------------------------------------------------------------------------
ComposeZeroDATA1PIDAnswer:
		ldi	temp0,DATA0PID			;DATA0 PID - in the next will be toggled to DATA1PID in load descriptor
		sts	OutputBufferBegin+1,temp0	;load to output buffer
ComposeZeroAnswer:
		ldi	temp0,SOPbyte
		sts	OutputBufferBegin+0,temp0	;SOP byte
		rcall	ToggleDATAPID			;change DATAPID
		ldi	temp0,0x00
		sts	OutputBufferBegin+2,temp0	;CRC byte
		sts	OutputBufferBegin+3,temp0	;CRC byte
		ldi	ByteCount,2+2			;length of output buffer (SOP and PID + CRC16)
		ret
;------------------------------------------------------------------------------------------

;------------------------------------------------------------------------------------------
InitJoystickBufffer:

;		ldi	ZH, high(JoystickAnswer<<1)	;ROMpointer to answer
;		ldi	ZL,  low(JoystickAnswer<<1)
		ldi	temp0,JoystickReport1Size				;number of my bytes answers to temp0

		mov TotalBytesToSend, temp0

		ldi	temp0,SOPbyte
		sts	OutputBufferBegin+0,temp0		;SOP byte
		ldi	temp0,DATA0PID
		sts	OutputBufferBegin+1,temp0		;DATA0PID byte


		mov	temp3,TotalBytesToSend	;otherwise send only given number of bytes
		mov ByteCount,TotalBytesToSend;

		ldi	USBBufptrY,OutputBufferBegin+2	;to transmitting buffer
LoadDescriptorFromROM_2:
		lpm				;load from ROM position pointer to R0 <- (ZH:ZL)
		st	Y+,R0			;R0 save to buffer and increment buffer (Y) <- R0, Y++
		adiw	ZH:ZL,1			;increment index to ROM ; Z++
		dec	ByteCount		;till are not all bytes
		brne	LoadDescriptorFromROM_2	;then load next

		ldi	ByteCount,2		;length of output buffer (only SOP and PID)
		add	ByteCount,temp3		;+ number of bytes
	rcall	AddCRCOut		;addition of CRC to buffer
		inc	ByteCount		;length of output buffer + CRC16
		inc	ByteCount


		inc	BitStuffInOut			;transmitting buffer - insertion of bitstuff bits
		ldi	USBBufptrY,OutputBufferBegin	;to transmitting buffer
	rcall	BitStuff
		mov	OutputBufferLength,ByteCount	;length of answer store for transmiting
		clr	BitStuffInOut			;receiving buffer - deletion of bitstuff bits



	; copy to Joystick buffer
		sts JoyOutputBufferLength, OutputBufferLength
		sts JoyOutBitStuffNumber, OutBitStuffNumber

		mov	ByteCount, OutputBufferLength
	;	ldi	ZH, high(OutputBufferBegin<<1)	;pointer to answer
		clr ZH
		ldi	ZL,  OutputBufferBegin
		ldi	USBBufptrY,JoystickBufferBegin	;to transmitting buffer
CopyToJoyBufferLoop:
		ld	R0, Z+				;load from RAM position pointer to R0 <- (ZH:ZL)
		st	Y+,R0			;R0 save to buffer and increment buffer (Y) 

⌨️ 快捷键说明

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