📄 usb90s23x3.asm
字号:
reti;********************************************************************;* Init program;********************************************************************;------------------------------------------------------------------------------------------reset: ;inicializacia procesora a premennych na spravne hodnoty ldi temp0,StackBegin ;inicializacia stacku out SPL,temp0 clr XH ;Infra pointer clr YH ;USB pointer clr ZH ;ROM pointer sts InfraBufferBegin,YH ;znuluj dlzky Infra kodu v bufferi sts InfraBufferBegin+1,YH ;znuluj pocitadlo infra kodov v bufferi clr MyUpdatedAddress ;nova adresa USB - nedekodovana rcall InitACKBufffer ;inicializacia ACK buffera rcall InitNAKBufffer ;inicializacia NAK buffera rcall USBReset ;inicializacia USB adresy sbi TSOPpullupPort,TSOPpin ;nahodit pull-up na TSOP vstupe ldi temp0,(1<<LEDlsb0)+(1<<LEDlsb1)+(1<<LEDlsb2) out LEDPortLSB,temp0 ;nahodit pull-up na vsetkych LED vstupoch LSB ldi temp0,(1<<LEDmsb3)+(1<<LEDmsb4)+(1<<LEDmsb5)+(1<<LEDmsb6)+(1<<LEDmsb7) out LEDPortMSB,temp0 ;nahodit pull-up na vsetkych LED vstupoch MSB sbi PORTD,0 ;nahodit pull-up na RxD vstupe ldi temp0,BaudRate ;nastavitvysielaciu rychlost UART-u out UBRR,temp0 sbi UCR,TXEN ;povolit vysielanie UART-u sbi UCR,RXEN ;povolit prijimanie UART-u ldi temp0,0x0F ;INT0 - reagovanie na nabeznu hranu out MCUCR,temp0 ; ldi temp0,1<<INT0 ;povolit externy interrupt INT0 out GIMSK,temp0 rcall InitCounter ;inicializacia citaca na TSOP zmenu;------------------------------------------------------------------------------------------;********************************************************************;* Main program;******************************************************************** sei ;povolit interrupty globalneMain: sbis inputport,DATAminus ;cakanie az sa zmeni D- na 0 rjmp CheckUSBReset ;a skontroluj, ci to nie je USB reset cpi ActionFlag,DoReceiveSetupData breq ProcReceiveSetupData cpi ActionFlag,DoPrepareOutContinuousBuffer breq ProcPrepareOutContinuousBuffer rjmp MainCheckUSBReset: ldi temp0,255 ;pocitadlo trvania reset-u (podla normy je to cca 10ms - tu je to cca 100us)WaitForUSBReset: sbic inputport,DATAminus ;cakanie az sa zmeni D+ na 0 rjmp Main dec temp0 brne WaitForUSBReset rcall USBReset rjmp MainProcPrepareOutContinuousBuffer: rcall PrepareOutContinuousBuffer ;priprav pokracovanie odpovede do buffera ldi ActionFlag,DoReadySendAnswer rjmp MainProcReceiveSetupData: ldi USBBufptrY,InputBufferBegin ;pointer na zaciatok prijimacieho buffera 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 paketuCheckchangeMinus: sbis inputport,DATAminus ;cakanie az sa zmeni D- na 1 rjmp CheckchangeMinusCheckchangePlus: sbis inputport,DATAplus ;cakanie az sa zmeni D+ na 1 rjmp CheckchangePlusDetectSOPEnd: sbis inputport,DATAplus rjmp Increment0 ;D+ =0Increment1: ldi temp0,3 ;pocitadlo trvania log0 dec temp1 ;kolko cyklov trvala log1 nop breq USBBeginPacket ;ak je to koniec SOP - prijimaj paket rjmp DetectSOPEndIncrement0: ldi temp1,2 ;pocitadlo trvania log1 dec temp0 ;kolko cyklov trvala log0 nop brne DetectSOPEnd ;ak nenastal SOF - pokracuj rjmp EndInt0HandlerPOP2EndInt0Handler: pop ACC pop InfraBufptrX pop temp3 pop temp2EndInt0HandlerPOP: pop USBBufptrY pop ByteCount mov bitcount,backupbitcount ;obnova bitcount registraEndInt0HandlerPOP2: 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 registraUSBloopBegin: 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 bufferUSBloop1_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 bufferaUSBloop7: 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 bufferaUSBloop0: ;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 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;------------------------------------------------------------------------------------------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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -