📄 usb90s23x3.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 MAXINFRALENGTH =36 ;maximalna dlzka Infra kodu (pocet jednotiek a nul spolu) (pozor: MAXINFRALENGTH musi byt parne cislo !!!).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 InfraBufferBegin =InputShiftBufferBegin+MAXUSBBYTES ;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 INT1addr ;externe prerusenie INT1 (pre AT89S2323 je tu Timer0 prerusenie) sei ;povol interrupty na obsluhu USB in backupSREGTimer,SREG rjmp OVF0handler2323 ;na kompatibilitu s AT89S2323 sa skoci na pretecenie casovaca T0;------------------------------------------------------------------------------------------;********************************************************************;* Timer0 interrupt handler;********************************************************************.org OVF0addr ;citac/casovac 0OVF0handler: sei ;povol interrupty na obsluhu USB in backupSREGTimer,SREGOVF0handler2323: push temp0 ldi temp0,0<<TOIE0 ;zakazat interrupt od casovaca out TIMSK,temp0 ldi temp0,5 ;nastav clock input na CLK/1024 = tick kazdych 0.0853ms out TCCR0,temp0 push temp1 push temp2 push temp3 clr temp2 ;vynulovanie offsetu v bufferi (a flagu pretecenia) ldi temp3,1 ;timeout - plnenie citaca (pre prve bity iny ako pre dalsie bity: aby sa nikdy nevyslala dlzka kodu 255, tak sa musi plnit aspon na 1)StartTSOPsampling: ldi InfraBufptrX,InfraBufferBegin+3 ;nastavenie sa na zaciatok buffera Infra kodu + 3byty hlavicky (dlzka kodu + counter + offset) clr temp1 ;vynulovanie dlzky Infra koduWaitForTOSOP1: sbis TSOPPort,TSOPPin ;ak je TSOPPin v nule rjmp CheckWaitForTOSOP1 ;tak cakaj na jednotku rjmp StoreToInfraBufferWaitForTOSOP0: sbic TSOPPort,TSOPPin ;ak je TSOPPin v jednotke rjmp CheckWaitForTOSOP0 ;tak cakaj na nuluStoreToInfraBuffer: in temp0,TCNT0 ;odchyt citac sub temp0,temp3 ;koriguj odchyteny citac vzhladom na jeho plnenie cpi temp1,NumberOfFirstBits ;ak este neboli prve bity brne WasNotFirstBits ;tak nechaj plnenie citaca na nule ldi temp3,NoFirstBitsTimerOffset ;inak zmen plnenie citacaWasNotFirstBits: out TCNT0,temp3 ;nastav citac aby bol ako casovac out UDR,temp0 ;vysli data na UART cpi InfraBufferFull,0 ;ak je infra buffer plny brne NoStoreToInfraBuffer ;tak neukladaj data sbrs RAMread,0 ;ak RAMread=1 cita sa z RAM - potom neukladaj data st X+,temp0 ;a uloz ho do bufferaNoStoreToInfraBuffer: inc temp1 ;zvys dlzku Infra Buffera cpi temp1,MAXINFRALENGTH ;ak sa nedosiahol maximum Infra buffera brne NoTSOPoverflow ;tak pokracuj inc temp2 ;inak si poznac ze pretiekol cpi temp2,3 ;ak boli uz 3 pretecenia dec temp1 ;tak uber posledny bit breq EndInfraSampling ;a skonci so samplovanim rjmp StartTSOPsampling ;a zacni odznova (pozor: MAXINFRALENGTH musi byt parne cislo !!!)NoTSOPoverflow: sbic TSOPPort,TSOPPin ;ak je TSOPPin v jednotke rjmp WaitForTOSOP0 ;tak cakaj na nulu ;inak cakaj na jednotkuCheckWaitForTOSOP1: in temp0,TIFR ;odchyt flag pretecenia citaca sbrc temp0,TOV0 ;ak pretiekol rjmp EndInfraSampling ;tak skonci so samplovanim rjmp WaitForTOSOP1 ;inak cakaj na zmenu stavuCheckWaitForTOSOP0: in temp0,TIFR ;odchyt flag pretecenia citaca sbrc temp0,TOV0 ;ak pretiekol rjmp EndInfraSampling ;tak skonci so samplovanim rjmp WaitForTOSOP0 ;inak cakaj na zmenu stavuEndInfraSampling: sbrs InfraBufferFull,0 ;ak je infra buffer plny - tak neukladaj hlavicku sbrc RAMread,0 ;ak RAMread=1 cita sa z RAM rjmp EndTSOPSampling ;potom neukladaj hlavicku cpi temp2,0 ;ak nebolo nejake pretecenie breq NoOverflow ;tak nic nerob mov temp2,temp1 ;inak zaznamenaj offset ldi temp1,MAXINFRALENGTH ;a maximalnu dlzku bufferaNoOverflow: sts InfraBufferBegin,temp1 ;dlzku kodu na zaciatok Infra buffera cpi temp1,3 ;zisti ci je dlzka kodu aspon 3 lds temp1,InfraBufferBegin+1;nacitaj pocitadlo infra kodov brcs NoIncrementCodeCounter ;ak je dlzka kodu vacsia alebo rovna 3 inc temp1 ;tak zvys pocitadlo infra kodov ldi InfraBufferFull,1 ;a nastav plnost bufferaNoIncrementCodeCounter: sts InfraBufferBegin+1,temp1;uloz nove pocitadlo infra kodov sts InfraBufferBegin+2,temp2;uloz offset zaciatku bufferaEndTSOPSampling: pop temp3 pop temp2 pop temp1 ldi temp0,0xFF ;napln temp0 hodnotou 0xFF (ukoncovaci znak) out UDR,temp0 ;a vysli ukoncovaci znak na UART out SREG,backupSREGTimer ;obnova SREG (a sucasne povolenie interruptu) rcall InitCounter ;restartni citac na TSOP zmenu a zakaz interrupt pop temp0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -