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

📄 usb90s23x3.asm

📁 单片机AT90S系列 制作简易USB接口(软件模拟,无usb硬件)。asm源代码
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		ret
;------------------------------------------------------------------------------------------
InitCounter:		;inicializacia countera na prijem zmeny z TSOP
		ldi		temp0,6			;na zostupnu hranu casovaca - externy pin
		out		TCCR0,temp0
		ldi		temp0,0xFF		;napln citac naplno - aby hned na nasledujucu hranu pretiekol
		out		TCNT0,temp0
		ldi		temp0,1<<TOV0		;znuluj pripadny cakajuci flag pretecenia citaca
		out		TIFR,temp0
		ldi		temp0,1<<TOIE0		;povolit interrupt od casovaca
	;cli				;zakaz interrupt kvoli zacykleniu
		out		TIMSK,temp0
		ret
;------------------------------------------------------------------------------------------
SendPreparedUSBAnswer:	;poslanie kodovanim NRZI OUT buffer s dlzkou OutputBufferLength do USB
		mov		ByteCount,OutputBufferLength		;dlzka odpovede
SendUSBAnswer:	;poslanie kodovanim NRZI OUT buffer do USB
		ldi		USBBufptrY,OutputBufferBegin		;pointer na zaciatok vysielacieho buffera
SendUSBBuffer:	;poslanie kodovanim NRZI dany buffer do USB
		ldi		temp1,0			;zvysovanie pointra (pomocna premenna)
		mov		temp3,ByteCount		;pocitadlo bytov: temp3 = ByteCount
		ldi		temp2,0b00000011	;maska na xorovanie
		ld		inputbuf,Y+		;nacitanie prveho bytu do inputbuf a zvys pointer do buffera
						;USB ako vystup:
		cbi		outputport,DATAplus	;zhodenie DATAplus : kludovy stav portu USB
		sbi		outputport,DATAminus	;nahodenie DATAminus : kludovy stav portu USB
		sbi		USBdirection,DATAplus	;DATAplus ako vystupny
		sbi		USBdirection,DATAminus	;DATAminus ako vystupny

		in		temp0,outputport	;kludovy stav portu USB do temp0
SendUSBAnswerLoop:
		ldi		bitcount,7		;pocitadlo bitov
SendUSBAnswerByteLoop:
		nop				;oneskorenie kvoli casovaniu
		ror		inputbuf		;do carry vysielany bit (v smere naskor LSB a potom MSB)
		brcs	NoXORSend		;ak je jedna - nemen stav na USB
		eor		temp0,temp2		;inak sa bude stav menit
NoXORSend:
		out		outputport,temp0	;vysli von na USB
		dec		bitcount		;zmensi pocitadlo bitov - podla carry flagu
		brne	SendUSBAnswerByteLoop	;ak pocitadlo bitov nie je nulove - opakuj vysielanie s dalsim bitom
		sbrs	inputbuf,0		;ak je vysielany bit jedna - nemen stav na USB
		eor		temp0,temp2		;inak sa bude stav menit
NoXORSendLSB:
		dec		temp3			;zniz pocitadlo bytov
		ld		inputbuf,Y+		;nacitanie dalsieho bytu a zvys pointer do buffera
		out		outputport,temp0	;vysli von na USB
		brne	SendUSBAnswerLoop	;opakuj pre cely buffer (pokial temp3=0)

		mov		bitcount,OutBitStuffNumber	;pocitadlo bitov pre bitstuff
		cpi		bitcount,0		;ak nie je potrebny bitstuff
		breq	ZeroBitStuf
SendUSBAnswerBitstuffLoop:
		ror		inputbuf		;do carry vysielany bit (v smere naskor LSB a potom MSB)
		brcs	NoXORBitstuffSend	;ak je jedna - nemen stav na USB
		eor		temp0,temp2		;inak sa bude stav menit
NoXORBitstuffSend:
		out		outputport,temp0	;vysli von na USB
		nop				;oneskorenie kvoli casovaniu
		dec		bitcount		;zmensi pocitadlo bitov - podla carry flagu
		brne	SendUSBAnswerBitstuffLoop	;ak pocitadlo bitov nie je nulove - opakuj vysielanie s dalsim bitom
		ld		inputbuf,Y		;oneskorenie 2 cykly
ZeroBitStuf:
		nop				;oneskorenie 1 cyklus
		cbr		temp0,3
		out		outputport,temp0	;vysli EOP na USB
		
		ldi		bitcount,5		;pocitadlo oneskorenia: EOP ma trvat 2 bity (16 cyklov pri 12MHz)
SendUSBWaitEOP:
		dec		bitcount
		brne	SendUSBWaitEOP
		
		sbi		outputport,DATAminus	;nahodenie DATAminus : kludovy stav na port USB
		sbi		outputport,DATAminus	;oneskorenie 2 cykly: Idle ma trvat 1 bit (8 cyklov pri 12MHz)
		cbi		USBdirection,DATAplus	;DATAplus ako vstupny
		cbi		USBdirection,DATAminus	;DATAminus ako vstupny
		cbi		outputport,DATAminus	;zhodenie DATAminus : treti stav na port USB
		ret
;------------------------------------------------------------------------------------------
ToggleDATAPID:
		lds		temp0,OutputBufferBegin+1	;nahraj posledne PID
		cpi		temp0,DATA1PID			;ak bolo posledne DATA1PID byte
		ldi		temp0,DATA0PID
		breq	SendData0PID			;tak posli nulovu odpoved s DATA0PID
		ldi		temp0,DATA1PID			;inak posli nulovu odpoved s DATA1PID
SendData0PID:
		sts		OutputBufferBegin+1,temp0	;DATA0PID byte
		ret
;------------------------------------------------------------------------------------------
ComposeZeroDATA1PIDAnswer:
		ldi		temp0,DATA0PID			;DATA0 PID - v skutocnosti sa stoggluje na DATA1PID v nahrati deskriptora
		sts		OutputBufferBegin+1,temp0	;nahraj do vyst buffera
ComposeZeroAnswer:
		ldi		temp0,SOPbyte
		sts		OutputBufferBegin+0,temp0	;SOP byte
		rcall	ToggleDATAPID			;zmen DATAPID
		ldi		temp0,0x00
		sts		OutputBufferBegin+2,temp0	;CRC byte
		sts		OutputBufferBegin+3,temp0	;CRC byte
		ldi		ByteCount,2+2			;dlzka vystupneho buffera (SOP a PID + CRC16)
		ret
;------------------------------------------------------------------------------------------
InitACKBufffer:
		ldi		temp0,SOPbyte
		sts		ACKBufferBegin+0,temp0		;SOP byte
		ldi		temp0,ACKPID
		sts		ACKBufferBegin+1,temp0		;ACKPID byte
		ret
;------------------------------------------------------------------------------------------
SendACK:
		push	USBBufptrY
		push	bitcount
		push	OutBitStuffNumber
		ldi		USBBufptrY,ACKBufferBegin	;pointer na zaciatok ACK buffera
		ldi		ByteCount,2			;pocet vyslanych bytov (iba SOP a ACKPID)
		clr		OutBitStuffNumber
		rcall	SendUSBBuffer
		pop		OutBitStuffNumber
		pop		bitcount
		pop		USBBufptrY
		ret
;------------------------------------------------------------------------------------------
InitNAKBufffer:
		ldi		temp0,SOPbyte
		sts		NAKBufferBegin+0,temp0		;SOP byte
		ldi		temp0,NAKPID
		sts		NAKBufferBegin+1,temp0		;NAKPID byte
		ret
;------------------------------------------------------------------------------------------
SendNAK:
		push	OutBitStuffNumber
		ldi		USBBufptrY,NAKBufferBegin	;pointer na zaciatok ACK buffera
		ldi		ByteCount,2			;pocet vyslanych bytov (iba SOP a NAKPID)
		clr		OutBitStuffNumber
		rcall	SendUSBBuffer
		pop		OutBitStuffNumber
		ret
;------------------------------------------------------------------------------------------
ComposeSTALL:
		ldi		temp0,SOPbyte
		sts		OutputBufferBegin+0,temp0	;SOP byte
		ldi		temp0,STALLPID
		sts		OutputBufferBegin+1,temp0	;STALLPID byte
		ldi		ByteCount,2			;dlzka vystupneho buffera (SOP a PID)
		ret
;------------------------------------------------------------------------------------------
DecodeNRZI:	;enkodovanie buffera z NRZI kodu do binarneho
		push	USBBufptrY		;zalohuj pointer do buffera
		push	ByteCount		;zalohuj dlzku buffera
		add		ByteCount,USBBufptrY	;koniec buffera do ByteCount
		ser		temp0			;na zabezpecenie jednotkoveho carry (v nasledujucej rotacii)
NRZIloop:
		ror		temp0			;naplnenie carry z predchadzajuceho byte
		ld		temp0,Y			;nahraj prijaty byte z buffera
		mov		temp2,temp0		;posunuty register o jeden bit vpravo a XOR na funkciu NRZI dekodovania
		ror		temp2			;carry do najvyssieho bitu a sucasne posuv
		eor		temp2,temp0		;samotne dekodovanie NRZI
		com		temp2			;negovanie
		st		Y+,temp2		;ulozenie spat ako dekodovany byte a zvys pointer do buffera
		cp		USBBufptrY,ByteCount	;ak este neboli vsetky
		brne	NRZIloop		;tak opakuj
		pop		ByteCount		;obnov dlzku buffera
		pop		USBBufptrY		;obnov pointer do buffera
		ret				;inak skonci
;------------------------------------------------------------------------------------------
BitStuff:	;odstranenie bit-stuffingu v buffri
		clr		temp3			;pocitadlo vynechanych bitov
		clr		lastBitstufNumber	;0xFF do lastBitstufNumber
		dec		lastBitstufNumber
BitStuffRepeat:
		push	USBBufptrY		;zalohuj pointer do buffera
		push	ByteCount		;zalohuj dlzku buffera
		mov		temp1,temp3		;pocitadlo vsetkych bitov
		ldi		temp0,8			;spocitat vsetky bity v bufferi
SumAllBits:
		add		temp1,temp0
		dec		ByteCount
		brne	SumAllBits
		ldi		temp2,6			;inicializuj pocitadlo jednotiek
		pop		ByteCount		;obnov dlzku buffera
		push	ByteCount		;zalohuj dlzku buffera
		add		ByteCount,USBBufptrY	;koniec buffera do ByteCount
		inc		ByteCount		;a pre istotu ho zvys o 2 (kvoli posuvaniu)
		inc		ByteCount
BitStuffLoop:
		ld		temp0,Y			;nahraj prijaty byte z buffera
		ldi		bitcount,8		;pocitadlo bitov v byte
BitStuffByteLoop:
		ror		temp0			;naplnenie carry z LSB
		brcs	IncrementBitstuff	;ak LSB=0
		ldi		temp2,7			;inicializuj pocitadlo jednotiek +1 (ak bola nula)
IncrementBitstuff:
		dec		temp2			;zniz pocitadlo jednotiek (predpoklad jednotkoveho bitu)
		brne	NeposunBuffer		;ak este nebolo 6 jednotiek za sebou - neposun buffer
		cp		temp1,lastBitstufNumber	;
		ldi		temp2,6			;inicializuj pocitadlo jednotiek (ak by sa nerobil bitstuffing tak sa musi zacat odznova)
		brcc	NeposunBuffer		;ak sa tu uz robil bitstuffing - neposun buffer

		dec		temp1
		mov		lastBitstufNumber,temp1	;zapamataj si poslednu poziciu bitstuffingu
		cpi		bitcount,1		;aby sa ukazovalo na 7 bit (ktory sa ma vymazat alebo kde sa ma vlozit nula)
		brne	NoBitcountCorrect
		ldi		bitcount,9
		inc		USBBufptrY		;zvys pointer do buffera
NoBitcountCorrect:
		dec		bitcount
		bst		BitStuffInOut,0
		brts	CorrectOutBuffer	;ak je Out buffer - zvys dlzku buffera
		rcall	PosunDeleteBuffer	;posun In buffer
		dec		temp3			;zniz pocitadlo vynechani
		rjmp	CorrectBufferEnd
CorrectOutBuffer:
		rcall	PosunInsertBuffer	;posun Out buffer
		inc		temp3			;zvys pocitadlo vynechani
CorrectBufferEnd:
		pop		ByteCount		;obnov dlzku buffera
		pop		USBBufptrY		;obnov pointer do buffera
		rjmp	BitStuffRepeat		;a restartni od zaciatku
NeposunBuffer:
		dec		temp1			;ak uz boli vsetky bity
		breq	EndBitStuff		;ukonci cyklus
		dec		bitcount		;zniz pocitadlo bitov v byte
		brne	BitStuffByteLoop	;ak este neboli vsetky bity v byte - chod na dalsi bit
						;inak nahraj dalsi byte
		inc		USBBufptrY		;zvys pointer do buffera
		rjmp	BitStuffLoop		;a opakuj
EndBitStuff:
		pop		ByteCount		;obnov dlzku buffera
		pop		USBBufptrY		;obnov pointer do buffera
		bst		BitStuffInOut,0
		brts	IncrementLength		;ak je Out buffer - zvys dlzku Out buffera
DecrementLength:				;ak je In buffer - zniz dlzku In buffera
		cpi		temp3,0			;bolo aspon jedno znizenie
		breq	NoChangeByteCount	;ak nie - nemen dlzku buffera
		dec		ByteCount		;ak je In buffer - zniz dlzku buffera
		subi	temp3,256-8		;ak nebolo viac ako 8 bitov naviac
		brcc	NoChangeByteCount	;tak skonci
		dec		ByteCount		;inak este zniz dlzku buffera
		ret				;a skonci
IncrementLength:
		mov		OutBitStuffNumber,temp3	;zapamataj si pocet bitov naviac
		subi	temp3,8			;ak nebolo viac ako 8 bitov naviac
		brcs	NoChangeByteCount	;tak skonci
		inc		ByteCount		;inak zvys dlzku buffera
		mov		OutBitStuffNumber,temp3	;a zapamataj si pocet bitov naviac (znizene o 8)
NoChangeByteCount:
		ret				;skonci
;------------------------------------------------------------------------------------------
PosunInsertBuffer:	;posuv buffera o jeden bit vpravo od konca az po poziciu: byte-USBBufptrY a bit-bitcount
		mov		temp0,bitcount		;vypocet: bitcount= 9-bitcount
		ldi		bitcount,9
		sub		bitcount,temp0		;do bitcount poloha bitu, ktory treba nulovat

		ld		temp1,Y			;nahraj byte ktory este treba posunut od pozicie bitcount
		rol		temp1			;a posun vlavo cez Carry (prenos z vyssieho byte a LSB do Carry)
		ser		temp2			;FF do masky - temp2
HalfInsertPosuvMask:
		lsl		temp2			;nula do dalsieho spodneho bitu masky
		dec		bitcount		;az pokial sa nedosiahne hranica posuvania v byte
		brne	HalfInsertPosuvMask
		
		and		temp1,temp2		;odmaskuj aby zostali iba vrchne posunute bity v temp1
		com		temp2			;invertuj masku
		lsr		temp2			;posun masku vpravo - na vlozenie nuloveho bitu
		ld		temp0,Y			;nahraj byte ktory este treba posunut od pozicie bitcount do temp0
		and		temp0,temp2		;odmaskuj aby zostali iba spodne neposunute bity v temp0
		or		temp1,temp0		;a zluc posunutu a neposunutu cast

		ld		temp0,Y			;nahraj byte ktory este treba posunut od pozicie bitcount
		rol		temp0			;a posun ho vlavo cez Carry (aby sa nastavilo spravne Carry pre dalsie prenosy)
		st		Y+,temp1		;a nahraj spat upraveny byte
PosunInsertBufferLoop:
		cpse	USBBufptrY,ByteCount	;ak nie su vsetky cele byty
		rjmp	NoEndPosunInsertBuffer	;tak pokracuj
		ret				;inak skonci
NoEndPosunInsertBuffer:
		ld		temp1,Y			;nahraj byte
		rol		temp1			;a posun vlavo cez Carry (prenos z nizsieho byte a LSB do Carry)
		st		Y+,temp1		;a nahraj spat
		rjmp	PosunInsertBufferLoop	;a pokracuj
;------------------------------------------------------------------------------------------
PosunDeleteBuffer:	;posuv buffera o jeden bit vlavo od konca az po poziciu: byte-USBBufptrY a bit-bitcount
		mov		temp0,bitcount		;vypocet: bitcount= 9-bitcount
		ldi		bitcount,9
		sub		bitcount,temp0		;do bitcount poloha bitu, ktory este treba posunut
		mov		temp0,USBBufptrY	;uschovanie pointera do buffera
		inc		temp0			;pozicia celych bytov do temp0
		mov		USBBufptrY,ByteCount	;maximalna pozicia do pointra
PosunDeleteBufferLoop:
		ld		temp1,-Y		;zniz buffer a nahraj byte
		ror		temp1			;a posun vpravo cez Carry (prenos z vyssieho byte a LSB do Carry)
		st		Y,temp1			;a nahraj spat
		cpse	USBBufptrY,temp0	;ak nie su vsetky cele byty
		rjmp	PosunDeleteBufferLoop	;tak pokracuj

		ld		temp1,-Y		;zniz buffer a nahraj byte ktory este treba posunut od pozicie bitcount
		ror		temp1			;a posun vpravo cez Carry (prenos z vyssieho byte a LSB do Carry)
		ser		temp2			;FF do masky - temp2
HalfDeletePosuvMask:
		dec		bitcount		;az pokial sa nedosiahne hranica posuvania v byte
		breq	DoneMask

⌨️ 快捷键说明

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