📄 usb90s2313.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 :AVR309:USB to UART protocol converter (simple - small FIFO)
;* Date :26.01.2004
;* Version :2.2
;* Target MCU :AT90S2313-10
;* AUTHOR :Ing. Igor Cesko
;* Slovakia
;* cesko@internet.sk
;* http://www.cesko.host.sk
;*
;* DESCRIPTION:
;* USB protocol implementation into MCU with noUSB interface:
;* Device:
;* Universal USB interface (8-bit I/O port + RS232 serial line + EEPROM)
;* + added RS232 FIFO buffer
;*
;* The timing is adapted for 12 MHz crystal (overclocked MCU !!!)
;*
;*
;* to add your own functions - see section: TEMPLATE OF YOUR FUNCTION
;*
;* to customize device to your company you must change VendorUSB ID (VID)
;* to VID assigned to your company (for more information see www.usb.org)
;*
;***************************************************************************
.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 ;
.equ AddressChangeState =6 ;
;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 MAXRS232LENGTH =36 ;maximalna dlzka RS232 kodu (pocet jednotiek a nul spolu) (pozor: MAXRS232LENGTH 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 InitBaudRate =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 RS232BufferBegin =InputShiftBufferBegin+MAXUSBBYTES ;zaciatok buffera pre RS232 prijem
.equ MyInAddressSRAM =RS232BufferBegin+MAXRS232LENGTH+1
.equ MyOutAddressSRAM =MyInAddressSRAM+1
.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 MyOutAddress =R14 ;moja USB adresa na update
.def MyInAddress =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 RS232BufptrX =R26 ;XL register - pointer do buffera prijatych IR kodov
.def RS232BufferFull =R27 ;XH register - priznak plneho RS232 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
.equ USER_FNC_NUMBER =100
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt table
;********************************************************************
.cseg
;------------------------------------------------------------------------------------------
.org 0 ;po resete
rjmp reset
;------------------------------------------------------------------------------------------
.org INT0addr ;externe prerusenie INT0
rjmp INT0handler
;------------------------------------------------------------------------------------------
.org URXCaddr ;prijem zo seriovej linky
push temp0
in temp0,UDR ;nacitaj do temp0 prijate data z UART-u
sei ;povol interrupty na obsluhu USB
in backupSREGTimer,SREG ;zaloha SREG
cbi UCR,RXCIE ;zakazat interrupt od prijimania UART
cpi RS232BufferFull,MAXRS232LENGTH-4
brcc NoIncRS232BufferFull
push RS232BufptrX
lds RS232BufptrX,RS232BufferBegin+2 ;nastavenie sa na zaciatok buffera zapisu RS232 kodu : 3.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
st X+,temp0 ;a uloz ho do buffera
cpi RS232BufptrX,RS232BufferBegin+MAXRS232LENGTH+1 ;ak sa nedosiahol maximum RS232 buffera
brne NoUARTBufferOverflow ;tak pokracuj
ldi RS232BufptrX,RS232BufferBegin+4 ;inak sa nastav na zaciatok buffera
NoUARTBufferOverflow:
sts RS232BufferBegin+2,RS232BufptrX ;ulozenie noveho offsetu buffera zapisu RS232 kodu : 3.byte hlavicky (dlzka kodu + citanie + zapis + rezerva)
inc RS232BufferFull ;zvys dlzku RS232 Buffera
pop RS232BufptrX
NoIncRS232BufferFull:
pop temp0
out SREG,backupSREGTimer ;obnova SREG
cli ;zakazat interrupt kvoli zacykleniu
sbi UCR,RXCIE ;povolit interrupt od prijimania UART
reti
;------------------------------------------------------------------------------------------
;********************************************************************
;* Init program
;********************************************************************
;------------------------------------------------------------------------------------------
reset: ;inicializacia procesora a premennych na spravne hodnoty
ldi temp0,StackBegin ;inicializacia stacku
out SPL,temp0
clr XH ;RS232 pointer
clr YH ;USB pointer
clr ZH ;ROM pointer
sts RS232BufferBegin+0,YH ;znuluj dlzky RS232 kodu v bufferi
ldi temp0,RS232BufferBegin+4
sts RS232BufferBegin+1,temp0;znuluj ukazovatel citania
sts RS232BufferBegin+2,temp0;znuluj ukazovatel zapisu
clr RS232BufferFull
rcall InitACKBufffer ;inicializacia ACK buffera
rcall InitNAKBufffer ;inicializacia NAK buffera
rcall USBReset ;inicializacia USB adresy
sbi TSOPpullupPort,TSOPpin ;nahodit pull-up na TSOP vstupe
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,InitBaudRate ;nastavitvysielaciu rychlost UART-u
out UBRR,temp0
sbi UCR,TXEN ;povolit vysielanie UART-u
sbi UCR,RXEN ;povolit prijimanie UART-u
sbi UCR,RXCIE ;povolit interrupt od prijimania UART
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 globalne
Main:
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 Main
CheckUSBReset:
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 Main
ProcPrepareOutContinuousBuffer:
rcall PrepareOutContinuousBuffer ;priprav pokracovanie odpovede do buffera
ldi ActionFlag,DoReadySendAnswer
rjmp Main
ProcReceiveSetupData:
ldi USBBufptrY,InputBufferBegin ;pointer na zaciatok prijimacieho buffera
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -