📄 usb90s23x3.asm
字号:
;cli ;zakaz interrupt kvoli zacykleniu out TIMSK,temp0 ret;------------------------------------------------------------------------------------------SendPreparedUSBAnswer: ;poslanie kodovanim NRZI OUT buffer s dlzkou OutputBufferLength do USB mov ByteCount,OutputBufferLength ;dlzka odpovedeSendUSBAnswer: ;poslanie kodovanim NRZI OUT buffer do USB ldi USBBufptrY,OutputBufferBegin ;pointer na zaciatok vysielacieho bufferaSendUSBBuffer: ;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 temp0SendUSBAnswerLoop: ldi bitcount,7 ;pocitadlo bitovSendUSBAnswerByteLoop: 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 menitNoXORSend: 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 menitNoXORSendLSB: 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 ZeroBitStufSendUSBAnswerBitstuffLoop: 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 menitNoXORBitstuffSend: 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 cyklyZeroBitStuf: 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 DATA1PIDSendData0PID: 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 bufferaComposeZeroAnswer: 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 lastBitstufNumberBitStuffRepeat: push USBBufptrY ;zalohuj pointer do buffera push ByteCount ;zalohuj dlzku buffera mov temp1,temp3 ;pocitadlo vsetkych bitov ldi temp0,8 ;spocitat vsetky bity v bufferiSumAllBits: 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 ByteCountBitStuffLoop: ld temp0,Y ;nahraj prijaty byte z buffera ldi bitcount,8 ;pocitadlo bitov v byteBitStuffByteLoop: 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 bufferaNoBitcountCorrect: 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 CorrectBufferEndCorrectOutBuffer: rcall PosunInsertBuffer ;posun Out buffer inc temp3 ;zvys pocitadlo vynechaniCorrectBufferEnd: pop ByteCount ;obnov dlzku buffera pop USBBufptrY ;obnov pointer do buffera rjmp BitStuffRepeat ;a restartni od zaciatkuNeposunBuffer: 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 opakujEndBitStuff: pop ByteCount ;obnov dlzku buffera pop USBBufptrY ;obnov pointer do buffera bst BitStuffInOut,0 brts IncrementLength ;ak je Out buffer - zvys dlzku Out bufferaDecrementLength: ;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 skonciIncrementLength: 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 - temp2HalfInsertPosuvMask: 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 bytePosunInsertBufferLoop: cpse USBBufptrY,ByteCount ;ak nie su vsetky cele byty rjmp NoEndPosunInsertBuffer ;tak pokracuj ret ;inak skonciNoEndPosunInsertBuffer: 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 pointraPosunDeleteBufferLoop: 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 - temp2HalfDeletePosuvMask: dec bitcount ;az pokial sa nedosiahne hranica posuvania v byte breq DoneMask lsl temp2 ;nula do dalsieho spodneho bitu masky rjmp HalfDeletePosuvMaskDoneMask: and temp1,temp2 ;odmaskuj aby zostali iba vrchne posunute bity v temp1 com temp2 ;invertuj masku 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 st Y,temp1 ;a nahraj spat ret ;a skonci;------------------------------------------------------------------------------------------MirrorInBufferBytes: push USBBufptrY push ByteCount ldi USBBufptrY,InputBufferBegin rcall MirrorBufferBytes
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -