📄 usb90s23x3.asm
字号:
pop ByteCount pop USBBufptrY ret;------------------------------------------------------------------------------------------MirrorBufferBytes: add ByteCount,USBBufptrY ;ByteCount ukazuje na koniec spravyMirrorBufferloop: ld temp0,Y ;nahraj prijaty byte z buffera ldi temp1,8 ;pocitadlo bitovMirrorBufferByteLoop: ror temp0 ;do carry dalsi najnizsi bit rol temp2 ;z carry dalsi bit na obratene poradie dec temp1 ;bol uz cely byte brne MirrorBufferByteLoop ;ak nie tak opakuj dalsi najnizsi bit st Y+,temp2 ;ulozenie spat ako obrateny byte a zvys pointer do buffera cp USBBufptrY,ByteCount ;ak este neboli vsetky brne MirrorBufferloop ;tak opakuj ret ;inak skonci;------------------------------------------------------------------------------------------CheckCRCIn: push USBBufptrY push ByteCount ldi USBBufptrY,InputBufferBegin rcall CheckCRC pop ByteCount pop USBBufptrY ret;------------------------------------------------------------------------------------------AddCRCOut: push USBBufptrY push ByteCount ldi USBBufptrY,OutputBufferBegin rcall CheckCRC com temp0 ;negacia CRC com temp1 st Y+,temp1 ;ulozenie CRC na koniec buffera (najskor MSB) st Y,temp0 ;ulozenie CRC na koniec buffera (potom LSB) dec USBBufptrY ;pointer na poziciu CRC ldi ByteCount,2 ;otocit 2 byty CRC rcall MirrorBufferBytes ;opacne poradie bitov CRC (pri vysielani CRC sa posiela naskor MSB) pop ByteCount pop USBBufptrY ret;------------------------------------------------------------------------------------------CheckCRC: ;vstup: USBBufptrY = zaciatok spravy ,ByteCount = dlzka spravy add ByteCount,USBBufptrY ;ByteCount ukazuje na koniec spravy inc USBBufptrY ;nastav pointer na zaciatok spravy - vynechat SOP ld temp0,Y+ ;nahraj PID do temp0 ;a nastav pointer na zaciatok spravy - vynechat aj PID cpi temp0,DATA0PID ;ci je DATA0 pole breq ComputeDATACRC ;pocitaj CRC16 cpi temp0,DATA1PID ;ci je DATA1 pole brne CRC16End ;ak nie tak skonci ComputeDATACRC: ser temp0 ;inicializacia zvysku LSB na 0xff ser temp1 ;inicializacia zvysku MSB na 0xff CRC16Loop: ld temp2,Y+ ;nahraj spravu do temp2 a zvys pointer do buffera ldi temp3,8 ;pocitadlo bitov v byte - temp3CRC16LoopByte: bst temp1,7 ;do T uloz MSB zvysku (zvysok je iba 16 bitovy - 8 bit vyssieho byte) bld bitcount,0 ;do bitcount LSB uloz T - MSB zvysku eor bitcount,temp2 ;XOR bitu spravy a bitu zvysku - v LSB bitcount rol temp0 ;posun zvysok dolava - nizsi byte (dva byty - cez carry) rol temp1 ;posun zvysok dolava - vyssi byte (dva byty - cez carry) cbr temp0,1 ;znuluj LSB zvysku lsr temp2 ;posun spravu doprava ror bitcount ;vysledok XOR-u bitov z LSB do carry brcc CRC16NoXOR ;ak je XOR bitu spravy a MSB zvysku = 0 , tak nerob XOR ldi bitcount,CRC16poly>>8 ;do bitcount CRC polynom - vrchny byte eor temp1,bitcount ;a urob XOR zo zvyskom a CRC polynomom - vrchny byte ldi bitcount,CRC16poly ;do bitcount CRC polynom - spodny byte eor temp0,bitcount ;a urob XOR zo zvyskom a CRC polynomom - spodny byteCRC16NoXOR: dec temp3 ;boli uz vsetky bity v byte brne CRC16LoopByte ;ak nie, tak chod na dalsi bit cp USBBufptrY,ByteCount ;bol uz koniec spravy brne CRC16Loop ;ak nie tak opakujCRC16End: ret ;inak skonci (v temp0 a temp1 je vysledok);------------------------------------------------------------------------------------------LoadDescriptorFromROM: lpm ;nahraj z pozicie ROM pointra do R0 st Y+,R0 ;R0 uloz do buffera a zvys buffer adiw ZH:ZL,1 ;zvys ukazovatel do ROM dec ByteCount ;pokial nie su vsetky byty brne LoadDescriptorFromROM ;tak nahravaj dalej rjmp EndFromRAMROM ;inak skonci;------------------------------------------------------------------------------------------LoadDescriptorFromROMZeroInsert: lpm ;nahraj z pozicie ROM pointra do R0 st Y+,R0 ;R0 uloz do buffera a zvys buffer bst RAMread,3 ;ak je 3 bit jednotkovy - nebude sa vkladat nula brtc InsertingZero ;inak sa bude vkladat nula adiw ZH:ZL,1 ;zvys ukazovatel do ROM lpm ;nahraj z pozicie ROM pointra do R0 st Y+,R0 ;R0 uloz do buffera a zvys buffer clt ;a znuluj bld RAMread,3 ;treti bit v RAMread - aby sa v dalsom vkladali nuly rjmp InsertingZeroEnd ;a pokracujInsertingZero: clr R0 ;na vkladanie nul st Y+,R0 ;nulu uloz do buffera a zvys bufferInsertingZeroEnd: adiw ZH:ZL,1 ;zvys ukazovatel do ROM subi ByteCount,2 ;pokial nie su vsetky byty brne LoadDescriptorFromROMZeroInsert ;tak nahravaj dalej rjmp EndFromRAMROM ;inak skonci;------------------------------------------------------------------------------------------LoadDescriptorFromSRAM: ld R0,Z ;nahraj z pozicie RAM pointra do R0 st Y+,R0 ;R0 uloz do buffera a zvys buffer inc ZL ;zvys ukazovatel do RAM dec ByteCount ;pokial nie su vsetky byty brne LoadDescriptorFromSRAM ;tak nahravaj dalej rjmp EndFromRAMROM ;inak skonci;------------------------------------------------------------------------------------------LoadDescriptorFromEEPROM: out EEAR,ZL ;nastav adresu EEPROM sbi EECR,EERE ;vycitaj EEPROM do registra EEDR in R0,EEDR ;nahraj z EEDR do R0 st Y+,R0 ;R0 uloz do buffera a zvys buffer inc ZL ;zvys ukazovatel do RAM dec ByteCount ;pokial nie su vsetky byty brne LoadDescriptorFromEEPROM;tak nahravaj dalej rjmp EndFromRAMROM ;inak skonci;------------------------------------------------------------------------------------------LoadXXXDescriptor: ldi temp0,SOPbyte ;SOP byte sts OutputBufferBegin,temp0 ;na zaciatok vysielacieho buffera dat SOP ldi ByteCount,8 ;8 bytov nahrat ldi USBBufptrY,OutputBufferBegin+2 ;do vysielacieho buffera and RAMread,RAMread ;ci sa bude citat z RAM alebo ROM-ky alebo EEPROM-ky brne FromRAMorEEPROM ;0=ROM,1=RAM,2=EEPROM,4=ROM s vkladanim nulyFromROM: rjmp LoadDescriptorFromROM ;nahrat descriptor z ROM-kyFromRAMorEEPROM: sbrc RAMread,2 ;ak RAMread=4 rjmp LoadDescriptorFromROMZeroInsert ;citaj z ROM s vkladanim nuly sbrc RAMread,0 ;ak RAMread=1 rjmp LoadDescriptorFromSRAM ;nahraj data zo SRAM-ky rjmp LoadDescriptorFromEEPROM ;inak citaj z EEPROMEndFromRAMROM: sbrc RAMread,7 ;ak je najvyssi bit v premennej RAMread=1 clr RAMread ;znuluj RAMread rcall ToggleDATAPID ;zmenit DATAPID ldi USBBufptrY,OutputBufferBegin+1 ;do vysielacieho buffera - pozicia DATA PID ret;------------------------------------------------------------------------------------------PrepareUSBOutAnswer: ;pripravenie odpovede do buffera rcall PrepareUSBAnswer ;pripravenie odpovede do bufferaMakeOutBitStuff: inc BitStuffInOut ;vysielaci buffer - vkladanie bitstuff bitov ldi USBBufptrY,OutputBufferBegin ;do vysielacieho buffera rcall BitStuff mov OutputBufferLength,ByteCount ;dlzku odpovede zapamatat pre vysielanie clr BitStuffInOut ;prijimaci buffer - mazanie bitstuff bitov ret;------------------------------------------------------------------------------------------PrepareUSBAnswer: ;pripravenie odpovede do buffera clr RAMread ;nulu do RAMread premennej - cita sa z ROM-ky lds temp0,InputBufferBegin+2 ;bmRequestType do temp0 lds temp1,InputBufferBegin+3 ;bRequest do temp1 cbr temp0,0b10011111 ;ak je 5 a 6 bit nulovy brne VendorRequest ;tak to nie je Vendor Request rjmp StandardRequest ;ale je to standardny request;--------------------------DoSetInfraBufferEmpty: clr InfraBufferFull ;nastav prazdnost bufferaSendZeroAnswerInfraEmpty: rjmp OneZeroAnswer ;potvrd prijem jednou nulou;--------------------------VendorRequest: clr ZH ;pre citanie z RAM alebo EEPROM cpi temp1,1 ; breq DoSetInfraBufferEmpty ;restartne infra prijimanie (ak bolo zastavene citanim z RAM-ky) cpi temp1,2 ; breq DoGetInfraCode ;vysle prijaty infra kod (ak je v bufferi) cpi temp1,3 ; breq DoSetDataPortDirection ;nastavi smer toku datovych bitov cpi temp1,4 ; breq DoGetDataPortDirection ;zisti smer toku datovych bitov cpi temp1,5 ; breq DoSetOutDataPort ;nastavi datove bity (ak su vstupne, tak ich pull-up) cpi temp1,6 ; breq DoGetOutDataPort ;zisti nastavenie datovych out bitov (ak su vstupne, tak ich pull-up) cpi temp1,7 ; breq DoGetInDataPort ;vrati hodnotu datoveho vstupneho portu cpi temp1,8 ; breq DoEEPROMRead ;vrati obsah EEPROM od urcitej adresy cpi temp1,9 ; breq DoEEPROMWrite ;zapise EEPROM na urcitu adresu urcite data cpi temp1,10 ; breq DoRS232Send ;vysle byte na seriovy linku cpi temp1,11 ; breq DoRS232Read ;vrati prijaty byte zo seriovej linky (ak sa nejaky prijal) cpi temp1,12 ; breq DoSetRS232Baud ;nastavi prenosovu rychlost seriovej linky cpi temp1,13 ; breq DoGetRS232Baud ;vrati prenosovu rychlost seriovej linky rjmp ZeroDATA1Answer ;ak to bolo nieco nezname, tak priprav nulovu odpoved;----------------------------- USER FUNCTIONS --------------------------------------DoGetInfraCode: cpi InfraBufferFull,0 ;ak je Infra Buffer prazdny breq SendZeroAnswerInfraEmpty ;tak nic neposli ldi ZL,InfraBufferBegin lds temp1,InputBufferBegin+4 ;prvy parameter - offset v infra bufferi add ZL,temp1 ;plus offset v buffri lds temp0,InfraBufferBegin ;pocet mojich bytovych odpovedi do temp0 ldi temp1,3 ;plus 3 byty hlavicky add temp0,temp1 inc RAMread ;RAMread=1 - cita sa z RAM-ky rjmp ComposeEndXXXDescriptor ;a priprav dataDoEEPROMRead: lds ZL,InputBufferBegin+4 ;prvy parameter - offset v EEPROM-ke ldi temp0,2 mov RAMread,temp0 ;RAMread=2 - cita sa z EEPROM-ky ldi temp0,E2END+1 ;pocet mojich bytovych odpovedi do temp0 - cela dlzka EEPROM rjmp ComposeEndXXXDescriptor ;inak priprav dataDoEEPROMWrite: lds ZL,InputBufferBegin+4 ;prvy parameter - offset v EEPROM-ke (adresa) lds R0,InputBufferBegin+6 ;druhy parameter - data, ktore sa maju zapisat do EEPROM-ky (data) rjmp EEPROMWrite ;zapis do EEPROM a aj ukonci prikazDoSetDataPortDirection: lds ACC,InputBufferBegin+4 ;prvy parameter - smer datovych bitov rcall SetDataPortDirection rjmp OneZeroAnswer ;potvrd prijem jednou nulouDoGetDataPortDirection: rcall GetDataPortDirection rjmp DoGetInDoSetOutDataPort: lds ACC,InputBufferBegin+4 ;prvy parameter - hodnota datovych bitov rcall SetOutDataPort rjmp OneZeroAnswer ;potvrd prijem jednou nulouDoGetOutDataPort: rcall GetOutDataPort rjmp DoGetInDoGetInDataPort: rcall GetInDataPort DoGetIn: ldi ZL,0 ;posiela sa hodnota v R0 ldi temp0,0x81 ;RAMread=1 - cita sa z RAM-ky mov RAMread,temp0 ;(najvyssi bit na 1 - aby sa hned premenna RAMread znulovala) ldi temp0,1 ;posli iba jeden byte rjmp ComposeEndXXXDescriptor ;a priprav dataDoSetRS232Baud: lds temp0,InputBufferBegin+4 ;prvy parameter - hodnota baudrate na RS232 out UBRR,temp0 ;nastav rychlost UART-u rjmp OneZeroAnswer ;potvrd prijem jednou nulouDoGetRS232Baud: in R0,UBRR ;vrat rychlost UART-u v R0 rjmp DoGetIn ;a ukonci DoRS232Send: lds temp0,InputBufferBegin+4 ;prvy parameter - hodnota vysielana na RS232 out UDR,temp0 ;vysli data na UARTWaitForRS232Send: sbis UCR,TXEN ;ak nie je povoleny UART vysielac rjmp OneZeroAnswer ;tak skonci - ochrana kvoli zacykleniu v AT90S2323/2343 sbis USR,TXC ;pockat na dovysielanie bytu rjmp WaitForRS232Send rjmp OneZeroAnswer ;potvrd prijem jednou nulouDoRS232Read: sbis USR,RXC ;ak je prijimaci register prazdny rjmp TwoZeroAnswer ;tak iba potvrd prijem dvoma nulami in R0,UDR ;inak nacitaj do R0 prijate data z UART-u ldi ZL,0 ;posiela sa hodnota v R0 ldi temp0,0x81 ;RAMread=1 - cita sa z RAM-ky mov RAMread,temp0 ;(najvyssi bit na 1 - aby sa hned premenna RAMread znulovala) ldi temp0,1 ;posli iba jeden byte sbic USR,OR ;ak bolo pretecenie prijimacieho buffera ldi temp0,3 ;posli 3 byty :prvy je prijata hodnota (na ostatnych nezalezi) rjmp ComposeEndXXXDescriptor ;tak priprav data;----------------------------- END USER FUNCTIONS ----------------------------------OneZeroAnswer: ;posle jednu nulu ldi temp0,1 ;pocet mojich bytovych odpovedi do temp0 rjmp ComposeGET_STATUS2StandardRequest: cpi temp1,GET_STATUS ; breq ComposeGET_STATUS ; cpi temp1,CLEAR_FEATURE ; breq ComposeCLEAR_FEATURE ; cpi temp1,SET_FEATURE ; breq ComposeSET_FEATURE ; cpi temp1,SET_ADDRESS ;ak sa ma nastavit adresa breq ComposeSET_ADDRESS ;nastav adresu cpi temp1,GET_DESCRIPTOR ;ak sa ziada descriptor breq ComposeGET_DESCRIPTOR ;vygeneruj ho
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -