📄 usb-prog.asm
字号:
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 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;--------------------------VendorRequest: clr ZH ;pre citanie z RAM alebo EEPROM 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 cpi temp1, 15 breq DoSPI4 rjmp ZeroDATA1Answer ;ak to bolo nieco nezname, tak priprav nulovu odpoved;----------------------------- USER FUNCTIONS --------------------------------------DoLcdData: sbr ZH, 0x10 ;commandDoLcdCommand: lds ZL,InputBufferBegin+4 ;prvy parameter rcall LcdWrite rjmp OneZeroAnswerDoEEPROMRead: 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 DoSPI4: lds ZH,InputBufferBegin+4 rcall SPI1 sts SPIBuffer, ZL lds ZH,InputBufferBegin+5 rcall SPI1 sts SPIBuffer+2, ZL lds ZH,InputBufferBegin+6 rcall SPI1 sts SPIBuffer+2, ZL lds ZH,InputBufferBegin+7 rcall SPI1 sts SPIBuffer+3, ZL ldi ZL, SPIBuffer ldi temp0, 0x81 mov RAMread, temp0 ldi temp0, 4 rjmp ComposeEndXXXDescriptor.equ SLAVE_PIN = PINB.equ SLAVE_PORT = PORTB.equ SLAVE_SCK_MASK = PB7.equ SLAVE_MISO_MASK = PB6.equ SLAVE_MOSI_MASK = PB5.equ SLAVE_RESET_MASK = PB4.equ SLAVE_SCK = 7.equ SLAVE_MISO = 6.equ SLAVE_MOSI = 5SPI1:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -