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

📄 usbtiny2313.asm

📁 AVR的USB开发源代码 USB-RS232转换
💻 ASM
📖 第 1 页 / 共 5 页
字号:
		breq	ComposeSET_DESCRIPTOR		;

		cpi	temp1,GET_CONFIGURATION		;
		breq	ComposeGET_CONFIGURATION	;

		cpi	temp1,SET_CONFIGURATION		;
		breq	ComposeSET_CONFIGURATION	;

		cpi	temp1,GET_INTERFACE		;
		breq	ComposeGET_INTERFACE		;

		cpi	temp1,SET_INTERFACE		;
		breq	ComposeSET_INTERFACE		;

		cpi	temp1,SYNCH_FRAME		;
		breq	ComposeSYNCH_FRAME		;
							;if not found known request
		rjmp	ZeroDATA1Answer			;if that was something unknown, then prepare zero answer

ComposeSET_ADDRESS:
		lds	temp1,InputBufferBegin+4	;new address to temp1
		rcall	SetMyNewUSBAddresses		;and compute NRZI and bitstuffing coded adresses
		ldi	State,AddressChangeState	;set state for Address changing
		rjmp	ZeroDATA1Answer			;send zero answer

ComposeSET_CONFIGURATION:
		lds	ConfigByte,InputBufferBegin+4	;number of configuration to variable ConfigByte
ComposeCLEAR_FEATURE:
ComposeSET_FEATURE:
ComposeSET_INTERFACE:
ZeroStringAnswer:
		rjmp	ZeroDATA1Answer			;send zero answer
ComposeGET_STATUS:
TwoZeroAnswer:
		ldi	temp0,2				;number of my bytes answers to temp0
ComposeGET_STATUS2:
		ldi	ZH, high(StatusAnswer<<1)	;ROMpointer to  answer
		ldi	ZL,  low(StatusAnswer<<1)
		rjmp	ComposeEndXXXDescriptor		;and complete
ComposeGET_CONFIGURATION:
		and	ConfigByte,ConfigByte		;if I am unconfigured
		breq	OneZeroAnswer			;then send single zero - otherwise send my configuration
		ldi	temp0,1				;number of my bytes answers to temp0
		ldi	ZH, high(ConfigAnswerMinus1<<1)	;ROMpointer to  answer
		ldi	ZL,  low(ConfigAnswerMinus1<<1)+1
		rjmp	ComposeEndXXXDescriptor		;and complete
ComposeGET_INTERFACE:
		ldi	ZH, high(InterfaceAnswer<<1)	;ROMpointer to answer
		ldi	ZL,  low(InterfaceAnswer<<1)
		ldi	temp0,1				;number of my bytes answers to temp0
		rjmp	ComposeEndXXXDescriptor		;and complete
ComposeSYNCH_FRAME:
ComposeSET_DESCRIPTOR:
		rcall	ComposeSTALL
		ret
ComposeGET_DESCRIPTOR:
		lds	temp1,InputBufferBegin+5	;DescriptorType to temp1
		cpi	temp1,DEVICE			;DeviceDescriptor
		breq	ComposeDeviceDescriptor		;
		cpi	temp1,CONFIGURATION		;ConfigurationDescriptor
		breq	ComposeConfigDescriptor		;
		cpi	temp1,STRING			;StringDeviceDescriptor
		breq	ComposeStringDescriptor		;
		ret
ComposeDeviceDescriptor:
		ldi	ZH, high(DeviceDescriptor<<1)	;ROMpointer to descriptor
		ldi	ZL,  low(DeviceDescriptor<<1)
		ldi	temp0,0x12			;number of my bytes answers to temp0
		rjmp	ComposeEndXXXDescriptor		;and complete
ComposeConfigDescriptor:
		ldi	ZH, high(ConfigDescriptor<<1)	;ROMpointer to descriptor
		ldi	ZL,  low(ConfigDescriptor<<1)
		ldi	temp0,9+9+7			;number of my bytes answers to temp0
ComposeEndXXXDescriptor:
		lds	TotalBytesToSend,InputBufferBegin+8	;number of requested bytes to TotalBytesToSend
		cp	TotalBytesToSend,temp0			;if not requested more than I can send
		brcs	HostConfigLength		;transmit the requested number
		mov	TotalBytesToSend,temp0		;otherwise send number of my answers
HostConfigLength:
		mov	temp0,TotalBytesToSend		;
		clr	TransmitPart			;zero the number of 8 bytes answers
		andi	temp0,0b00000111		;if is length divisible by 8
		breq	Length8Multiply			;then not count one answer (under 8 byte)
		inc	TransmitPart			;otherwise count it
Length8Multiply:
		mov	temp0,TotalBytesToSend		;
		lsr	temp0				;length of 8 bytes answers will reach
		lsr	temp0				;integer division by 8
		lsr	temp0
		add	TransmitPart,temp0		;and by addition to last non entire 8-bytes to variable TransmitPart
		ldi	temp0,DATA0PID			;DATA0 PID - in the next will be toggled to DATA1PID in load descriptor
		sts	OutputBufferBegin+1,temp0	;store to output buffer
		rjmp	ComposeNextAnswerPart
ComposeStringDescriptor:
		ldi	temp1,4+8			;if RAMread=4(insert zeros from ROM reading) + 8(behind first byte no load zero)
		mov	RAMread,temp1
		lds	temp1,InputBufferBegin+4	;DescriptorIndex to temp1
		cpi	temp1,0				;LANGID String
		breq	ComposeLangIDString		;
		cpi	temp1,2				;DevNameString
		breq	ComposeDevNameString		;
		brcc	ZeroStringAnswer		;if is DescriptorIndex higher than 2 - send zero answer
							;otherwise is VendorString
ComposeVendorString:
		ldi	ZH, high(VendorStringDescriptor<<1)	;ROMpointer to descriptor
		ldi	ZL,  low(VendorStringDescriptor<<1)
		ldi	temp0,(VendorStringDescriptorEnd-VendorStringDescriptor)*4-2	;number of my bytes answers to temp0
		rjmp	ComposeEndXXXDescriptor		;and complete
ComposeDevNameString:
		ldi	ZH, high(DevNameStringDescriptor<<1)	;ROMpointer to descriptor
		ldi	ZL,  low(DevNameStringDescriptor<<1)
		ldi	temp0,(DevNameStringDescriptorEnd-DevNameStringDescriptor)*4-2	;number of my bytes answers to temp0
		rjmp	ComposeEndXXXDescriptor		;and complete
ComposeLangIDString:
		clr	RAMread
		ldi	ZH, high(LangIDStringDescriptor<<1)	;ROMpointer to descriptor
		ldi	ZL,  low(LangIDStringDescriptor<<1)
		ldi	temp0,(LangIDStringDescriptorEnd-LangIDStringDescriptor)*2;pocet mojich bytovych odpovedi do temp0
		rjmp	ComposeEndXXXDescriptor		;and complete
;------------------------------------------------------------------------------------------
ZeroDATA1Answer:
		rcall	ComposeZeroDATA1PIDAnswer
		ret
;------------------------------------------------------------------------------------------
SetMyNewUSBAddresses:		;set new USB addresses in NRZI coded
		mov	temp2,temp1		;address to temp2 and temp1 and temp3
 		mov	temp3,temp1		;
		cpi	temp1,0b01111111	;if address contains less than 6 ones
		brne	NewAddressNo6ones	;then don't add bitstuffing
		ldi	temp1,0b10111111	;else insert one zero - bitstuffing
 NewAddressNo6ones:
		andi	temp3,0b00000111	;mask 3 low bits of Address
		cpi	temp3,0b00000111	;and if 3 low bits of Address is no all ones
		brne	NewAddressNo3ones	;then no change address
						;else insert zero after 3-rd bit (bitstuffing)
		sec				;set carry
		rol	temp2			;rotate left
		andi	temp2,0b11110111	;and inserted zero after 3-rd bit
 NewAddressNo3ones:
		sts	MyOutAddressSRAM,temp2	;store new non-coded address Out (temp2)
						;and now perform NRZI coding
		rcall	NRZIforAddress		;NRZI for AddressIn (in temp1)
		sts	MyInAddressSRAM,ACC	;store NRZI coded AddressIn

		lds	temp1,MyOutAddressSRAM	;load non-coded address Out (in temp1)
		rcall	NRZIforAddress		;NRZI for AddressOut
		sts	MyOutAddressSRAM,ACC	;store NRZI coded AddressOut

		ret				;and return
;------------------------------------------------------------------------------------------
NRZIforAddress:
		clr	ACC			;original answer state - of my nNRZI USB address
		ldi	temp2,0b00000001	;mask for xoring
		ldi	temp3,8			;bits counter
SetMyNewUSBAddressesLoop:
		mov	temp0,ACC		;remember final answer
		ror	temp1			;to carry transmitting bit LSB (in direction firstly LSB then MSB)
		brcs	NoXORBits		;if one - don't change state
		eor	temp0,temp2		;otherwise state will be changed according to last bit of answer
NoXORBits:
		ror	temp0			;last bit of changed answer to carry
		rol	ACC			;and from carry to final answer to the LSB place (and reverse LSB and MSB order)
		dec	temp3			;decrement bits counter
		brne	SetMyNewUSBAddressesLoop	;if bits counter isn't zero repeat transmitting with next bit
		ret
;------------------------------------------------------------------------------------------
;------------------------------------------------------------------------------------------
PrepareOutContinuousBuffer:
		rcall	PrepareContinuousBuffer
		rcall	MakeOutBitStuff
		ret
;------------------------------------------------------------------------------------------
PrepareContinuousBuffer:
		mov	temp0,TransmitPart
		cpi	temp0,1
		brne	NextAnswerInBuffer		;if buffer empty
		rcall	ComposeZeroAnswer		;prepare zero answer
		ret
NextAnswerInBuffer:
		dec	TransmitPart			;decrement general length of answer
ComposeNextAnswerPart:
		mov	temp1,TotalBytesToSend	;decrement number of bytes to transmit
		subi	temp1,8			;is is necessary to send more as 8 byte
		ldi	temp3,8			;if yes - send only 8 byte
		brcc	Nad8Bytov
		mov	temp3,TotalBytesToSend	;otherwise send only given number of bytes
		clr	TransmitPart
		inc	TransmitPart		;and this will be last answer
Nad8Bytov:
		mov	TotalBytesToSend,temp1	;decremented number of bytes to TotalBytesToSend
		rcall	LoadXXXDescriptor
		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
		ret				;finish
;------------------------------------------------------------------------------------------
.equ	USBversion		=0x0101		;for what version USB is that (1.01)
.equ	VendorUSBID		=0x03EB		; vendor identifier (Atmel=0x03EB)
.equ	DeviceUSBID		=0x21FE		;product identifier (USB to RS232 converter ATmega8=0x21FF)
.equ	DeviceVersion		=0x0002		;version number of product (version=0.02)
.equ	MaxUSBCurrent		=46		;current consumption from USB (46mA)
;------------------------------------------------------------------------------------------
DeviceDescriptor:
		.db	0x12,0x01		;0 byte - size of descriptor in byte
						;1 byte - descriptor type: Device descriptor
		.dw	USBversion		;2,3 byte - version USB LSB (1.00)
		.db	0x00,0x00		;4 byte - device class
						;5 byte - subclass
		.db	0x00,0x08		;6 byte - protocol code
						;7 byte - FIFO size in bytes
		.dw	VendorUSBID		;8,9 byte - vendor identifier (Cypress=0x04B4)
		.dw	DeviceUSBID		;10,11 byte - product identifier (teplomer=0x0002)
		.dw	DeviceVersion		;12,13 byte - product version number (verzia=0.01)
		.db	0x01,0x02		;14 byte - index of string "vendor"
						;15 byte - index of string "product"
		.db	0x00,0x01		;16 byte - index of string "serial number"
						;17 byte - number of possible configurations
DeviceDescriptorEnd:
;------------------------------------------------------------------------------------------
ConfigDescriptor:
		.db	0x9,0x02		;length, descriptor type
ConfigDescriptorLength:
		.dw	9+9+7			;entire length of all descriptors
	ConfigAnswerMinus1:			;for sending the number - congiguration number (attention - addition of 1 required)
		.db	1,1			;numInterfaces, congiguration number
		.db	0,0x80			;string index, attributes; bus powered
		.db	MaxUSBCurrent/2,0x09	;current consumption, interface descriptor length
		.db	0x04,0			;interface descriptor; number of interface
	InterfaceAnswer:			;for sending number of alternatively interface
		.db	0,1			;alternatively interface; number of endpoints except EP0
	StatusAnswer:				;2 zero answers (saving ROM place)
		.db	0,0			;interface class; interface subclass
		.db	0,0			;protocol code; string index
		.db	0x07,0x5		;length, descriptor type - endpoint
		.db	0x81,0			;endpoint address; transfer type
		.dw	0x08			;max packet size
		.db	10,0			;polling interval [ms]; dummy byte (for filling)
ConfigDescriptorEnd:
;------------------------------------------------------------------------------------------
LangIDStringDescriptor:
		.db	(LangIDStringDescriptorEnd-LangIDStringDescriptor)*2,3	;length, type: string descriptor
		.dw	0x0409			;English
LangIDStringDescriptorEnd:
;------------------------------------------------------------------------------------------
VendorStringDescriptor:
		.db	(VendorStringDescriptorEnd-VendorStringDescriptor)*4-2,3	;length, type: string descriptor
VendorStringDescriptorEnd:
;------------------------------------------------------------------------------------------
DevNameStringDescriptor:
		.db	(DevNameStringDescriptorEnd-DevNameStringDescriptor)*4-2,3;dlzka, typ: string deskriptor
		.db	"AVR309:USB to UART protocol converter (simple)"
DevNameStringDescriptorEnd:
;------------------------------------------------------------------------------------------
MaskPortData:
		bst	ACC,0
		bld	temp0,LEDlsb0
		bst	ACC,1
		bld	temp0,LEDlsb1
		bst	ACC,2
		bld	temp0,LEDlsb2
		bst	ACC,3
		bld	temp1,LEDmsb3
		bst	ACC,4
		bld	temp1,LEDmsb4
		bst	ACC,5
		bld	temp1,LEDmsb5
		bst	ACC,6
		bld	temp1,LEDmsb6
		bst	ACC,7
		bld	temp1,LEDmsb7
		ret
;------------------------------------------------------------------------------------------
SetDataPortDirection:
		in	temp0,LEDdirectionLSB		;read current LSB state to temp0 (next bit directions will be not changed)
		in	temp1,LEDdirectionMSB		;read current MSB state to temp1 (next bit directions will be not changed)
		rcall	MaskPortData
		out	LEDdirectionLSB,temp0		;and update LSB port direction
		out	LEDdirectionMSB,temp1		;and update MSB port direction
		ret
;------------------------------------------------------------------------------------------
SetOutDataPort:
		in	temp0,LEDPortLSB		;read current LSB state to temp0 (next data bits will be not changed)
		in	temp1,LEDPortMSB		;read current MSB state to temp1 (next data bits will be not changed)
		rcall	MaskPortData
		out	LEDPortLSB,temp0		;and update LSB data port
		out	LEDPortMSB,temp1		;and update MSB data port
		ret
;------------------------------------------------------------------------------------------
GetInDataPort:
		in	temp0,LEDPinMSB			;read current MSB state to temp0
		in	temp1,LEDPinLSB			;read current LSB state to temp1
MoveLEDin:
		bst	temp1,LEDlsb0			;and move LSB bits to correct positions (from temp1 to temp0)
		bld	temp0,0				;(MSB bits are in correct place)
		bst	temp1,LEDlsb1
		bld	

⌨️ 快捷键说明

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