📄 usb-prog.asm
字号:
clr ZL ldi temp2,8 in temp3, SLAVE_PORTSPILoop: LSL ZL ; bits go to bottom of ZL (yes, you read a bit here!) in temp0, SLAVE_PIN ; read MISO from slave (in temp0 and R0) bst temp0, SLAVE_MISO_MASK ; pick MISO out bld ZL, 0 ; store in the low bit (will be shifted left enough) bst ZH, 7 ; take the high bit from ZH (or bit shifted there) bld temp3, SLAVE_MOSI_MASK ; set MOSI from ZH cbr temp3, SLAVE_SCK_MASK ; turn off sck (it should have already been off!) out SLAVE_PORT, temp3 ; and do it sbi SLAVE_PORT, SLAVE_SCK rcall SPIDelay cbi SLAVE_PORT, SLAVE_SCK rcall SPIDelay LSL ZH ; shift output byte dec temp2 ; and loop brne SPILoop retSPIDelay: nop ; In theory length of SCK strobe depends on programmed device's clock nop ; I know I'm programming at90s2313 also at 12MHz nop ; and I will find the right count empirically ret;----------------------------- END USER FUNCTIONS ----------------------------------LcdWrite: push ZL swap ZL rcall LcdNibble pop ZLLcdNibble: andi ZL, 0xf or ZL, ZH mov ACC, ZL rcall SetOutDataPort sbr ZL, 0x20 mov ACC, ZL rcall SetOutDataPort cbr ZL, 0x20 mov ACC, ZL rcall SetOutDataPort retOneZeroAnswer: ;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 cpi temp1,SET_DESCRIPTOR ; breq ComposeSET_DESCRIPTOR ; cpi temp1,GET_CONFIGURATION ; breq ComposeGET_CONFIGURATION ; cpi temp1,SET_CONFIGURATION ; breq ComposeSET_CONFIGURATION ; cpi temp1,GET_INTERFACE ; breq ComposeGET_INTERFACE ; cpi temp1,SET_INTERFACE ; breq ComposeSET_INTERFACE ; cpi temp1,SYNCH_FRAME ; breq ComposeSYNCH_FRAME ; ;ak sa nenasla znama poziadavka rjmp ZeroDATA1Answer ;ak to bolo nieco nezname, tak priprav nulovu odpovedComposeSET_ADDRESS: lds MyUpdatedAddress,InputBufferBegin+4 ;nova adresa do MyUpdatedAddress rjmp ZeroDATA1Answer ;posli nulovu odpovedComposeSET_CONFIGURATION: lds ConfigByte,InputBufferBegin+4 ;cislo konfiguracie do premennej ConfigByteComposeCLEAR_FEATURE:ComposeSET_FEATURE:ComposeSET_INTERFACE:ZeroStringAnswer: rjmp ZeroDATA1Answer ;posli nulovu odpovedComposeGET_STATUS:TwoZeroAnswer: ldi temp0,2 ;pocet mojich bytovych odpovedi do temp0ComposeGET_STATUS2: ldi ZH, high(StatusAnswer<<1) ;ROMpointer na odpoved ldi ZL, low(StatusAnswer<<1) rjmp ComposeEndXXXDescriptor ;a dokonciComposeGET_CONFIGURATION: and ConfigByte,ConfigByte ;ak som nenakonfigurovany breq OneZeroAnswer ;tak posli jednu nulu - inak posli moju konfiguraciu ldi temp0,1 ;pocet mojich bytovych odpovedi do temp0 ldi ZH, high(ConfigAnswerMinus1<<1) ;ROMpointer na odpoved ldi ZL, low(ConfigAnswerMinus1<<1)+1 rjmp ComposeEndXXXDescriptor ;a dokonciComposeGET_INTERFACE: ldi ZH, high(InterfaceAnswer<<1) ;ROMpointer na odpoved ldi ZL, low(InterfaceAnswer<<1) ldi temp0,1 ;pocet mojich bytovych odpovedi do temp0 rjmp ComposeEndXXXDescriptor ;a dokonciComposeSYNCH_FRAME:ComposeSET_DESCRIPTOR: rcall ComposeSTALL retComposeGET_DESCRIPTOR: lds temp1,InputBufferBegin+5 ;DescriptorType do temp1 cpi temp1,DEVICE ;DeviceDescriptor breq ComposeDeviceDescriptor ; cpi temp1,CONFIGURATION ;ConfigurationDescriptor breq ComposeConfigDescriptor ; cpi temp1,STRING ;StringDeviceDescriptor breq ComposeStringDescriptor ; retComposeDeviceDescriptor: ldi ZH, high(DeviceDescriptor<<1) ;ROMpointer na descriptor ldi ZL, low(DeviceDescriptor<<1) ldi temp0,0x12 ;pocet mojich bytovych odpovedi do temp0 rjmp ComposeEndXXXDescriptor ;a dokonciComposeConfigDescriptor: ldi ZH, high(ConfigDescriptor<<1) ;ROMpointer na descriptor ldi ZL, low(ConfigDescriptor<<1) ldi temp0,9+9+7 ;pocet mojich bytovych odpovedi do temp0ComposeEndXXXDescriptor: lds TotalBytesToSend,InputBufferBegin+8 ;pocet pozadovanych bytov do TotalBytesToSend cp TotalBytesToSend,temp0 ;ak sa neziada viac ako mozem dodat brcs HostConfigLength ;vysli tolko kolko sa ziada mov TotalBytesToSend,temp0 ;inak posli pocet mojich odpovediHostConfigLength: mov temp0,TotalBytesToSend ; clr TransmitPart ;nuluj pocet 8 bytovych odpovedi andi temp0,0b00000111 ;ak je dlzka delitelna 8-mimi breq Length8Multiply ;tak nezapocitaj jednu necelu odpoved (pod 8 bytov) inc TransmitPart ;inak ju zapocitajLength8Multiply: mov temp0,TotalBytesToSend ; lsr temp0 ;dlzka 8 bytovych odpovedi sa dosiahne lsr temp0 ;delenie celociselne 8-mimi lsr temp0 add TransmitPart,temp0 ;a pripocitanim k poslednej necelej 8-mici do premennej TransmitPart ldi temp0,DATA0PID ;DATA0 PID - v skutocnosti sa stoggluje na DATA1PID v nahrati deskriptora sts OutputBufferBegin+1,temp0 ;nahraj do vyst buffera rjmp ComposeNextAnswerPartComposeStringDescriptor: ldi temp1,4+8 ;ak RAMread=4(vkladaj nuly z ROM-koveho citania) + 8(za prvy byte nevkldadaj nulu) mov RAMread,temp1 lds temp1,InputBufferBegin+4 ;DescriptorIndex do temp1 cpi temp1,0 ;LANGID String breq ComposeLangIDString ; cpi temp1,2 ;DevNameString breq ComposeDevNameString ; brcc ZeroStringAnswer ;ak je DescriptorIndex vyssi nez 2 - posli nulovu odpoved ;inak to bude VendorStringComposeVendorString: ldi ZH, high(VendorStringDescriptor<<1) ;ROMpointer na descriptor ldi ZL, low(VendorStringDescriptor<<1) ldi temp0,(VendorStringDescriptorEnd-VendorStringDescriptor)*4-2 ;pocet mojich bytovych odpovedi do temp0 rjmp ComposeEndXXXDescriptor ;a dokonciComposeDevNameString: ldi ZH, high(DevNameStringDescriptor<<1) ;ROMpointer na descriptor ldi ZL, low(DevNameStringDescriptor<<1) ldi temp0,(DevNameStringDescriptorEnd-DevNameStringDescriptor)*4-2 ;pocet mojich bytovych odpovedi do temp0 rjmp ComposeEndXXXDescriptor ;a dokonciComposeLangIDString: clr RAMread ldi ZH, high(LangIDStringDescriptor<<1) ;ROMpointer na descriptor ldi ZL, low(LangIDStringDescriptor<<1) ldi temp0,(LangIDStringDescriptorEnd-LangIDStringDescriptor)*2;pocet mojich bytovych odpovedi do temp0 rjmp ComposeEndXXXDescriptor ;a dokonci;------------------------------------------------------------------------------------------ZeroDATA1Answer: rcall ComposeZeroDATA1PIDAnswer ret;------------------------------------------------------------------------------------------PrepareOutContinuousBuffer: rcall PrepareContinuousBuffer rcall MakeOutBitStuff ret;------------------------------------------------------------------------------------------PrepareContinuousBuffer: mov temp0,TransmitPart cpi temp0,1 brne NextAnswerInBuffer ;ak uz je buffer prazdny rcall ComposeZeroAnswer ;priprav nulovu odpoved retNextAnswerInBuffer: dec TransmitPart ;znizit celkovu dlzku odpovedeComposeNextAnswerPart: mov temp1,TotalBytesToSend ;zniz pocet bytov na vyslanie subi temp1,8 ;ci je este treba poslat viac ako 8 bytov ldi temp3,8 ;ak ano - posli iba 8 bytov brcc Nad8Bytov mov temp3,TotalBytesToSend ;inak posli iba dany pocet bytov clr TransmitPart inc TransmitPart ;a bude to posledna odpovedNad8Bytov: mov TotalBytesToSend,temp1 ;znizeny pocet bytov do TotalBytesToSend rcall LoadXXXDescriptor ldi ByteCount,2 ;dlzka vystupneho buffera (iba SOP a PID) add ByteCount,temp3 ;+ pocet bytov rcall AddCRCOut ;pridanie CRC do buffera inc ByteCount ;dlzka vystupneho buffera + CRC16 inc ByteCount ret ;skonci;------------------------------------------------------------------------------------------.equ USBversion =0x0100 ;pre aku verziu USB je to (1.00).equ VendorUSBID =0x03EB ;identifikator dodavatela (Atmel=0x03EB).equ DeviceUSBID =0x0002 ;identifikator vyrobku (USB dialkove ovladanie=0x0002).equ DeviceVersion =0x0001 ;cislo verzie vyrobku (verzia=0.01).equ MaxUSBCurrent =40 ;prudovy odber z USB (40mA);------------------------------------------------------------------------------------------DeviceDescriptor: .db 0x12,0x01 ;0 byte - velkost deskriptora v bytoch ;1 byte - typ deskriptora: Deskriptor zariadenia .dw USBversion ;2,3 byte - verzia USB LSB (1.00) .db 0x00,0x00 ;4 byte - trieda zariadenia ;5 byte - podtrieda zariadenia .db 0x00,0x08 ;6 byte - kod protokolu ;7 byte - velkost FIFO v bytoch .dw VendorUSBID ;8,9 byte - identifikator dodavatela (Cypress=0x04B4) .dw DeviceUSBID ;10,11 byte - identifikator vyrobku (teplomer=0x0002) .dw DeviceVersion ;12,13 byte - cislo verzie vyrobku (verzia=0.01) .db 0x01,0x02 ;14 byte - index stringu "vyrobca" ;15 byte - index stringu "vyrobok" .db 0x00,0x01 ;16 byte - index stringu "seriove cislo" ;17 byte - pocet moznych konfiguraciiDeviceDescriptorEnd:;------------------------------------------------------------------------------------------ConfigDescriptor: .db 0x9,0x02 ;dlzka,typ deskriptoruConfigDescriptorLength: .dw 9+9+7 ;celkova dlzka vsetkych deskriptorov ConfigAnswerMinus1: ;pre poslanie cisla congiguration number (pozor je treba este pricitat 1) .db 1,1 ;numInterfaces,congiguration number .db 0,0x80 ;popisny index stringu, atributy;bus powered .db MaxUSBCurrent/2,0x09 ;prudovy odber, interface descriptor length .db 0x04,0 ;interface descriptor; cislo interface InterfaceAnswer: ;pre poslanie cisla alternativneho interface .db 0,1 ;alternativne nastavenie interface; pocet koncovych bodov okrem EP0 StatusAnswer: ;2 nulove odpovede (na usetrenie miestom) .db 0,0 ;trieda rozhrania; podtrieda rozhrania .db 0,0 ;kod protokolu; index popisneho stringu .db 0x07,0x5 ;dlzka,typ deskriptoru - endpoint .db 0x81,0 ;endpoint address; transfer type .dw 0x08 ;max packet size .db 10,0 ;polling interval [ms]; dummy byte (pre vyplnenie)ConfigDescriptorEnd:;------------------------------------------------------------------------------------------LangIDStringDescriptor: .db (LangIDStringDescriptorEnd-LangIDStringDescriptor)*2,3 ;dlzka, typ: string deskriptor .dw 0x0409 ;EnglishLangIDStringDescriptorEnd:;------------------------------------------------------------------------------------------VendorStringDescriptor: .db (VendorStringDescriptorEnd-VendorStringDescriptor)*4-2,3 ;dlzka, typ: string deskriptorCopyRight: .db "Ing. Igor Cesko, Copyright(c) 2003"CopyRightEnd:VendorStringDescriptorEnd:;------------------------------------------------------------------------------------------DevNameStringDescriptor: .db (DevNameStringDescriptorEnd-DevNameStringDescriptor)*4-2,3;dlzka, typ: string deskriptor .db "IgorPlug-USB (AVR)"DevNameStringDescriptorEnd:;------------------------------------------------------------------------------------------MaskPortData: bst ACC,0 bld temp0,LEDlsb0 bst ACC,1 bld temp0,LEDlsb1 bst ACC,2 bld temp0,LEDlsb2 bst ACC,3 bld temp1,LEDmsb3 bst ACC,4 bld temp1,LEDmsb4 bst ACC,5 bld temp1,LEDmsb5 bst ACC,6 bld temp1,LEDmsb6 bst ACC,7 bld temp1,LEDmsb7 ret;------------------------------------------------------------------------------------------SetDataPortDirection: in temp0,LEDdirectionLSB ;nacitaj aktualny stav LSB do temp0 (aby sa nezmenili ostatne smery bitov) in temp1,LEDdirectionMSB ;nacitaj aktualny stav MSB do temp1 (aby sa nezmenili ostatne smery bitov) rcall MaskPortData out LEDdirectionLSB,temp0 ;a update smeru LSB datoveho portu out LEDdirectionMSB,temp1 ;a update smeru MSB datoveho portu ret;------------------------------------------------------------------------------------------SetOutDataPort: in temp0,LEDPortLSB ;nacitaj aktualny stav LSB do temp0 (aby sa nezmenili ostatne bity) in temp1,LEDPortMSB ;nacitaj aktualny stav MSB do temp1 (aby sa nezmenili ostatne bity) rcall MaskPortData out LEDPortLSB,temp0 ;a update LSB datoveho portu out LEDPortMSB,temp1 ;a update MSB datoveho portu ret;------------------------------------------------------------------------------------------GetInDataPort: in temp0,LEDPinMSB ;nacitaj aktualny stav MSB do temp0 in temp1,LEDPinLSB ;nacitaj aktualny stav LSB do temp1MoveLEDin: bst temp1,LEDlsb0 ;a daj bity LSB na spravne pozicie (z temp1 do temp0) bld temp0,0 ;(bity MSB su na spravnom mieste) bst temp1,LEDlsb1 bld temp0,1 bst temp1,LEDlsb2 bld temp0,2 mov R0,temp0 ;a vysledok uloz do R0 ret;------------------------------------------------------------------------------------------GetOutDataPort: in temp0,LEDPortMSB ;nacitaj aktualny stav MSB do temp0 in temp1,LEDPortLSB ;nacitaj aktualny stav LSB do temp1 rjmp MoveLEDin;------------------------------------------------------------------------------------------GetDataPortDirection: in temp0,LEDdirectionMSB ;nacitaj aktualny stav MSB do temp0 in temp1,LEDdirectionLSB ;nacitaj aktualny stav LSB do temp1 rjmp MoveLEDin;------------------------------------------------------------------------------------------EEPROMWrite: out EEAR,ZL ;nastav adresu EEPROM out EEDR,R0 ;nastav data do EEPROM cli ;zakaz prerusenie sbi EECR,EEMWE ;nastav master write enable sei ;povol prerusenie (este sa vykona nasledujuca instrukcia) sbi EECR,EEWE ;samotny zapisWaitForEEPROMReady: sbic EECR,EEWE ;pockaj si na koniec zapisu rjmp WaitForEEPROMReady ;v slucke (max cca 4ms) (kvoli naslednemu citaniu/zapisu) rjmp OneZeroAnswer ;potvrd prijem jednou nulou;------------------------------------------------------------------------------------------;********************************************************************;* End of Program;********************************************************************;------------------------------------------------------------------------------------------;********************************************************************;* EEPROM contents;********************************************************************;------------------------------------------------------------------------------------------.eseg ;data v EEPROM-ke (vo finalnej verzii zapoznamkovat);.org 0x400 ;pre naplnenie EEPROM dat na spravne adresy - hned za kod programu (vo finalnej verzii odpoznamkovat)EEData: .db "This device was developed by Ing. Igor Cesko: cesko@internet.sk " .db "For more information see: http://www.cesko.host.sk. " .db "S/N:00000001";------------------------------------------------------------------------------------------;********************************************************************;* End of file;********************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -