📄 usbtors232.asm
字号:
rcall CheckCRC
com temp0 ;negation of CRC
com temp1
st Y+,temp1 ;save CRC to the end of buffer (at first MSB)
st Y,temp0 ;save CRC to the end of buffer (then LSB)
dec USBBufptrY ;pointer to CRC position
ldi ByteCount,2 ;reverse bits order in 2 bytes CRC
rcall MirrorBufferBytes ;reverse bits order in CRC (transmiting CRC - MSB first)
pop ByteCount
pop USBBufptrY
ret
;------------------------------------------------------------------------------------------
CheckCRC: ;input: USBBufptrY = begin of message ,ByteCount = length of message
add ByteCount,USBBufptrY ;ByteCount points to the end of message
inc USBBufptrY ;set the pointer to message start - omit SOP
ld temp0,Y+ ;load PID to temp0
;and set the pointer to start of message - omit also PID
cpi temp0,DATA0PID ;if is DATA0 field
breq ComputeDATACRC ;compute CRC16
cpi temp0,DATA1PID ;if is DATA1 field
brne CRC16End ;if no then finish
ComputeDATACRC:
ser temp0 ;initialization of remaider LSB to 0xff
ser temp1 ;initialization of remaider MSB to 0xff
CRC16Loop:
ld temp2,Y+ ;load message to temp2 and increment pointer to buffer
ldi temp3,8 ;bits counter in byte - temp3
CRC16LoopByte:
bst temp1,7 ;to T save MSB of remainder (remainder is only 16 bits - 8 bit of higher byte)
bld bitcount,0 ;to bitcount LSB save T - of MSB remainder
eor bitcount,temp2 ;XOR of bit message and bit remainder - in LSB bitcount
rol temp0 ;shift remainder to the left - low byte (two bytes - through carry)
rol temp1 ;shift remainder to the left - high byte (two bytes - through carry)
cbr temp0,1 ;znuluj LSB remains
lsr temp2 ;shift message to right
ror bitcount ;result of XOR bits from LSB to carry
brcc CRC16NoXOR ;if is XOR bitmessage and MSB of remainder = 0 , then no XOR
ldi bitcount,CRC16poly>>8 ;to bitcount CRC polynomial - high byte
eor temp1,bitcount ;and make XOR from remains and CRC polynomial - high byte
ldi bitcount,CRC16poly ;to bitcount CRC polynomial - low byte
eor temp0,bitcount ;and make XOR of remainder and CRC polynomial - low byte
CRC16NoXOR:
dec temp3 ;were already all bits in byte
brne CRC16LoopByte ;unless, then go to next bit
cp USBBufptrY,ByteCount ;was already end-of-message
brne CRC16Loop ;unless then repeat
CRC16End:
ret ;otherwise finish (in temp0 and temp1 is result)
;------------------------------------------------------------------------------------------
LoadDescriptorFromROM:
lpm ;load from ROM position pointer to R0
st Y+,R0 ;R0 save to buffer and increment buffer
adiw ZH:ZL,1 ;increment index to ROM
dec ByteCount ;till are not all bytes
brne LoadDescriptorFromROM ;then load next
rjmp EndFromRAMROM ;otherwise finish
;------------------------------------------------------------------------------------------
LoadDescriptorFromROMZeroInsert:
lpm ;load from ROM position pointer to R0
st Y+,R0 ;R0 save to buffer and increment buffer
bst RAMread,3 ;if bit 3 is one - don't insert zero
brtc InsertingZero ;otherwise zero will be inserted
adiw ZH:ZL,1 ;increment index to ROM
lpm ;load from ROM position pointer to R0
st Y+,R0 ;R0 save to buffer and increment buffer
clt ;and clear
bld RAMread,3 ;the third bit in RAMread - for to the next zero insertion will be made
rjmp InsertingZeroEnd ;and continue
InsertingZero:
clr R0 ;for insertion of zero
st Y+,R0 ;zero save to buffer and increment buffer
InsertingZeroEnd:
adiw ZH:ZL,1 ;increment index to ROM
subi ByteCount,2 ;till are not all bytes
brne LoadDescriptorFromROMZeroInsert ;then load next
rjmp EndFromRAMROM ;otherwise finish
;------------------------------------------------------------------------------------------
LoadDescriptorFromSRAM:
ld R0,Z ;load from position RAM pointer to R0
st Y+,R0 ;R0 save to buffer and increment buffer
adiw ZH:ZL,1 ;increment index to RAM
dec ByteCount ;till are not all bytes
brne LoadDescriptorFromSRAM ;then load next
rjmp EndFromRAMROM ;otherwise finish
;------------------------------------------------------------------------------------------
LoadDescriptorFromEEPROM:
out EEARL,ZL ;set the address EEPROM Lo
out EEARH,ZH ;set the address EEPROM Hi
sbi EECR,EERE ;read EEPROM to register EEDR
in R0,EEDR ;load from EEDR to R0
st Y+,R0 ;R0 save to buffer and increment buffer
adiw ZH:ZL,1 ;increment index to EEPROM
dec ByteCount ;till are not all bytes
brne LoadDescriptorFromEEPROM;then load next
rjmp EndFromRAMROM ;otherwise finish
;------------------------------------------------------------------------------------------
LoadXXXDescriptor:
ldi temp0,SOPbyte ;SOP byte
sts OutputBufferBegin,temp0 ;to begin of tramsmiting buffer store SOP
ldi ByteCount,8 ;8 byte store
ldi USBBufptrY,OutputBufferBegin+2 ;to transmitting buffer
and RAMread,RAMread ;if will be reading from RAM or ROM or EEPROM
brne FromRAMorEEPROM ;0=ROM,1=RAM,2=EEPROM,4=ROM with zero insertion (string)
FromROM:
rjmp LoadDescriptorFromROM ;load descriptor from ROM
FromRAMorEEPROM:
sbrc RAMread,2 ;if RAMREAD=4
rjmp LoadDescriptorFromROMZeroInsert ;read from ROM with zero insertion
sbrc RAMread,0 ;if RAMREAD=1
rjmp LoadDescriptorFromSRAM ;load data from SRAM
rjmp LoadDescriptorFromEEPROM ;otherwise read from EEPROM
EndFromRAMROM:
sbrc RAMread,7 ;if is most significant bit in variable RAMread=1
clr RAMread ;clear RAMread
rcall ToggleDATAPID ;change DATAPID
ldi USBBufptrY,OutputBufferBegin+1 ;to transmitting buffer - position of DATA PID
ret
;------------------------------------------------------------------------------------------
PrepareUSBOutAnswer: ;prepare answer to buffer
rcall PrepareUSBAnswer ;prepare answer to buffer
MakeOutBitStuff:
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
ret
;------------------------------------------------------------------------------------------
PrepareUSBAnswer: ;prepare answer to buffer
clr RAMread ;zero to RAMread variable - reading from ROM
lds temp0,InputBufferBegin+2 ;bmRequestType to temp0
lds temp1,InputBufferBegin+3 ;bRequest to temp1
cbr temp0,0b10011111 ;if is 5 and 6 bit zero
brne VendorRequest ;then this isn't Vendor Request
rjmp StandardRequest ;but this is standard Request
;--------------------------
VendorRequest:
clr ZH ;for reading from RAM or EEPROM
cpi temp1,1 ;
brne NoDoSetInfraBufferEmpty ;
rjmp DoSetInfraBufferEmpty ;restart infra receiving (if it was stopped by reading from RAM)
NoDoSetInfraBufferEmpty:
cpi temp1,2 ;
brne NoDoGetInfraCode
rjmp DoGetInfraCode ;transmit received infra code (if it is in buffer)
NoDoGetInfraCode:
cpi temp1,3 ;
brne NoDoSetDataPortDirection
rjmp DoSetDataPortDirection ;set flow direction of datal bits
NoDoSetDataPortDirection:
cpi temp1,4 ;
brne NoDoGetDataPortDirection
rjmp DoGetDataPortDirection ;detect of flow direction of data bits
NoDoGetDataPortDirection:
cpi temp1,5 ;
brne NoDoSetOutDataPort
rjmp DoSetOutDataPort ;set data bits (if they are inputs, then pull-ups)
NoDoSetOutDataPort:
cpi temp1,6 ;
brne NoDoGetOutDataPort
rjmp DoGetOutDataPort ;detect settings of data out bits (if they are input, then pull-ups)
NoDoGetOutDataPort:
cpi temp1,7 ;
brne NoDoGetInDataPort
rjmp DoGetInDataPort ;return value of input data port
NoDoGetInDataPort:
cpi temp1,8 ;
brne NoDoEEPROMRead
rjmp DoEEPROMRead ;return contents of EEPROM from given address
NoDoEEPROMRead:
cpi temp1,9 ;
brne NoDoEEPROMWrite
rjmp DoEEPROMWrite ;write to EEPROM to given address given data
NoDoEEPROMWrite:
cpi temp1,10 ;
brne NoDoRS232Send
rjmp DoRS232Send ;transmit byte to serial line
NoDoRS232Send:
cpi temp1,11 ;
brne NoDoRS232Read
rjmp DoRS232Read ;returns received byte from serial line
NoDoRS232Read:
cpi temp1,12 ;
brne NoDoSetRS232Baud
rjmp DoSetRS232Baud ;set line speed of of serial line
NoDoSetRS232Baud:
cpi temp1,13 ;
brne NoDoGetRS232Baud
rjmp DoGetRS232Baud ;return line speed of serial line
NoDoGetRS232Baud:
cpi temp1,14 ;
brne NoDoGetRS232Buffer
rjmp DoGetRS232Buffer ;return line speed of serial line
NoDoGetRS232Buffer:
cpi temp1,15 ;
brne NoDoSetRS232DataBits
rjmp DoSetRS232DataBits ;set line speed of serial line
NoDoSetRS232DataBits:
cpi temp1,16 ;
brne NoDoGetRS232DataBits
rjmp DoGetRS232DataBits ;return line speed of serial line
NoDoGetRS232DataBits:
cpi temp1,17 ;
brne NoDoSetRS232Parity
rjmp DoSetRS232Parity ;set line speed of serial line
NoDoSetRS232Parity:
cpi temp1,18 ;
brne NoDoGetRS232Parity
rjmp DoGetRS232Parity ;return line speed of serial line
NoDoGetRS232Parity:
cpi temp1,19 ;
brne NoDoSetRS232StopBits
rjmp DoSetRS232StopBits ;set line speed of serial line
NoDoSetRS232StopBits:
cpi temp1,20 ;
brne NoDoGetRS232StopBits
rjmp DoGetRS232StopBits ;return line speed of serial line
NoDoGetRS232StopBits:
cpi temp1,USER_FNC_NUMBER+0 ;
brne NoDoUserFunction0
rjmp DoUserFunction0 ;execute of user function0
NoDoUserFunction0:
cpi temp1,USER_FNC_NUMBER+1 ;
brne NoDoUserFunction1
rjmp DoUserFunction1 ;execute of user function1
NoDoUserFunction1:
cpi temp1,USER_FNC_NUMBER+2 ;
brne NoDoUserFunction2
rjmp DoUserFunction2 ;execute of user function1
NoDoUserFunction2:
rjmp ZeroDATA1Answer ;if that it was something unknown, then prepare zero answer
;----------------------------- USER FUNCTIONS --------------------------------------
;------------------------------TEMPLATE OF YOUR FUNCTION----------------------------
;------------------ BEGIN: This is template how to write own function --------------
;free of use are registers:
;temp0,temp1,temp2,temp3,ACC,ZH,ZL
;registers are destroyed after execution (use push/pop to save content)
;at the end of routine you must correctly set registers:
;RAMread - 0=reading from ROM, 1=reading from RAM, 2=reading from EEPROM
;temp0 - number of transmitted data bytes
;ZH,ZL - pointer to buffer of transmitted data (pointer to ROM/RAM/EEPROM)
;to transmit data (preparing data to buffer) :
;to transmit data you must jump to "ComposeEndXXXDescriptor"
;to transmit one zero byte you can jump to "OneZeroAnswer" (commonly used as confirmation of correct processing)
;to transmit two zero byte you can jump to "TwoZeroAnswer" (commonly used as confirmation of error in processing)
;for small size (up to 8 bytes) ansver use buffer AnswerArray (see function DoGetOutDataPort:)
DoUserFunctionX:
DoUserFunction0: ;send byte(s) of RAM starting at position given by first parameter in function
lds temp0,InputBufferBegin+4 ;first parameter Lo into temp0
lds temp1,InputBufferBegin+5 ;first parameter Hi into temp1
;lds temp2,InputBufferBegin+6 ;second parameter Lo into temp2
;lds temp3,InputBufferBegin+7 ;second parameter Hi into temp3
;lds ACC,InputBufferBegin+8 ;number of requested bytes from USB host (computer) into ACC
;Here add your own code:
;-------------------------------------------------------------------
nop ;example of code - nothing to do
nop
nop
nop
nop
;-------------------------------------------------------------------
mov ZL,temp0 ;will be sending value of RAM - from address stored in temp0 (first parameter Lo of function)
mov ZH,temp1 ;will be sending value of RAM - from address stored in temp1 (first parameter Hi of function)
inc RAMread ;RAMread=1 - reading from RAM
ldi temp0,255 ;send max number of bytes - 255 bytes are maximum
rjmp ComposeEndXXXDescriptor ;a prepare data
DoUserFunction1:
rjmp OneZeroAnswer ;only confirm receiving by one zero byte answer
DoUserFunction2:
rjmp TwoZeroAnswer ;only confirm receiving by two zero bytes answer
;------------------ END: This is template how to write own function ----------------
;----------------------------- USER FUNCTIONS --------------------------------------
;--------------------------
DoSetInfraBufferEmpty:
rjmp OneZeroAnswer ;acknowledge reception with single zero
;--------------------------
DoGetInfraCode:
rjmp OneZeroAnswer ;acknowledge reception with single zero
;--------------------------
DoSetDataPortDirection:
lds temp1,InputBufferBegin+7 ;fourth parameter - bit mask - which port(s) to change
lds temp0,InputBufferBegin+4 ;first parameter - direction of data bits DDRB
andi temp0,0b00111100 ;mask unused pins
sbrc temp1,0 ;if bit0 is zero - don't change port state
out DDRB,temp0 ;and update direction of data port
lds temp0,InputBufferBegin+5 ;second parameter - direction of data bits DDRC
sbrc temp1,1 ;if bit1 is zero - don't change port state
out DDRC,temp0 ;and update direction of data port
lds temp0,InputBufferBegin+6 ;third parameter - direction of data bits DDRD
andi temp0,0b11111000 ;mask unused pins
ori temp0,0b00000010 ;mask unused pins
sbrc temp1,2 ;if bit2 is zero - don't change port state
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -