📄 usb-prog.asm
字号:
rjmp EndInt0HandlerPOP ;inak opakuj od zaciatkuUSBloopEnd: 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 DataPaketTestIOPacket: cp temp1,MyAddress ;ak to nie je urcene (adresa) pre mna brne TestDataPacket ;tak to moze byt este Data PacketTestSetupPacket:;test na SETUP paket cpi temp0,nNRZISETUPPID brne TestOutPacket ;ak nie je Setup PID - dekoduj iny paket ldi State,SetupState rjmp EndInt0HandlerPOP ;ak je Setup PID - prijimaj nasledny Data paketTestOutPacket: ;test na OUT paket cpi temp0,nNRZIOUTPID brne TestInPacket ;ak nie je Out PID - dekoduj iny paket ldi State,OutState rjmp EndInt0HandlerPOP ;ak je Out PID - prijimaj nasledny Data paketTestInPacket: ;test na IN paket cpi temp0,nNRZIINPID brne TestDataPacket ;ak nie je In PID - dekoduj iny paket rjmp AnswerToInRequestTestDataPacket: ;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 paketData0Packet: cpi State,SetupState ;ak bol stav Setup breq ReceiveSetupData ;prijmi ho cpi State,OutState ;ak bol stav Out breq ReceiveOutData ;prijmi hoNoMyPacked: ldi State,BaseState ;znuluj stav rjmp EndInt0HandlerPOP ;a prijimaj nasledny Data paketAnswerToInRequest: push temp2 ;zazalohuj dalsie registre a pokracuj push temp3 push InfraBufptrX push ACC cpi ActionFlag,DoReadySendAnswer ;ak nie je pripravena odpoved brne NoReadySend ;tak posli NAK rcall SendPreparedUSBAnswer ;poslanie odpovede naspat and MyUpdatedAddress,MyUpdatedAddress ;ak je MyUpdatedAddress nenulova brne SetMyNewUSBAddress ;tak treba zmenit USB adresu ldi State,InState ldi ActionFlag,DoPrepareOutContinuousBuffer rjmp EndInt0Handler ;a opakuj - cakaj na dalsiu odozvu z USBReceiveSetupData: push temp2 ;zazalohuj dalsie registre a pokracuj push temp3 push InfraBufptrX push ACC rcall SendACK ;akceptovanie Setup Data paketu rcall FinishReceiving ;ukonci prijem ldi ActionFlag,DoReceiveSetupData rjmp EndInt0HandlerReceiveOutData: push temp2 ;zazalohuj dalsie registre a pokracuj push temp3 push InfraBufptrX push ACC cpi ActionFlag,DoReceiveSetupData ;ak sa prave spracovava prikaz Setup breq NoReadySend ;tak posli NAK rcall SendACK ;akceptovanie Out paketu clr ActionFlag rjmp EndInt0HandlerNoReadySend: 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 clr MyAddress ;vychodzi stav odpovede - mojej nNRZI USB adresy ldi temp2,0b00000001 ;maska na xorovanie ldi temp3,8 ;pocitadlo bitovSetMyNewUSBAddressLoop: mov temp0,MyAddress ;zapamatat si koncovu odpoved ror MyUpdatedAddress ;do carry vysielany bit LSB (v smere naskor LSB a potom MSB) brcs NoXORBit ;ak je jedna - nemen stav eor temp0,temp2 ;inak sa bude stav menit podla posledneho bitu odpovedeNoXORBit: ror temp0 ;posledny bit zmenenej odpovede do carry rol MyAddress ;a z carry do koncovej odpovede na miesto LSB (a sucasne prehodenie LSB a MSB poradia) dec temp3 ;zmensi pocitadlo bitov brne SetMyNewUSBAddressLoop ;ak pocitadlo bitov nie je nulove opakuj vysielanie s dalsim bitom clr MyUpdatedAddress ;znulovanie adresy ako priznak jej buduceho nemenenia 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 bitcountShiftRemainingBits: rol shiftbuf ;posun ostavajuce necele bity na spravnu poziciu dec bitcount brne ShiftRemainingBits st Y+,shiftbuf ;a skopiruj shift register bo buffera - necely byteNoRemainingBits: 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 InfraBufptrX,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 MyAddress,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 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -