📄 usb-prog.asm
字号:
;***************************************************************************;* U S B S T A C K F O R T H E A V R F A M I L Y;* ;* File Name :"USB90S2313.asm";* Title :USB stack + Infrared remote control to nonUSB MCU;* Date :5.4.2003;* Version :1.6;* Target MCU :AT90S2313-10,AT90S2323-10,AT90S2343-10;* AUTHOR :Ing. Igor Cesko;* Slovakia;* cesko@internet.sk;* http://www.cesko.host.sk;*;* DESCRIPTION:;* USB protocol implementation into MCU with noUSB interface:;* Device:;* Infrared remote control with TSOP17xx/SFH511x sensor and USB connection;* + Universal USB interface (8-bit I/O port + RS232 serial line + EEPROM);*;* The timing is adapted for 12 MHz crystal (overclocked MCU !!!);*;* Copyright (c) Ing. Igor Cesko 2002-2003;*;* This program is free software; you can redistribute it and/or modify;* it under the terms of the GNU General Public License as published by;* the Free Software Foundation; either version 2 of the License, or;* (at your option) any later version.;*;* This program is distributed in the hope that it will be useful,;* but WITHOUT ANY WARRANTY; without even the implied warranty of;* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;* GNU General Public License for more details.;*;* You should have received a copy of the GNU General Public License;* along with this program; if not, write to the Free Software;* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.;*;***************************************************************************;***************************************************************************.include "2313def.inc".equ inputport =PINB.equ outputport =PORTB.equ USBdirection =DDRB.equ DATAplus =1 ;signal D+ na PB1.equ DATAminus =0 ;signal D- na PB0 - treba dat na tento pin pull-up 1.5kOhm.equ USBpinmask =0b11111100 ;mask low 2 bits (D+,D-) on PB.equ USBpinmaskDplus =~(1<<DATAplus) ;mask D+ bit on PB.equ USBpinmaskDminus =~(1<<DATAminus);mask D- bit on PB.equ TSOPPort =PINB.equ TSOPpullupPort =PORTB.equ TSOPPin =2 ;signal OUT z IR senzora TSOP1738 na PB2.equ LEDPortLSB =PORTD ;pripojenie LED diod LSB.equ LEDPinLSB =PIND ;pripojenie LED diod LSB (vstup).equ LEDdirectionLSB =DDRD ;vstup/vystup LED LSB.equ LEDPortMSB =PORTB ;pripojenie LED diod MSB.equ LEDPinMSB =PINB ;pripojenie LED diod MSB (vstup).equ LEDdirectionMSB =DDRB ;vstup/vystup LED MSB.equ LEDlsb0 =3 ;LED0 na pin PD3.equ LEDlsb1 =5 ;LED1 na pin PD5.equ LEDlsb2 =6 ;LED2 na pin PD6.equ LEDmsb3 =3 ;LED3 na pin PB3.equ LEDmsb4 =4 ;LED4 na pin PB4.equ LEDmsb5 =5 ;LED5 na pin PB5.equ LEDmsb6 =6 ;LED6 na pin PB6.equ LEDmsb7 =7 ;LED7 na pin PB7.equ SOPbyte =0b10000000 ;Start of Packet byte.equ DATA0PID =0b11000011 ;PID pre DATA0 pole.equ DATA1PID =0b01001011 ;PID pre DATA1 pole.equ OUTPID =0b11100001 ;PID pre OUT pole.equ INPID =0b01101001 ;PID pre IN pole.equ SOFPID =0b10100101 ;PID pre SOF pole.equ SETUPPID =0b00101101 ;PID pre SETUP pole.equ ACKPID =0b11010010 ;PID pre ACK pole.equ NAKPID =0b01011010 ;PID pre NAK pole.equ STALLPID =0b00011110 ;PID pre STALL pole.equ PREPID =0b00111100 ;PID pre PRE pole.equ nSOPbyte =0b00000001 ;Start of Packet byte - opacne poradie.equ nDATA0PID =0b11000011 ;PID pre DATA0 pole - opacne poradie.equ nDATA1PID =0b11010010 ;PID pre DATA1 pole - opacne poradie.equ nOUTPID =0b10000111 ;PID pre OUT pole - opacne poradie.equ nINPID =0b10010110 ;PID pre IN pole - opacne poradie.equ nSOFPID =0b10100101 ;PID pre SOF pole - opacne poradie.equ nSETUPPID =0b10110100 ;PID pre SETUP pole - opacne poradie.equ nACKPID =0b01001011 ;PID pre ACK pole - opacne poradie.equ nNAKPID =0b01011010 ;PID pre NAK pole - opacne poradie.equ nSTALLPID =0b01111000 ;PID pre STALL pole - opacne poradie.equ nPREPID =0b00111100 ;PID pre PRE pole - opacne poradie.equ nNRZITokenPID =~0b10000000 ;PID maska pre Token paket (IN,OUT,SOF,SETUP) - opacne poradie NRZI.equ nNRZISOPbyte =~0b10101011 ;Start of Packet byte - opacne poradie NRZI.equ nNRZIDATA0PID =~0b11010111 ;PID pre DATA0 pole - opacne poradie NRZI.equ nNRZIDATA1PID =~0b11001001 ;PID pre DATA1 pole - opacne poradie NRZI.equ nNRZIOUTPID =~0b10101111 ;PID pre OUT pole - opacne poradie NRZI.equ nNRZIINPID =~0b10110001 ;PID pre IN pole - opacne poradie NRZI.equ nNRZISOFPID =~0b10010011 ;PID pre SOF pole - opacne poradie NRZI.equ nNRZISETUPPID =~0b10001101 ;PID pre SETUP pole - opacne poradie NRZI.equ nNRZIACKPID =~0b00100111 ;PID pre ACK pole - opacne poradie NRZI.equ nNRZINAKPID =~0b00111001 ;PID pre NAK pole - opacne poradie NRZI.equ nNRZISTALLPID =~0b00000111 ;PID pre STALL pole - opacne poradie NRZI.equ nNRZIPREPID =~0b01111101 ;PID pre PRE pole - opacne poradie NRZI.equ nNRZIADDR0 =~0b01010101 ;Adresa = 0 - opacne poradie NRZI ;stavove byty - State.equ BaseState =0 ;.equ SetupState =1 ;.equ InState =2 ;.equ OutState =3 ;.equ SOFState =4 ;.equ DataState =5 ; ;Flagy pozadovanej akcie.equ DoNone =0.equ DoReceiveOutData =1.equ DoReceiveSetupData =2.equ DoPrepareOutContinuousBuffer =3.equ DoReadySendAnswer =4.equ CRC5poly =0b00101 ;CRC5 polynom.equ CRC5zvysok =0b01100 ;CRC5 zvysok po uspesnpm CRC5.equ CRC16poly =0b1000000000000101 ;CRC16 polynom.equ CRC16zvysok =0b1000000000001101 ;CRC16 zvysok po uspesnom CRC16.equ MAXUSBBYTES =14 ;maximum bytes in USB input message.equ NumberOfFirstBits =10 ;kolko prvych bitov moze byt dlhsich.equ NoFirstBitsTimerOffset =256-12800*12/1024 ;Timeout 12.8ms (12800us) na ukoncenie prijmu po uvodnych bitoch (12Mhz:clock, 1024:timer predivider, 256:timer overflow value).equ BaudRate =12000000/16/57600-1 ;nastavit vysielaciu rychlost UART-u na 57600 (pre 12MHz=12000000Hz).equ InputBufferBegin =RAMEND-127 ;zaciatok prijimacieho shift buffera.equ InputShiftBufferBegin =InputBufferBegin+MAXUSBBYTES ;zaciatok prijimacieho buffera.equ SPIBuffer =InputShiftBufferBegin+MAXUSBBYTES ; location of SPI return value buffer ;was zaciatok buffera pre Infra prijem.equ OutputBufferBegin =RAMEND-MAXUSBBYTES-2 ;zaciatok vysielacieho buffera.equ AckBufferBegin =OutputBufferBegin-3 ;zaciatok vysielacieho buffera Ack.equ NakBufferBegin =AckBufferBegin-3 ;zaciatok vysielacieho buffera Nak.equ StackBegin =NakBufferBegin-1 ;spodok zasobnika.def ConfigByte =R1 ;0=unconfigured state.def backupbitcount =R2 ;zaloha bitcount registra v INT0 preruseni.def RAMread =R3 ;ci sa ma citat zo SRAM-ky.def backupSREGTimer =R4 ;zaloha Flag registra v Timer interrupte.def backupSREG =R5 ;zaloha Flag registra v INT0 preruseni.def ACC =R6 ;accumulator.def lastBitstufNumber =R7 ;pozicia bitstuffingu.def OutBitStuffNumber =R8 ;kolko bitov sa ma este odvysielat z posledneho bytu - bitstuffing.def BitStuffInOut =R9 ;ci sa ma vkladat alebo mazat bitstuffing.def TotalBytesToSend =R10 ;kolko sa ma poslat bytov.def TransmitPart =R11 ;poradove cislo vysielacej casti.def InputBufferLength =R12 ;dlzka pripravena vo vstupnom USB bufferi.def OutputBufferLength =R13 ;dlzka odpovede pripravena v USB bufferi.def MyUpdatedAddress =R14 ;moja USB adresa na update.def MyAddress =R15 ;moja USB adresa.def ActionFlag =R16 ;co sa ma urobit v hlavnej slucke programu.def temp3 =R17 ;temporary register.def temp2 =R18 ;temporary register.def temp1 =R19 ;temporary register.def temp0 =R20 ;temporary register.def bitcount =R21 ;counter of bits in byte.def ByteCount =R22 ;pocitadlo maximalneho poctu prijatych bajtov.def inputbuf =R23 ;prijimaci register.def shiftbuf =R24 ;posuvny prijimaci register.def State =R25 ;byte stavu stavoveho stroja.def InfraBufptrX =R26 ;XL register - pointer do buffera prijatych IR kodov.def InfraBufferFull =R27 ;XH register - priznak plneho Infra Buffera.def USBBufptrY =R28 ;YL register - pointer do USB buffera input/output.def ROMBufptrZ =R30 ;ZL register - pointer do buffera ROM dat;poziadavky na deskriptory.equ GET_STATUS =0.equ CLEAR_FEATURE =1.equ SET_FEATURE =3.equ SET_ADDRESS =5.equ GET_DESCRIPTOR =6.equ SET_DESCRIPTOR =7.equ GET_CONFIGURATION =8.equ SET_CONFIGURATION =9.equ GET_INTERFACE =10.equ SET_INTERFACE =11.equ SYNCH_FRAME =12;typy deskriptorov.equ DEVICE =1.equ CONFIGURATION =2.equ STRING =3.equ INTERFACE =4.equ ENDPOINT =5;------------------------------------------------------------------------------------------;********************************************************************;* Interrupt table;********************************************************************.cseg;------------------------------------------------------------------------------------------.org 0 ;po resete rjmp reset;------------------------------------------------------------------------------------------.org INT0addr ;externe prerusenie INT0 rjmp INT0handler;------------------------------------------------------------------------------------------.org OVF0addr ;citac/casovac 0OVF0handler: reti;********************************************************************;* Init program;********************************************************************;------------------------------------------------------------------------------------------reset: ;inicializacia procesora a premennych na spravne hodnoty ldi temp0,StackBegin ;inicializacia stacku out SPL,temp0 clr XH ;was Infra pointer clr YH ;USB pointer clr ZH ;ROM pointer clr MyUpdatedAddress ;nova adresa USB - nedekodovana rcall InitACKBufffer ;inicializacia ACK buffera rcall InitNAKBufffer ;inicializacia NAK buffera rcall USBReset ;inicializacia USB adresy ; 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;------------------------------------------------------------------------------------------;********************************************************************;* 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -