📄 usbtors232.asm
字号:
rcall InitACKBufffer ;initialization of ACK buffer
rcall InitNAKBufffer ;initialization of NAK buffer
rcall USBReset ;initialization of USB addresses
ldi temp0,0b00111100 ;set pull-up on PORTB
out PORTB,temp0
ldi temp0,0b11111111 ;set pull-up on PORTC
out PORTC,temp0
ldi temp0,0b11111011 ;set pull-up on PORTD
out PORTD,temp0
clr temp0 ;
out UBRRH,temp0 ;set UART speed High
out EEARH,temp0 ;zero EEPROM index
ldi temp0,1<<U2X ;set mode X2 on UART
out USR,temp0
ldi temp0,InitBaudRate ;set UART speed
out UBRR,temp0
sbi UCR,TXEN ;enable transmiting of UART
sbi UCR,RXEN ;enable receiving of UART
sbi UCR,RXCIE ;enable interrupt from receiving of UART
ldi temp0,0x0F ;INT0 - respond to leading edge
out MCUCR,temp0 ;
ldi temp0,1<<INT0 ;enable external interrupt INT0
out GIMSK,temp0
;------------------------------------------------------------------------------------------
;********************************************************************
;* Main program
;********************************************************************
sei ;enable interrupts globally
Main:
sbis inputport,DATAminus ;waiting till change D- to 0
rjmp CheckUSBReset ;and check, if isn't USB reset
cpi ActionFlag,DoReceiveSetupData
breq ProcReceiveSetupData
cpi ActionFlag,DoPrepareOutContinuousBuffer
breq ProcPrepareOutContinuousBuffer
rjmp Main
CheckUSBReset:
ldi temp0,255 ;counter duration of reset (according to specification is that cca 10ms - here is cca 100us)
WaitForUSBReset:
sbic inputport,DATAminus ;waiting till change D+ to 0
rjmp Main
dec temp0
brne WaitForUSBReset
rcall USBReset
rjmp Main
ProcPrepareOutContinuousBuffer:
rcall PrepareOutContinuousBuffer ;prepare next sequence of answer to buffer
ldi ActionFlag,DoReadySendAnswer
rjmp Main
ProcReceiveSetupData:
ldi USBBufptrY,InputBufferBegin ;pointer to begin of receiving buffer
mov ByteCount,InputBufferLength ;length of input buffer
rcall DecodeNRZI ;transfer NRZI coding to bits
rcall MirrorInBufferBytes ;invert bits order in bytes
rcall BitStuff ;removal of bitstuffing
;rcall CheckCRCIn ;check CRC
rcall PrepareUSBOutAnswer ;prepare answers to transmitting buffer
ldi ActionFlag,DoReadySendAnswer
rjmp Main
;********************************************************************
;* Main program END
;********************************************************************
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt0 interrupt handler
;********************************************************************
INT0Handler: ;interrupt INT0
in backupSREG,SREG
push temp0
push temp1
ldi temp0,3 ;counter of duration log0
ldi temp1,2 ;counter of duration log1
;waiting for begin packet
CheckchangeMinus:
sbis inputport,DATAminus ;waiting till change D- to 1
rjmp CheckchangeMinus
CheckchangePlus:
sbis inputport,DATAplus ;waiting till change D+ to 1
rjmp CheckchangePlus
DetectSOPEnd:
sbis inputport,DATAplus
rjmp Increment0 ;D+ =0
Increment1:
ldi temp0,3 ;counter of duration log0
dec temp1 ;how many cycles takes log1
nop
breq USBBeginPacket ;if this is end of SOP - receive packet
rjmp DetectSOPEnd
Increment0:
ldi temp1,2 ;counter of duration log1
dec temp0 ;how many cycles take log0
nop
brne DetectSOPEnd ;if there isn't SOF - continue
rjmp EndInt0HandlerPOP2
EndInt0Handler:
pop ACC
pop RS232BufptrX
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:
; 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
cp temp1,MyInAddress ;if this isn't assigned (address) for me
brne TestDataPacket ;then this can be still DataPacket
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
cp temp1,MyOutAddress ;if this isn't assigned (address) for me
brne TestDataPacket ;then this can be still DataPacket
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
cp temp1,MyInAddress ;if this isn't assigned (address) for me
breq 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 RS232BufptrX
push ACC
cpi ActionFlag,DoReadySendAnswer ;if isn't prepared answer
brne NoReadySend ;then send NAK
rcall SendPreparedUSBAnswer ;transmitting answer back
cpi State,AddressChangeState ;if state is AddressChange
breq SetMyNewUSBAddress ;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 RS232BufptrX
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 RS232BufptrX
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: ;set new USB address in NRZI coded
lds MyInAddress,MyInAddressSRAM
lds MyOutAddress,MyOutAddressSRAM
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 RS232BufptrX,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: ;initialization of USB state engine
ldi temp0,nNRZIADDR0 ;initialization of USB address
mov MyOutAddress,temp0
mov MyInAddress,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 ;otherwise state will be changed
NoXORSend:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -