📄 usb90s23x3.asm
字号:
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 + -