📄 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 R4 =4
.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 0
OVF0handler:
sei ;povol interrupty na obsluhu USB
in backupSREGTimer,SREG
OVF0handler2323:
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 kodu
WaitForTOSOP1:
sbis TSOPPort,TSOPPin ;ak je TSOPPin v nule
rjmp CheckWaitForTOSOP1 ;tak cakaj na jednotku
rjmp StoreToInfraBuffer
WaitForTOSOP0:
sbic TSOPPort,TSOPPin ;ak je TSOPPin v jednotke
rjmp CheckWaitForTOSOP0 ;tak cakaj na nulu
StoreToInfraBuffer:
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 citaca
WasNotFirstBits:
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 buffera
NoStoreToInfraBuffer:
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 jednotku
CheckWaitForTOSOP1:
in temp0,TIFR ;odchyt flag pretecenia citaca
sbrc temp0,TOV0 ;ak pretiekol
rjmp EndInfraSampling ;tak skonci so samplovanim
rjmp WaitForTOSOP1 ;inak cakaj na zmenu stavu
CheckWaitForTOSOP0:
in temp0,TIFR ;odchyt flag pretecenia citaca
sbrc temp0,TOV0 ;ak pretiekol
rjmp EndInfraSampling ;tak skonci so samplovanim
rjmp WaitForTOSOP0 ;inak cakaj na zmenu stavu
EndInfraSampling:
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 buffera
NoOverflow:
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 buffera
NoIncrementCodeCounter:
sts InfraBufferBegin+1,temp1;uloz nove pocitadlo infra kodov
sts InfraBufferBegin+2,temp2;uloz offset zaciatku buffera
EndTSOPSampling:
pop temp3
pop temp2
pop temp1
ldi temp0,0xFF ;napln temp0 hodnotou 0xFF (ukoncovaci znak)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -