📄 usb90s2313.asm
字号:
mov ByteCount,InputBufferLength ;dlzka vstupneho buffera
rcall DecodeNRZI ;prevod kodovania NRZI na bity
rcall MirrorInBufferBytes ;prehodit poradie bitov v bajtoch
rcall BitStuff ;odstranenie bit stuffing
;rcall CheckCRCIn ;kontrola CRC
rcall PrepareUSBOutAnswer ;pripravenie odpovede do vysielacieho buffera
ldi ActionFlag,DoReadySendAnswer
rjmp Main
;********************************************************************
;* Main program END
;********************************************************************
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt0 interrupt handler
;********************************************************************
INT0Handler: ;prerusenie INT0
in backupSREG,SREG
push temp0
push temp1
ldi temp0,3 ;pocitadlo trvania log0
ldi temp1,2 ;pocitadlo trvania log1
;cakanie na zaciatok paketu
CheckchangeMinus:
sbis inputport,DATAminus ;cakanie az sa zmeni D- na 1
rjmp CheckchangeMinus
CheckchangePlus:
sbis inputport,DATAplus ;cakanie az sa zmeni D+ na 1
rjmp CheckchangePlus
DetectSOPEnd:
sbis inputport,DATAplus
rjmp Increment0 ;D+ =0
Increment1:
ldi temp0,3 ;pocitadlo trvania log0
dec temp1 ;kolko cyklov trvala log1
nop
breq USBBeginPacket ;ak je to koniec SOP - prijimaj paket
rjmp DetectSOPEnd
Increment0:
ldi temp1,2 ;pocitadlo trvania log1
dec temp0 ;kolko cyklov trvala log0
nop
brne DetectSOPEnd ;ak nenastal SOF - pokracuj
rjmp EndInt0HandlerPOP2
EndInt0Handler:
pop ACC
pop RS232BufptrX
pop temp3
pop temp2
EndInt0HandlerPOP:
pop USBBufptrY
pop ByteCount
mov bitcount,backupbitcount ;obnova bitcount registra
EndInt0HandlerPOP2:
pop temp1
pop temp0
out SREG,backupSREG
ldi shiftbuf,1<<INTF0 ;znulovat flag interruptu INTF0
out GIFR,shiftbuf
reti ;inak skonci (bol iba SOF - kazdu milisekundu)
USBBeginPacket:
mov backupbitcount,bitcount ;zaloha bitcount registra
in shiftbuf,inputport ;ak ano nacitaj ho ako nulty bit priamo do shift registra
USBloopBegin:
push ByteCount ;dalsia zaloha registrov (setrenie casu)
push USBBufptrY
ldi bitcount,6 ;inicializacia pocitadla bitov v bajte
ldi ByteCount,MAXUSBBYTES ;inicializacia max poctu prijatych bajtov v pakete
ldi USBBufptrY,InputShiftBufferBegin ;nastav vstupny buffer
USBloop1_6:
in inputbuf,inputport
cbr inputbuf,USBpinmask ;odmaskovat spodne 2 bity
breq USBloopEnd ;ak su nulove - koniec USB packetu
ror inputbuf ;presun Data+ do shift registra
rol shiftbuf
dec bitcount ;zmensi pocitadlo bitov
brne USBloop1_6 ;ak nie je nulove - opakuj naplnanie shift registra
nop ;inak bude nutne skopirovat shift register bo buffera
USBloop7:
in inputbuf,inputport
cbr inputbuf,USBpinmask ;odmaskovat spodne 2 bity
breq USBloopEnd ;ak su nulove - koniec USB packetu
ror inputbuf ;presun Data+ do shift registra
rol shiftbuf
ldi bitcount,7 ;inicializacia pocitadla bitov v bajte
st Y+,shiftbuf ;skopiruj shift register bo buffera a zvys pointer do buffera
USBloop0: ;a zacni prijimat dalsi bajt
in shiftbuf,inputport ;nulty bit priamo do shift registra
cbr shiftbuf,USBpinmask ;odmaskovat spodne 2 bity
breq USBloopEnd ;ak su nulove - koniec USB packetu
dec bitcount ;zmensi pocitadlo bitov
nop ;
dec ByteCount ;ak sa nedosiahol maximum buffera
brne USBloop1_6 ;tak prijimaj dalej
rjmp EndInt0HandlerPOP ;inak opakuj od zaciatku
USBloopEnd:
cpi USBBufptrY,InputShiftBufferBegin+3 ;ak sa neprijali aspon 3 byte
brcs EndInt0HandlerPOP ;tak skonci
lds temp0,InputShiftBufferBegin+0 ;identifikator paketu do temp0
lds temp1,InputShiftBufferBegin+1 ;adresa do temp1
brne TestDataPacket ;ak je dlzka ina ako 3 - tak to moze byt iba DataPaket
TestIOPacket:
; cp temp1,MyInAddress ;ak to nie je urcene (adresa) pre mna
; brne TestDataPacket ;tak to moze byt este Data Packet
TestSetupPacket:;test na SETUP paket
cpi temp0,nNRZISETUPPID
brne TestOutPacket ;ak nie je Setup PID - dekoduj iny paket
cp temp1,MyInAddress ;ak to nie je urcene (adresa) pre mna ;ENG;if this isn't assigned (address) for me
brne TestDataPacket ;tak to moze byt este Data Packet ;ENG;then this can be still DataPacket
ldi State,SetupState
rjmp EndInt0HandlerPOP ;ak je Setup PID - prijimaj nasledny Data paket
TestOutPacket: ;test na OUT paket
cpi temp0,nNRZIOUTPID
brne TestInPacket ;ak nie je Out PID - dekoduj iny paket
cp temp1,MyOutAddress ;ak to nie je urcene (adresa) pre mna ;ENG;if this isn't assigned (address) for me
brne TestDataPacket ;tak to moze byt este Data Packet ;ENG;then this can be still DataPacket
ldi State,OutState
rjmp EndInt0HandlerPOP ;ak je Out PID - prijimaj nasledny Data paket
TestInPacket: ;test na IN paket
cpi temp0,nNRZIINPID
brne TestDataPacket ;ak nie je In PID - dekoduj iny paket
cp temp1,MyInAddress ;ak to nie je urcene (adresa) pre mna ;ENG;if this isn't assigned (address) for me
breq AnswerToInRequest ;tak to moze byt este Data Packet ;ENG;then this can be still DataPacket
TestDataPacket: ;test na DATA0 a DATA1 paket
cpi temp0,nNRZIDATA0PID
breq Data0Packet ;ak nie je Data0 PID - dekoduj iny paket
cpi temp0,nNRZIDATA1PID
brne NoMyPacked ;ak nie je Data1 PID - dekoduj iny paket
Data0Packet:
cpi State,SetupState ;ak bol stav Setup
breq ReceiveSetupData ;prijmi ho
cpi State,OutState ;ak bol stav Out
breq ReceiveOutData ;prijmi ho
NoMyPacked:
ldi State,BaseState ;znuluj stav
rjmp EndInt0HandlerPOP ;a prijimaj nasledny Data paket
AnswerToInRequest:
push temp2 ;zazalohuj dalsie registre a pokracuj
push temp3
push RS232BufptrX
push ACC
cpi ActionFlag,DoReadySendAnswer ;ak nie je pripravena odpoved
brne NoReadySend ;tak posli NAK
rcall SendPreparedUSBAnswer ;poslanie odpovede naspat
cpi State,AddressChangeState;ak je stav AddressChange
breq SetMyNewUSBAddress ;tak treba zmenit USB adresu
ldi State,InState
ldi ActionFlag,DoPrepareOutContinuousBuffer
rjmp EndInt0Handler ;a opakuj - cakaj na dalsiu odozvu z USB
ReceiveSetupData:
push temp2 ;zazalohuj dalsie registre a pokracuj
push temp3
push RS232BufptrX
push ACC
rcall SendACK ;akceptovanie Setup Data paketu
rcall FinishReceiving ;ukonci prijem
ldi ActionFlag,DoReceiveSetupData
rjmp EndInt0Handler
ReceiveOutData:
push temp2 ;zazalohuj dalsie registre a pokracuj
push temp3
push RS232BufptrX
push ACC
cpi ActionFlag,DoReceiveSetupData ;ak sa prave spracovava prikaz Setup
breq NoReadySend ;tak posli NAK
rcall SendACK ;akceptovanie Out paketu
clr ActionFlag
rjmp EndInt0Handler
NoReadySend:
rcall SendNAK ;este nie som pripraveny s odpovedou
rjmp EndInt0Handler ;a opakuj - cakaj na dalsiu odozvu z USB
;------------------------------------------------------------------------------------------
SetMyNewUSBAddress: ;nastavi novu USB adresu v NRZI kodovani
lds MyInAddress,MyInAddressSRAM
lds MyOutAddress,MyOutAddressSRAM
rjmp EndInt0Handler
;------------------------------------------------------------------------------------------
FinishReceiving: ;korekcne akcie na ukoncenie prijmu
cpi bitcount,7 ;prenes do buffera aj posledny necely byte
breq NoRemainingBits ;ak boli vsetky byty prenesene, tak neprenasaj nic
inc bitcount
ShiftRemainingBits:
rol shiftbuf ;posun ostavajuce necele bity na spravnu poziciu
dec bitcount
brne ShiftRemainingBits
st Y+,shiftbuf ;a skopiruj shift register bo buffera - necely byte
NoRemainingBits:
mov ByteCount,USBBufptrY
subi ByteCount,InputShiftBufferBegin-1 ;v ByteCount je pocet prijatych byte (vratane necelych byte)
mov InputBufferLength,ByteCount ;a uchovat pre pouzitie v hlavnom programe
ldi USBBufptrY,InputShiftBufferBegin ;pointer na zaciatok prijimacieho shift buffera
ldi RS232BufptrX,InputBufferBegin+1 ;data buffer (vynechat SOP)
MoveDataBuffer:
ld temp0,Y+
st X+,temp0
dec ByteCount
brne MoveDataBuffer
ldi ByteCount,nNRZISOPbyte
sts InputBufferBegin,ByteCount ;ako keby sa prijal SOP - nekopiruje sa zo shift buffera
ret
;------------------------------------------------------------------------------------------
;********************************************************************
;* Other procedures
;********************************************************************
;------------------------------------------------------------------------------------------
USBReset: ;inicializacia USB stavoveho stroja
ldi temp0,nNRZIADDR0 ;inicializacia USB adresy
mov MyOutAddress,temp0
mov MyInAddress,temp0
clr State ;inicializacia stavoveho stroja
clr BitStuffInOut
clr OutBitStuffNumber
clr ActionFlag
clr RAMread ;bude sa vycitavat z ROM-ky
clr ConfigByte ;nenakonfiguravany stav
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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -