 |
;***************************************************************************
;* 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 :"USBtoRS232.asm"
;* Title :USB stack: USB to RS232 converter + USB to 8-bit I/O pins converter + USB to EEPROM recorder
;* Date :15.09.2003
;* Version :2.4
;* Target MCU :ATmega8
;* 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 (3x8-bit I/O port + RS232 serial line + EEPROM)
;* + added RS232 FIFO buffer
;*
;* The timing is adapted for 12 MHz crystal
;*
;* Copyright (c) Ing. Igor Cesko 2002-2003
;* All rights reserved
;*
;* to add your own functions - see section: TEMPLATE OF YOUR FUNCTION
;*
;***************************************************************************
.include "m8def.inc"
;comment for AT90S2313
.equ UCR =UCSRB
.equ UBRR =UBRRL
.equ EEAR =EEARL
.equ USR =UCSRA
.equ E2END =127
.equ RAMEND128 =96+127
.equ inputport =PINB
.equ outputport =PORTB
.equ USBdirection =DDRB
.equ DATAplus =1 ;signal D+ na PB1 ;ENG;signal D+ on PB1
.equ DATAminus =0 ;signal D- na PB0 - treba dat na tento pin pull-up 1.5kOhm ;ENG;signal D- on PB0 - give on this pin pull-up
1.5kOhm
.equ USBpinmask =0b11111100 ;mask low 2 bits (D+,D-) on PB ;ENG;mask low 2 bit (D+,D-) on PB
.equ USBpinmaskDplus =~(1<<DATAplus) ;mask D+ bit on PB ;ENG;mask D+ bit on PB
.equ USBpinmaskDminus =~(1<<DATAminus);mask D- bit on PB ;ENG;mask D- bit on PB
.equ TSOPPort =PINB
.equ TSOPpullupPort =PORTB
.equ TSOPPin =2 ;signal OUT z IR senzora TSOP1738 na PB2 ;ENG;signal OUT from IR sensor TSOP1738 on PB2
;.equ LEDPortLSB =PORTD ;pripojenie LED diod LSB ;ENG;connecting LED diode LSB
;.equ LEDPinLSB =PIND ;pripojenie LED diod LSB (vstup) ;ENG;connecting LED diode LSB (input)
;.equ LEDdirectionLSB =DDRD ;vstup/vystup LED LSB ;ENG;input/output LED LSB
;.equ LEDPortMSB =PORTB ;pripojenie LED diod MSB ;ENG;connecting LED diode MSB
;.equ LEDPinMSB =PINB ;pripojenie LED diod MSB (vstup) ;ENG;connecting LED diode MSB (input)
;.equ LEDdirectionMSB =DDRB ;vstup/vystup LED MSB ;ENG;input/output LED MSB
;.equ LEDlsb0 =3 ;LED0 na pin PD3 ;ENG;LED0 on pin PD3
;.equ LEDlsb1 =5 ;LED1 na pin PD5 ;ENG;LED1 on pin PD5
;.equ LEDlsb2 =6 ;LED2 na pin PD6 ;ENG;LED2 on pin PD6
;.equ LEDmsb3 =3 ;LED3 na pin PB3 ;ENG;LED3 on pin PB3
;.equ LEDmsb4 =4 ;LED4 na pin PB4 ;ENG;LED4 on pin PB4
;.equ LEDmsb5 =5 ;LED5 na pin PB5 ;ENG;LED5 on pin PB5
;.equ LEDmsb6 =6 ;LED6 na pin PB6 ;ENG;LED6 on pin PB6
;.equ LEDmsb7 =7 ;LED7 na pin PB7 ;ENG;LED7 on pin PB7
.equ SOPbyte =0b10000000 ;Start of Packet byte ;ENG;Start of Packet byte
.equ DATA0PID =0b11000011 ;PID pre DATA0 pole ;ENG;PID for DATA0 field
.equ DATA1PID =0b01001011 ;PID pre DATA1 pole ;ENG;PID for DATA1 field
.equ OUTPID =0b11100001 ;PID pre OUT pole ;ENG;PID for OUT field
.equ INPID =0b01101001 ;PID pre IN pole ;ENG;PID for IN field
.equ SOFPID =0b10100101 ;PID pre SOF pole ;ENG;PID for SOF field
.equ SETUPPID =0b00101101 ;PID pre SETUP pole ;ENG;PID for SETUP field
.equ ACKPID =0b11010010 ;PID pre ACK pole ;ENG;PID for ACK field
.equ NAKPID =0b01011010 ;PID pre NAK pole ;ENG;PID for NAK field
.equ STALLPID =0b00011110 ;PID pre STALL pole ;ENG;PID for STALL field
.equ PREPID =0b00111100 ;PID pre PRE pole ;ENG;PID for FOR field
.equ nSOPbyte =0b00000001 ;Start of Packet byte - opacne poradie ;ENG;Start of Packet byte - reverse order
.equ nDATA0PID =0b11000011 ;PID pre DATA0 pole - opacne poradie ;ENG;PID for DATA0 field - reverse order
.equ nDATA1PID =0b11010010 ;PID pre DATA1 pole - opacne poradie ;ENG;PID for DATA1 field - reverse order
.equ nOUTPID =0b10000111 ;PID pre OUT pole - opacne poradie ;ENG;PID for OUT field - reverse order
.equ nINPID =0b10010110 ;PID pre IN pole - opacne poradie ;ENG;PID for IN field - reverse order
.equ nSOFPID =0b10100101 ;PID pre SOF pole - opacne poradie ;ENG;PID for SOF field - reverse order
.equ nSETUPPID =0b10110100 ;PID pre SETUP pole - opacne poradie ;ENG;PID for SETUP field - reverse order
.equ nACKPID =0b01001011 ;PID pre ACK pole - opacne poradie ;ENG;PID for ACK field - reverse order
.equ nNAKPID =0b01011010 ;PID pre NAK pole - opacne poradie ;ENG;PID for NAK field - reverse order
.equ nSTALLPID =0b01111000 ;PID pre STALL pole - opacne poradie ;ENG;PID for STALL field - reverse order
.equ nPREPID =0b00111100 ;PID pre PRE pole - opacne poradie ;ENG;PID for FOR field - reverse order
.equ nNRZITokenPID =~0b10000000 ;PID maska pre Token paket (IN,OUT,SOF,SETUP) - opacne poradie NRZI ;ENG;PID mask for Token
packet (IN,OUT,SOF,SETUP) - reverse order NRZI
.equ nNRZISOPbyte =~0b10101011 ;Start of Packet byte - opacne poradie NRZI ;ENG;Start of Packet byte - reverse order NRZI
.equ nNRZIDATA0PID =~0b11010111 ;PID pre DATA0 pole - opacne poradie NRZI ;ENG;PID for DATA0 field - reverse order NRZI
.equ nNRZIDATA1PID =~0b11001001 ;PID pre DATA1 pole - opacne poradie NRZI ;ENG;PID for DATA1 field - reverse order NRZI
.equ nNRZIOUTPID =~0b10101111 ;PID pre OUT pole - opacne poradie NRZI ;ENG;PID for OUT field - reverse order NRZI
.equ nNRZIINPID =~0b10110001 ;PID pre IN pole - opacne poradie NRZI ;ENG;PID for IN field - reverse order NRZI
.equ nNRZISOFPID =~0b10010011 ;PID pre SOF pole - opacne poradie NRZI ;ENG;PID for SOF field - reverse order NRZI
.equ nNRZISETUPPID =~0b10001101 ;PID pre SETUP pole - opacne poradie NRZI ;ENG;PID for SETUP field - reverse order NRZI
.equ nNRZIACKPID =~0b00100111 ;PID pre ACK pole - opacne poradie NRZI ;ENG;PID for ACK field - reverse order NRZI
.equ nNRZINAKPID =~0b00111001 ;PID pre NAK pole - opacne poradie NRZI ;ENG;PID for NAK field - reverse order NRZI
.equ nNRZISTALLPID =~0b00000111 ;PID pre STALL pole - opacne poradie NRZI ;ENG;PID for STALL field - reverse order NRZI
.equ nNRZIPREPID =~0b01111101 ;PID pre PRE pole - opacne poradie NRZI ;ENG;PID for FOR field - reverse order NRZI
.equ nNRZIADDR0 =~0b01010101 ;Adresa = 0 - opacne poradie NRZI ;ENG;Address = 0 - reverse order NRZI
;stavove byty - State ;ENG;status bytes - State
.equ BaseState =0 ;
.equ SetupState =1 ;
.equ InState =2 ;
.equ OutState =3 ;
.equ SOFState =4 ;
.equ DataState =5 ;
;Flagy pozadovanej akcie ;ENG;Flags of action
.equ DoNone =0
.equ DoReceiveOutData =1
.equ DoReceiveSetupData =2
.equ DoPrepareOutContinuousBuffer =3
.equ DoReadySendAnswer =4
.equ CRC5poly =0b00101 ;CRC5 polynom ;ENG;CRC5 polynomial
.equ CRC5zvysok =0b01100 ;CRC5 zvysok po uspesnom CRC5 ;ENG;CRC5 remainder after successful CRC5
.equ CRC16poly =0b1000000000000101 ;CRC16 polynom ;ENG;CRC16 polynomial
.equ CRC16zvysok =0b1000000000001101 ;CRC16 zvysok po uspesnom CRC16 ;ENG;CRC16 remainder after successful CRC16
.equ MAXUSBBYTES =14 ;maximum bytes in USB input message ;ENG;maximum bytes in USB input message
.equ NumberOfFirstBits =10 ;kolko prvych bitov moze byt dlhsich ;ENG;how many first bits allowed be longer
.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) ;ENG;Timeout 12.8ms (12800us) to terminate after firsts bits
.equ InitBaudRate =12000000/16/57600-1 ;nastavit vysielaciu rychlost UART-u na 57600 (pre 12MHz=12000000Hz) ;ENG;UART on
57600 (for 12MHz=12000000Hz)
.equ InputBufferBegin =RAMEND128-127 ;zaciatok prijimacieho shift buffera ;ENG;compare of receiving shift buffer
.equ InputShiftBufferBegin =InputBufferBegin+MAXUSBBYTES ;zaciatok prijimacieho buffera ;ENG;compare of receiving buffera
.equ OutputBufferBegin =RAMEND128-MAXUSBBYTES-2 ;zaciatok vysielacieho buffera ;ENG;compare of transmitting buffer
.equ AckBufferBegin =OutputBufferBegin-3 ;zaciatok vysielacieho buffera Ack ;ENG;compare of transmitting buffer Ack
.equ NakBufferBegin =AckBufferBegin-3 ;zaciatok vysielacieho buffera Nak ;ENG;compare of transmitting buffer Nak
.equ ConfigByte =NakBufferBegin-1 ;0=unconfigured state ;ENG;0=unconfigured state
.equ AnswerArray =ConfigByte-8 ;8 byte answer array ;ENG;8 byte answer array
.equ StackBegin =AnswerArray-1 ;spodok zasobnika (stack je velky cca 68 bytov) ;ENG;low reservoir (stack is big cca 68 byte)
.equ MAXRS232LENGTH =RAMEND-RAMEND128-10 ;maximalna dlzka RS232 kodu ;ENG;maximum length RS232 code
.equ RS232BufferBegin =RAMEND128+1 ;zaciatok buffera pre RS232 prijem ;ENG;compare of buffer for RS232 - receiving
.equ RS232BufferEnd =RS232BufferBegin+MAXRS232LENGTH
.equ RS232ReadPosPtr =RS232BufferBegin+0
.equ RS232WritePosPtr =RS232BufferBegin+2
.equ RS232LengthPosPtr =RS232BufferBegin+4
.equ RS232Reserved =RS232BufferBegin+6
.equ RS232FIFOBegin =RS232BufferBegin+8
.def RS232BufferFull =R1 ;priznak plneho RS232 buffera ;ENG;flag of full RS232 buffer
.def backupbitcount =R2 ;zaloha bitcount registra v INT0 preruseni ;ENG;backup bitcount register in INT0 disconnected
.def RAMread =R3 ;ci sa ma citat zo SRAM-ky ;ENG;if reading from SRAM
.def backupSREGTimer =R4 ;zaloha Flag registra v Timer interrupte ;ENG;backup Flag register in Timer interrupt
.def backupSREG =R5 ;zaloha Flag registra v INT0 preruseni ;ENG;backup Flag register in INT0 interrupt
.def ACC =R6 ;accumulator ;ENG;accumulator
.def lastBitstufNumber =R7 ;pozicia bitstuffingu ;ENG;position in bitstuffing
.def OutBitStuffNumber =R8 ;kolko bitov sa ma este odvysielat z posledneho bytu - bitstuffing ;ENG;how many bits to send
last byte - bitstuffing
.def BitStuffInOut =R9 ;ci sa ma vkladat alebo mazat bitstuffing ;ENG;if insertion or deleting of bitstuffing
.def TotalBytesToSend =R10 ;kolko sa ma poslat bytov ;ENG;how many bytes to send
.def TransmitPart =R11 ;poradove cislo vysielacej casti ;ENG;order number of transmitting part
.def InputBufferLength =R12 ;dlzka pripravena vo vstupnom USB bufferi ;ENG;length prepared in input USB buffer
.def OutputBufferLength =R13 ;dlzka odpovede pripravena v USB bufferi ;ENG;length answers prepared in USB buffer
.def MyUpdatedAddress =R14 ;moja USB adresa na update ;ENG;my USB address for update
.def MyAddress =R15 ;moja USB adresa ;ENG;my USB address
.def ActionFlag =R16 ;co sa ma urobit v hlavnej slucke programu ;ENG;what to do in main program loop
.def temp3 =R17 ;temporary register ;ENG;temporary register
.def temp2 =R18 ;temporary register ;ENG;temporary register
.def temp1 =R19 ;temporary register ;ENG;temporary register
.def temp0 =R20 ;temporary register ;ENG;temporary register
.def bitcount =R21 ;counter of bits in byte ;ENG;counter of bits in byte
.def ByteCount =R22 ;pocitadlo maximalneho poctu prijatych bajtov ;ENG;counter of maximum number of received bytes
.def inputbuf =R23 ;prijimaci register ;ENG;receiver register
.def shiftbuf =R24 ;posuvny prijimaci register ;ENG;shift receiving register
.def State =R25 ;byte stavu stavoveho stroja ;ENG;state byte of status of state machine
.def RS232BufptrX =R26 ;XL register - pointer do buffera prijatych IR kodov ;ENG;XL register - pointer to buffer of received
IR codes
.def RS232BufptrXH =R27
.def USBBufptrY =R28 ;YL register - pointer do USB buffera input/output ;ENG;YL register - pointer to USB buffer input/output
.def ROMBufptrZ =R30 ;ZL register - pointer do buffera ROM dat ;ENG;ZL register - pointer to buffer of ROM data
;poziadavky na deskriptory ;ENG;requirements on descriptors
.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 ;ENG;descriptor types
.equ DEVICE =1
.equ CONFIGURATION =2
.equ STRING =3
.equ INTERFACE =4
.equ ENDPOINT =5
;databits ;ENG;databits
.equ DataBits5 =0
.equ DataBits6 =1
.equ DataBits7 =2
.equ DataBits8 =3
;parity ;ENG;parity
.equ ParityNone =0
.equ ParityOdd =1
.equ ParityEven =2
.equ ParityMark =3
.equ ParitySpace =4
;stopbits ;ENG;stopbits
.equ StopBit1 =0
.equ StopBit2 =1
;user function start number
.equ USER_FNC_NUMBER =100
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt table ;ENG;* Interrupt table
;********************************************************************
.cseg
;------------------------------------------------------------------------------------------
.org 0 ;po resete ;ENG;after reset
rjmp reset
;------------------------------------------------------------------------------------------
.org INT0addr ;externe prerusenie INT0 ;ENG;external interrupt INT0
rjmp INT0handler
;------------------------------------------------------------------------------------------
.org URXCaddr ;prijem zo seriovej linky ;ENG;receiving from serial line
push temp0
cbi UCR,RXCIE ;zakazat interrupt od prijimania UART ;ENG;disable interrupt from UART receiving
sei ;povol interrupty na obsluhu USB ;ENG;enable interrupts to service USB
in temp0,UDR ;nacitaj do temp0 prijate data z UART-u ;ENG;put to temp0 received data from UART
in backupSREGTimer,SREG ;zaloha SREG ;ENG;backup SREG
push temp2
push temp3
lds temp2,RS232LengthPosPtr
lds temp3,RS232LengthPosPtr+1 ;zisti dlzku buffera RS232 kodu ;ENG;determine length of RS232 code buffer
cpi temp3,HIGH(RS232BufferEnd-RS232FIFOBegin-1) ;ci by mal pretiect buffer ;ENG;if the buffer would overflow
brlo FIFOBufferNoOverflow ;ak nepretecie, tak zapis do FIFO ;ENG;if not overflow then write to FIFO
brne NoIncRS232BufferFull ;ak by mal pretiect, tak zabran prepisaniu ;ENG;if buffer would overflow, then prevent of overwriting
;inak (pri rovnosti) este porovnaj Lo byty ;ENG;otherwise (if equall) still compare Lo bytes
cpi temp2,LOW(RS232BufferEnd-RS232FIFOBegin-1) ;ak by mal pretiect buffer (Lo byte) ;ENG;if buffer would overflow (Lo byte)
brcc NoIncRS232BufferFull ;tak zabran prepisaniu ;ENG;then prevent of overwriting
FIFOBufferNoOverflow:
push RS232BufptrX
push RS232BufptrXH
lds RS232BufptrX,RS232WritePosPtr ;nastavenie sa na zaciatok buffera zapisu RS232 kodu ;ENG;set position to begin of buffer
write RS232 code
lds RS232BufptrXH,RS232WritePosPtr+1 ;nastavenie sa na zaciatok buffera zapisu RS232 kodu ;ENG;set position to begin of
buffer write RS232 code
st X+,temp0 ;a uloz ho do buffera ;ENG;and save it to buffer
cpi RS232BufptrXH,HIGH(RS232BufferEnd+1) ;ak sa nedosiahol maximum RS232 buffera ;ENG;if not reached maximum of RS232 buffer
brlo NoUARTBufferOverflow ;tak pokracuj ;ENG;then continue
brne UARTBufferOverflow ;skontroluj aj LSB ;ENG;check althen LSB
cpi RS232BufptrX,LOW(RS232BufferEnd+1) ;ak sa nedosiahol maximum RS232 buffera ;ENG;if not reached maximum of RS232 buffer
brlo NoUARTBufferOverflow ;tak pokracuj ;ENG;then continue
UARTBufferOverflow:
ldi RS232BufptrX,LOW(RS232FIFOBegin) ;inak sa nastav na zaciatok buffera ;ENG;otherwise set position to buffer begin
ldi RS232BufptrXH,HIGH(RS232FIFOBegin) ;inak sa nastav na zaciatok buffera ;ENG;otherwise set position to buffer begin
NoUARTBufferOverflow:
sts RS232WritePosPtr,RS232BufptrX ;ulozenie noveho offsetu buffera zapisu RS232 kodu ;ENG;save new offset of buffer write
RS232 code
sts RS232WritePosPtr+1,RS232BufptrXH ;ulozenie noveho offsetu buffera zapisu RS232 kodu ;ENG;save new offset of buffer write
RS232 code
ldi temp0,1 ;zvys dlzku RS232 buffera ;ENG;increment length of RS232 buffer
add temp2,temp0
ldi temp0,0
adc temp3,temp0
sts RS232LengthPosPtr,temp2 ;uloz dlzku buffera RS232 kodu ;ENG;save length of buffer RS232 code
sts RS232LengthPosPtr+1,temp3 ;uloz dlzku buffera RS232 kodu ;ENG;save length of buffer RS232 code
pop RS232BufptrXH
pop RS232BufptrX
NoIncRS232BufferFull:
pop temp3
pop temp2
pop temp0
out SREG,backupSREGTimer ;obnova SREG ;ENG;restore SREG
cli ;zakazat interrupt kvoli zacykleniu ;ENG;disable interrupt because to prevent reentrant interrupt call
sbi UCR,RXCIE ;povolit interrupt od prijimania UART ;ENG;enable interrupt from receiving of UART
reti
;------------------------------------------------------------------------------------------
;********************************************************************
;* Init program ;ENG;* Init program
;********************************************************************
;------------------------------------------------------------------------------------------
reset: ;inicializacia procesora a premennych na spravne hodnoty ;ENG;initialization of processor and variables to right
values
ldi temp0,StackBegin ;inicializacia stacku ;ENG;initialization of stack
out SPL,temp0
clr XH ;RS232 pointer ;ENG;RS232 pointer
clr YH ;USB pointer ;ENG;USB pointer
clr ZH ;ROM pointer ;ENG;ROM pointer
ldi temp0,LOW(RS232FIFOBegin) ;nastav na zaciatok buffera Low ;ENG;set Low to begin of buffer
sts RS232ReadPosPtr,temp0 ;znuluj ukazovatel citania ;ENG;zero index of reading
sts RS232WritePosPtr,temp0 ;znuluj ukazovatel zapisu ;ENG;zero index of writing
ldi temp0,HIGH(RS232FIFOBegin) ;nastav na zaciatok buffera High ;ENG;set High to begin of buffer
sts RS232ReadPosPtr+1,temp0 ;znuluj ukazovatel citania ;ENG;zero index of reading
sts RS232WritePosPtr+1,temp0 ;znuluj ukazovatel zapisu ;ENG;zero index of writing
sts RS232LengthPosPtr,YH ;znuluj ukazovatel dlzky ;ENG;zero index of length
sts RS232LengthPosPtr+1,YH ;znuluj ukazovatel dlzky ;ENG;zero index of length
clr RS232BufferFull
clr MyUpdatedAddress ;nova adresa USB - nedekodovana ;ENG;new address USB - non-decoded
rcall InitACKBufffer ;inicializacia ACK buffera ;ENG;initialization of ACK buffer
rcall InitNAKBufffer ;inicializacia NAK buffera ;ENG;initialization of NAK buffer
rcall USBReset ;inicializacia USB adresy ;ENG;initialization of USB addresses
ldi temp0,0b00111100 ;nahodit pull-up na PORTB ;ENG;set pull-up on PORTB
out PORTB,temp0
ldi temp0,0b11111111 ;nahodit pull-up na PORTC ;ENG;set pull-up on PORTC
out PORTC,temp0
ldi temp0,0b11111011 ;nahodit pull-up na PORTD ;ENG;set pull-up on PORTD
out PORTD,temp0
clr temp0 ;
out UBRRH,temp0 ;nastavit vysielaciu rychlost UART-u High ;ENG;set UART speed High
out EEARH,temp0 ;znulovat EEPROM ukazovatel ;ENG;zero EEPROM index
ldi temp0,1<<U2X ;nastavit mod X2 na UART-e ;ENG;set mode X2 on UART
out USR,temp0
ldi temp0,InitBaudRate ;nastavit vysielaciu rychlost UART-u ;ENG;set UART speed
out UBRR,temp0
sbi UCR,TXEN ;povolit vysielanie UART-u ;ENG;enable transmiting of UART
sbi UCR,RXEN ;povolit prijimanie UART-u ;ENG;enable receiving of UART
sbi UCR,RXCIE ;povolit interrupt od prijimania UART ;ENG;enable interrupt from receiving of UART
ldi temp0,0x0F ;INT0 - reagovanie na nabeznu hranu ;ENG;INT0 - respond to leading edge
out MCUCR,temp0 ;
ldi temp0,1<<INT0 ;povolit externy interrupt INT0 ;ENG;enable external interrupt INT0
out GIMSK,temp0
;------------------------------------------------------------------------------------------
;********************************************************************
;* Main program ;ENG;* Main program
;********************************************************************
sei ;povolit interrupty globalne ;ENG;enable interrupts globally
Main:
sbis inputport,DATAminus ;cakanie az sa zmeni D- na 0 ;ENG;waiting till change D- to 0
rjmp CheckUSBReset ;a skontroluj, ci to nie je USB reset ;ENG;and check, if isn't 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) ;ENG;counter duration of reset
(according to specification is that cca 10ms - here is cca 100us)
WaitForUSBReset:
sbic inputport,DATAminus ;cakanie az sa zmeni D+ na 0 ;ENG;waiting till change D+ to 0
rjmp Main
dec temp0
brne WaitForUSBReset
rcall USBReset
rjmp Main
ProcPrepareOutContinuousBuffer:
rcall PrepareOutContinuousBuffer ;priprav pokracovanie odpovede do buffera ;ENG;prepare next sequence of answer to buffer
ldi ActionFlag,DoReadySendAnswer
rjmp Main
ProcReceiveSetupData:
ldi USBBufptrY,InputBufferBegin ;pointer na zaciatok prijimacieho buffera ;ENG;pointer to begin of receiving buffer
mov ByteCount,InputBufferLength ;dlzka vstupneho buffera ;ENG;length of input buffer
rcall DecodeNRZI ;prevod kodovania NRZI na bity ;ENG;transfer NRZI coding to bits
rcall MirrorInBufferBytes ;prehodit poradie bitov v bajtoch ;ENG;invert bits order in bytes
rcall BitStuff ;odstranenie bit stuffing ;ENG;removal of bitstuffing
;rcall CheckCRCIn ;kontrola CRC ;ENG;rcall CheckCRCIn ;check CRC
rcall PrepareUSBOutAnswer ;pripravenie odpovede do vysielacieho buffera ;ENG;prepare answers to transmitting buffer
ldi ActionFlag,DoReadySendAnswer
rjmp Main
;********************************************************************
;* Main program END ;ENG;* Main program END
;********************************************************************
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt0 interrupt handler ;ENG;* Interrupt0 interrupt handler
;********************************************************************
INT0Handler: ;prerusenie INT0 ;ENG;interrupt INT0
in backupSREG,SREG
push temp0
push temp1
ldi temp0,3 ;pocitadlo trvania log0 ;ENG;counter of duration log0
ldi temp1,2 ;pocitadlo trvania log1 ;ENG;counter of duration log1
;cakanie na zaciatok paketu ;ENG;waiting for begin packet
CheckchangeMinus:
sbis inputport,DATAminus ;cakanie az sa zmeni D- na 1 ;ENG;waiting till change D- to 1
rjmp CheckchangeMinus
CheckchangePlus:
sbis inputport,DATAplus ;cakanie az sa zmeni D+ na 1 ;ENG;waiting till change D+ to 1
rjmp CheckchangePlus
DetectSOPEnd:
sbis inputport,DATAplus
rjmp Increment0 ;D+ =0 ;ENG;D+ =0
Increment1:
ldi temp0,3 ;pocitadlo trvania log0 ;ENG;counter of duration log0
dec temp1 ;kolko cyklov trvala log1 ;ENG;how many cycles takes log1
nop
breq USBBeginPacket ;ak je to koniec SOP - prijimaj paket ;ENG;if this is end of SOP - receive packet
rjmp DetectSOPEnd
Increment0:
ldi temp1,2 ;pocitadlo trvania log1 ;ENG;counter of duration log1
dec temp0 ;kolko cyklov trvala log0 ;ENG;how many cycles take log0
nop
brne DetectSOPEnd ;ak nenastal SOF - pokracuj ;ENG;if there isn't SOF - continue
rjmp EndInt0HandlerPOP2
EndInt0Handler:
pop ACC
pop RS232BufptrX
pop temp3
pop temp2
EndInt0HandlerPOP:
pop USBBufptrY
pop ByteCount
mov bitcount,backupbitcount ;obnova bitcount registra ;ENG;restore bitcount register
EndInt0HandlerPOP2:
pop temp1
pop temp0
out SREG,backupSREG
ldi shiftbuf,1<<INTF0 ;znulovat flag interruptu INTF0 ;ENG;zero interruptu flag INTF0
out GIFR,shiftbuf
reti ;inak skonci (bol iba SOF - kazdu milisekundu) ;ENG;otherwise finish (was only SOF - every millisecond)
USBBeginPacket:
mov backupbitcount,bitcount ;zaloha bitcount registra ;ENG;backup bitcount register
in shiftbuf,inputport ;ak ano nacitaj ho ako nulty bit priamo do shift registra ;ENG;if yes load it as zero bit directly
to shift register
USBloopBegin:
push ByteCount ;dalsia zaloha registrov (setrenie casu) ;ENG;additional backup of registers (save of time)
push USBBufptrY
ldi bitcount,6 ;inicializacia pocitadla bitov v bajte ;ENG;initialization of bits counter in byte
ldi ByteCount,MAXUSBBYTES ;inicializacia max poctu prijatych bajtov v pakete ;ENG;initialization of max number of received
bytes in packet
ldi USBBufptrY,InputShiftBufferBegin ;nastav vstupny buffera ;ENG;set the input buffer
USBloop1_6:
in inputbuf,inputport
cbr inputbuf,USBpinmask ;odmaskovat spodne 2 bity ;ENG;unmask low 2 bits
breq USBloopEnd ;ak su nulove - koniec USB packetu ;ENG;if they are zeros - end of USB packet
ror inputbuf ;presun Data+ do shift registra ;ENG;transfer Data+ to shift register
rol shiftbuf
dec bitcount ;zmensi pocitadlo bitov ;ENG;decrement bits counter
brne USBloop1_6 ;ak nie je nulove - opakuj naplnanie shift registra ;ENG;if it isn't zero - repeat filling of shift register
nop ;inak bude nutne skopirovat shift register bo buffera ;ENG;otherwise is necessary copy shift register to buffer
USBloop7:
in inputbuf,inputport
cbr inputbuf,USBpinmask ;odmaskovat spodne 2 bity ;ENG;unmask low 2 bits
breq USBloopEnd ;ak su nulove - koniec USB packetu ;ENG;if they are zeros - end of USB packet
ror inputbuf ;presun Data+ do shift registra ;ENG;transfer Data+ to shift register
rol shiftbuf
ldi bitcount,7 ;inicializacia pocitadla bitov v bajte ;ENG;initialization of bits counter in byte
st Y+,shiftbuf ;skopiruj shift register bo buffera a zvys pointer do buffera ;ENG;copy shift register into buffer and increment
pointer to buffer
USBloop0: ;a zacni prijimat dalsi bajt ;ENG;and start receiving next byte
in shiftbuf,inputport ;nulty bit priamo do shift registra ;ENG;zero bit directly to shift register
cbr shiftbuf,USBpinmask ;odmaskovat spodne 2 bity ;ENG;unmask low 2 bits
breq USBloopEnd ;ak su nulove - koniec USB packetu ;ENG;if they are zeros - end of USB packet
dec bitcount ;zmensi pocitadlo bitov ;ENG;decrement bits counter
nop ;
dec ByteCount ;ak sa nedosiahol maximum buffera ;ENG;if not reached maximum buffer
brne USBloop1_6 ;tak prijimaj dalej ;ENG;then receive next
rjmp EndInt0HandlerPOP ;inak opakuj od zaciatku ;ENG;otherwise repeat back from begin
USBloopEnd:
cpi USBBufptrY,InputShiftBufferBegin+3 ;ak sa neprijali aspon 3 byte ;ENG;if at least 3 byte not received
brcs EndInt0HandlerPOP ;tak skonci ;ENG;then finish
lds temp0,InputShiftBufferBegin+0 ;identifikator paketu do temp0 ;ENG;identifier of packet to temp0
lds temp1,InputShiftBufferBegin+1 ;adresa do temp1 ;ENG;address to temp1
brne TestDataPacket ;ak je dlzka ina ako 3 - tak to moze byt iba DataPaket ;ENG;if is length different from 3 - then this
can be only DataPaket
TestIOPacket:
cp temp1,MyAddress ;ak to nie je urcene (adresa) pre mna ;ENG;if this isn't assigned (address) for me
brne TestDataPacket ;tak to moze byt este Data Packet ;ENG;then this can be still DataPacket
TestSetupPacket:;test na SETUP paket ;ENG;test to SETUP packet
cpi temp0,nNRZISETUPPID
brne TestOutPacket ;ak nie je Setup PID - dekoduj iny paket ;ENG;if this isn't Setup PID - decode other packet
ldi State,SetupState
rjmp EndInt0HandlerPOP ;ak je Setup PID - prijimaj nasledny Data paket ;ENG;if this is Setup PID - receive consecutive Data
packet
TestOutPacket: ;test na OUT paket ;ENG;test for OUT packet
cpi temp0,nNRZIOUTPID
brne TestInPacket ;ak nie je Out PID - dekoduj iny paket ;ENG;if this isn't Out PID - decode other packet
ldi State,OutState
rjmp EndInt0HandlerPOP ;ak je Out PID - prijimaj nasledny Data paket ;ENG;if this is Out PID - receive consecutive Data
packet
TestInPacket: ;test na IN paket ;ENG;test on IN packet
cpi temp0,nNRZIINPID
brne TestDataPacket ;ak nie je In PID - dekoduj iny paket ;ENG;if this isn't In PID - decode other packet
rjmp AnswerToInRequest
TestDataPacket: ;test na DATA0 a DATA1 paket ;ENG;test for DATA0 and DATA1 packet
cpi temp0,nNRZIDATA0PID
breq Data0Packet ;ak nie je Data0 PID - dekoduj iny paket ;ENG;if this isn't Data0 PID - decode other packet
cpi temp0,nNRZIDATA1PID
brne NoMyPacked ;ak nie je Data1 PID - dekoduj iny paket ;ENG;if this isn't Data1 PID - decode other packet
Data0Packet:
cpi State,SetupState ;ak bol stav Setup ;ENG;if was state Setup
breq ReceiveSetupData ;prijmi ho ;ENG;receive it
cpi State,OutState ;ak bol stav Out ;ENG;if was state Out
breq ReceiveOutData ;prijmi ho ;ENG;receive it
NoMyPacked:
ldi State,BaseState ;znuluj stav ;ENG;zero state
rjmp EndInt0HandlerPOP ;a prijimaj nasledny Data paket ;ENG;and receive consecutive Data packet
AnswerToInRequest:
push temp2 ;zazalohuj dalsie registre a pokracuj ;ENG;backup next registers and continue
push temp3
push RS232BufptrX
push ACC
cpi ActionFlag,DoReadySendAnswer ;ak nie je pripravena odpoved ;ENG;if isn't prepared answer
brne NoReadySend ;tak posli NAK ;ENG;then send NAK
rcall SendPreparedUSBAnswer ;poslanie odpovede naspat ;ENG;transmitting answer back
and MyUpdatedAddress,MyUpdatedAddress ;ak je MyUpdatedAddress nenulova ;ENG;if is MyUpdatedAddress nonzero
brne SetMyNewUSBAddress ;tak treba zmenit USB adresu ;ENG;then is necessary to change USB address
ldi State,InState
ldi ActionFlag,DoPrepareOutContinuousBuffer
rjmp EndInt0Handler ;a opakuj - cakaj na dalsiu odozvu z USB ;ENG;and repeat - wait for next response from USB
ReceiveSetupData:
push temp2 ;zazalohuj dalsie registre a pokracuj ;ENG;backup next registers and continue
push temp3
push RS232BufptrX
push ACC
rcall SendACK ;akceptovanie Setup Data paketu ;ENG;accept Setup Data packet
rcall FinishReceiving ;ukonci prijem ;ENG;finish receiving
ldi ActionFlag,DoReceiveSetupData
rjmp EndInt0Handler
ReceiveOutData:
push temp2 ;zazalohuj dalsie registre a pokracuj ;ENG;backup next registers and continue
push temp3
push RS232BufptrX
push ACC
cpi ActionFlag,DoReceiveSetupData ;ak sa prave spracovava prikaz Setup ;ENG;if is currently in process command Setup
breq NoReadySend ;tak posli NAK ;ENG;then send NAK
rcall SendACK ;akceptovanie Out paketu ;ENG;accept Out packet
clr ActionFlag
rjmp EndInt0Handler
NoReadySend:
rcall SendNAK ;este nie som pripraveny s odpovedou ;ENG;still I am not ready to answer
rjmp EndInt0Handler ;a opakuj - cakaj na dalsiu odozvu z USB ;ENG;and repeat - wait for next response from USB
;------------------------------------------------------------------------------------------
SetMyNewUSBAddress: ;nastavi novu USB adresu v NRZI kodovani ;ENG;set new USB address in NRZI coded
clr MyAddress ;vychodzi stav odpovede - mojej nNRZI USB adresy ;ENG;original answer state - of my nNRZI USB address
ldi temp2,0b00000001 ;maska na xorovanie ;ENG;mask for xoring
ldi temp3,8 ;pocitadlo bitov ;ENG;bits counter
SetMyNewUSBAddressLoop:
mov temp0,MyAddress ;zapamatat si koncovu odpoved ;ENG;remember final answer
ror MyUpdatedAddress ;do carry vysielany bit LSB (v smere naskor LSB a potom MSB) ;ENG;to carry transmitting bit LSB (in
direction firstly LSB then MSB)
brcs NoXORBit ;ak je jedna - nemen stav ;ENG;if one - don't change state
eor temp0,temp2 ;inak sa bude stav menit podla posledneho bitu odpovede ;ENG;otherwise state will be changed according
to last bit of answer
NoXORBit:
ror temp0 ;posledny bit zmenenej odpovede do carry ;ENG;last bit of changed answer to carry
rol MyAddress ;a z carry do koncovej odpovede na miesto LSB (a sucasne prehodenie LSB a MSB poradia) ;ENG;and from carry
to final answer to the LSB place (and reverse LSB and MSB order)
dec temp3 ;zmensi pocitadlo bitov ;ENG;decrement bits counter
brne SetMyNewUSBAddressLoop ;ak pocitadlo bitov nie je nulove opakuj vysielanie s dalsim bitom ;ENG;if bits counter isn't
zero repeat transmitting with next bit
clr MyUpdatedAddress ;znulovanie adresy ako priznak jej buduceho nemenenia ;ENG;zero addresses as flag of its next unchanging
rjmp EndInt0Handler
;------------------------------------------------------------------------------------------
FinishReceiving: ;korekcne akcie na ukoncenie prijmu ;ENG;corrective actions for receive termination
cpi bitcount,7 ;prenes do buffera aj posledny necely byte ;ENG;transfer to buffer also last not completed byte
breq NoRemainingBits ;ak boli vsetky byty prenesene, tak neprenasaj nic ;ENG;if were all bytes transfered, then nothing
transfer
inc bitcount
ShiftRemainingBits:
rol shiftbuf ;posun ostavajuce necele bity na spravnu poziciu ;ENG;shift remaining not completed bits on right position
dec bitcount
brne ShiftRemainingBits
st Y+,shiftbuf ;a skopiruj shift register bo buffera - necely byte ;ENG;and copy shift register bo buffer - not completed
byte
NoRemainingBits:
mov ByteCount,USBBufptrY
subi ByteCount,InputShiftBufferBegin-1 ;v ByteCount je pocet prijatych byte (vratane necelych byte) ;ENG;in ByteCount is
number of received bytes (including not completed bytes)
mov InputBufferLength,ByteCount ;a uchovat pre pouzitie v hlavnom programe ;ENG;and save for use in main program
ldi USBBufptrY,InputShiftBufferBegin ;pointer na zaciatok prijimacieho shift buffera ;ENG;pointer to begin of receiving
shift buffer
ldi RS232BufptrX,InputBufferBegin+1 ;data buffer (vynechat SOP) ;ENG;data buffer (leave out SOP)
push XH ;uschova RS232BufptrX Hi ukazovatela ;ENG;save RS232BufptrX Hi index
clr XH
MoveDataBuffer:
ld temp0,Y+
st X+,temp0
dec ByteCount
brne MoveDataBuffer
pop XH ;obnova RS232BufptrX Hi ukazovatela ;ENG;restore RS232BufptrX Hi index
ldi ByteCount,nNRZISOPbyte
sts InputBufferBegin,ByteCount ;ako keby sa prijal SOP - nekopiruje sa zo shift buffera ;ENG;like received SOP - it is
not copied from shift buffer
ret
;------------------------------------------------------------------------------------------
;********************************************************************
;* Other procedures ;ENG;* Other procedures
;********************************************************************
;------------------------------------------------------------------------------------------
USBReset: ;inicializacia USB stavoveho stroja ;ENG;initialization of USB state engine
ldi temp0,nNRZIADDR0 ;inicializacia USB adresy ;ENG;initialization of USB address
mov MyAddress,temp0
clr State ;inicializacia stavoveho stroja ;ENG;initialization of state engine
clr BitStuffInOut
clr OutBitStuffNumber
clr ActionFlag
clr RAMread ;bude sa vycitavat z ROM-ky ;ENG;will be reading from ROM
sts ConfigByte,RAMread ;nenakonfiguravany stav ;ENG;unconfigured state
ret
;------------------------------------------------------------------------------------------
SendPreparedUSBAnswer: ;poslanie kodovanim NRZI OUT buffera s dlzkou OutputBufferLength do USB ;ENG;transmitting by NRZI coding
OUT buffer with length OutputBufferLength to USB
mov ByteCount,OutputBufferLength ;dlzka odpovede ;ENG;length of answer
SendUSBAnswer: ;poslanie kodovanim NRZI OUT buffera do USB ;ENG;transmitting by NRZI coding OUT buffer to USB
ldi USBBufptrY,OutputBufferBegin ;pointer na zaciatok vysielacieho buffera ;ENG;pointer to begin of transmitting buffer
SendUSBBuffer: ;poslanie kodovanim NRZI dany buffer do USB ;ENG;transmitting by NRZI coding given buffer to USB
ldi temp1,0 ;zvysovanie pointera (pomocna premenna) ;ENG;incrementing pointer (temporary variable)
mov temp3,ByteCount ;pocitadlo bytov: temp3 = ByteCount ;ENG;byte counter: temp3 = ByteCount
ldi temp2,0b00000011 ;maska na xorovanie ;ENG;mask for xoring
ld inputbuf,Y+ ;nacitanie prveho bytu do inputbuf a zvys pointer do buffera ;ENG;load first byte to inputbuf and increment
pointer to buffer
;USB ako vystup: ;ENG;USB as output:
cbi outputport,DATAplus ;zhodenie DATAplus : kludovy stav portu USB ;ENG;down DATAPLUS : idle state of USB port
sbi outputport,DATAminus ;nahodenie DATAminus : kludovy stav portu USB ;ENG;set DATAMINUS : idle state of USB port
sbi USBdirection,DATAplus ;DATAplus ako vystupny ;ENG;DATAPLUS as output
sbi USBdirection,DATAminus ;DATAminus ako vystupny ;ENG;DATAMINUS as output
in temp0,outputport ;kludovy stav portu USB do temp0 ;ENG;idle state of USB port to temp0
SendUSBAnswerLoop:
ldi bitcount,7 ;pocitadlo bitov ;ENG;bits counter
SendUSBAnswerByteLoop:
nop ;oneskorenie kvoli casovaniu ;ENG;delay because timing
ror inputbuf ;do carry vysielany bit (v smere naskor LSB a potom MSB) ;ENG;to carry transmiting bit (in direction first
LSB then MSB)
brcs NoXORSend ;ak je jedna - nemen stav na USB ;ENG;if that it is one - don't change USB state
eor temp0,temp2 ;inak sa bude stav menit ;ENG;otherwise state will be changed
NoXORSend:
out outputport,temp0 ;vysli von na USB ;ENG;send out to USB
dec bitcount ;zmensi pocitadlo bitov - podla carry flagu ;ENG;decrement bits counter - according to carry flag
brne SendUSBAnswerByteLoop ;ak pocitadlo bitov nie je nulove - opakuj vysielanie s dalsim bitom ;ENG;if bits counter isn't
zero - repeat transmiting with next bit
sbrs inputbuf,0 ;ak je vysielany bit jedna - nemen stav na USB ;ENG;if is transmiting bit one - don't change USB state
eor temp0,temp2 ;inak sa bude stav menit ;ENG;otherwise state will be changed
NoXORSendLSB:
dec temp3 ;zniz pocitadlo bytov ;ENG;decrement bytes counter
ld inputbuf,Y+ ;nacitanie dalsieho bytu a zvys pointer do buffera ;ENG;load next byte and increment pointer to buffer
out outputport,temp0 ;vysli von na USB ;ENG;transmit to USB
brne SendUSBAnswerLoop ;opakuj pre cely buffer (pokial temp3=0) ;ENG;repeat for all buffer (till temp3=0)
mov bitcount,OutBitStuffNumber ;pocitadlo bitov pre bitstuff ;ENG;bits counter for bitstuff
cpi bitcount,0 ;ak nie je potrebny bitstuff ;ENG;if not be needed bitstuff
breq ZeroBitStuf
SendUSBAnswerBitstuffLoop:
ror inputbuf ;do carry vysielany bit (v smere naskor LSB a potom MSB) ;ENG;to carry transmiting bit (in direction first
LSB then MSB)
brcs NoXORBitstuffSend ;ak je jedna - nemen stav na USB ;ENG;if is one - don't change state on USB
eor temp0,temp2 ;inak sa bude stav menit ;ENG;otherwise state will be changed
NoXORBitstuffSend:
out outputport,temp0 ;vysli von na USB ;ENG;transmit to USB
nop ;oneskorenie kvoli casovaniu ;ENG;delay because of timing
dec bitcount ;zmensi pocitadlo bitov - podla carry flagu ;ENG;decrement bits counter - according to carry flag
brne SendUSBAnswerBitstuffLoop ;ak pocitadlo bitov nie je nulove - opakuj vysielanie s dalsim bitom ;ENG;if bits counter
isn't zero - repeat transmiting with next bit
ld inputbuf,Y ;oneskorenie 2 cykly ;ENG;delay 2 cycle
ZeroBitStuf:
nop ;oneskorenie 1 cyklus ;ENG;delay 1 cycle
cbr temp0,3
out outputport,temp0 ;vysli EOP na USB ;ENG;transmit EOP on USB
ldi bitcount,5 ;pocitadlo oneskorenia: EOP ma trvat 2 bity (16 cyklov pri 12MHz) ;ENG;delay counter: EOP shouls exists
2 bits (16 cycle at 12MHz)
SendUSBWaitEOP:
dec bitcount
brne SendUSBWaitEOP
sbi outputport,DATAminus ;nahodenie DATAminus : kludovy stav na port USB ;ENG;set DATAMINUS : idle state on USB port
sbi outputport,DATAminus ;oneskorenie 2 cykly: Idle ma trvat 1 bit (8 cyklov pri 12MHz) ;ENG;delay 2 cycle: Idle should
exists 1 bit (8 cycle at 12MHz)
cbi USBdirection,DATAplus ;DATAplus ako vstupny ;ENG;DATAPLUS as input
cbi USBdirection,DATAminus ;DATAminus ako vstupny ;ENG;DATAMINUS as input
cbi outputport,DATAminus ;zhodenie DATAminus : treti stav na port USB ;ENG;reset DATAMINUS : the third state on USB port
ret
;------------------------------------------------------------------------------------------
ToggleDATAPID:
lds temp0,OutputBufferBegin+1 ;nahraj posledne PID ;ENG;load last PID
cpi temp0,DATA1PID ;ak bolo posledne DATA1PID byte ;ENG;if last was DATA1PID byte
ldi temp0,DATA0PID
breq SendData0PID ;tak posli nulovu odpoved s DATA0PID ;ENG;then send zero answer with DATA0PID
ldi temp0,DATA1PID ;inak posli nulovu odpoved s DATA1PID ;ENG;otherwise send zero answer with DATA1PID
SendData0PID:
sts OutputBufferBegin+1,temp0 ;DATA0PID byte ;ENG;DATA0PID byte
ret
;------------------------------------------------------------------------------------------
ComposeZeroDATA1PIDAnswer:
ldi temp0,DATA0PID ;DATA0 PID - v skutocnosti sa stoggluje na DATA1PID v nahrati deskriptora ;ENG;DATA0 PID - in the next
will be toggled to DATA1PID in load descriptor
sts OutputBufferBegin+1,temp0 ;nahraj do vyst buffera ;ENG;load to output buffer
ComposeZeroAnswer:
ldi temp0,SOPbyte
sts OutputBufferBegin+0,temp0 ;SOP byte ;ENG;SOP byte
rcall ToggleDATAPID ;zmen DATAPID ;ENG;change DATAPID
ldi temp0,0x00
sts OutputBufferBegin+2,temp0 ;CRC byte ;ENG;CRC byte
sts OutputBufferBegin+3,temp0 ;CRC byte ;ENG;CRC byte
ldi ByteCount,2+2 ;dlzka vystupneho buffera (SOP a PID + CRC16) ;ENG;length of output buffer (SOP and PID + CRC16)
ret
;------------------------------------------------------------------------------------------
InitACKBufffer:
ldi temp0,SOPbyte
sts ACKBufferBegin+0,temp0 ;SOP byte ;ENG;SOP byte
ldi temp0,ACKPID
sts ACKBufferBegin+1,temp0 ;ACKPID byte ;ENG;ACKPID byte
ret
;------------------------------------------------------------------------------------------
SendACK:
push USBBufptrY
push bitcount
push OutBitStuffNumber
ldi USBBufptrY,ACKBufferBegin ;pointer na zaciatok ACK buffera ;ENG;pointer to begin of ACK buffer
ldi ByteCount,2 ;pocet vyslanych bytov (iba SOP a ACKPID) ;ENG;number of transmit bytes (only SOP and ACKPID)
clr OutBitStuffNumber
rcall SendUSBBuffer
pop OutBitStuffNumber
pop bitcount
pop USBBufptrY
ret
;------------------------------------------------------------------------------------------
InitNAKBufffer:
ldi temp0,SOPbyte
sts NAKBufferBegin+0,temp0 ;SOP byte ;ENG;SOP byte
ldi temp0,NAKPID
sts NAKBufferBegin+1,temp0 ;NAKPID byte ;ENG;NAKPID byte
ret
;------------------------------------------------------------------------------------------
SendNAK:
push OutBitStuffNumber
ldi USBBufptrY,NAKBufferBegin ;pointer na zaciatok ACK buffera ;ENG;pointer to begin of ACK buffer
ldi ByteCount,2 ;pocet vyslanych bytov (iba SOP a NAKPID) ;ENG;number of transmited bytes (only SOP and NAKPID)
clr OutBitStuffNumber
rcall SendUSBBuffer
pop OutBitStuffNumber
ret
;------------------------------------------------------------------------------------------
ComposeSTALL:
ldi temp0,SOPbyte
sts OutputBufferBegin+0,temp0 ;SOP byte ;ENG;SOP byte
ldi temp0,STALLPID
sts OutputBufferBegin+1,temp0 ;STALLPID byte ;ENG;STALLPID byte
ldi ByteCount,2 ;dlzka vystupneho buffera (SOP a PID) ;ENG;length of output buffer (SOP and PID)
ret
;------------------------------------------------------------------------------------------
DecodeNRZI: ;enkodovanie buffera z NRZI kodu do binarneho ;ENG;encoding of buffer from NRZI code to binary
push USBBufptrY ;zalohuj pointer do buffera ;ENG;back up pointer to buffer
push ByteCount ;zalohuj dlzku buffera ;ENG;back up length of buffer
add ByteCount,USBBufptrY ;koniec buffera do ByteCount ;ENG;end of buffer to ByteCount
ser temp0 ;na zabezpecenie jednotkoveho carry (v nasledujucej rotacii) ;ENG;to ensure unit carry (in the next rotation)
NRZIloop:
ror temp0 ;naplnenie carry z predchadzajuceho byte ;ENG;filling carry from previous byte
ld temp0,Y ;nahraj prijaty byte z buffera ;ENG;load received byte from buffer
mov temp2,temp0 ;posunuty register o jeden bit vpravo a XOR na funkciu NRZI dekodovania ;ENG;shifted register to one bit
to the right and XOR for function of NRZI decoding
ror temp2 ;carry do najvyssieho bitu a sucasne posuv ;ENG;carry to most significant digit bit and shift
eor temp2,temp0 ;samotne dekodovanie NRZI ;ENG;NRZI decoding
com temp2 ;negovanie ;ENG;negate
st Y+,temp2 ;ulozenie spat ako dekodovany byte a zvys pointer do buffera ;ENG;save back as decoded byte and increment pointer
to buffer
cp USBBufptrY,ByteCount ;ak este neboli vsetky ;ENG;if not all bytes
brne NRZIloop ;tak opakuj ;ENG;then repeat
pop ByteCount ;obnov dlzku buffera ;ENG;restore buffer length
pop USBBufptrY ;obnov pointer do buffera ;ENG;restore pointer to buffer
ret ;inak skonci ;ENG;otherwise finish
;------------------------------------------------------------------------------------------
BitStuff: ;odstranenie bit-stuffingu v buffri ;ENG;removal of bitstuffing in buffer
clr temp3 ;pocitadlo vynechanych bitov ;ENG;counter of omitted bits
clr lastBitstufNumber ;0xFF do lastBitstufNumber ;ENG;0xFF to lastBitstufNumber
dec lastBitstufNumber
BitStuffRepeat:
push USBBufptrY ;zalohuj pointer do buffera ;ENG;back up pointer to buffer
push ByteCount ;zalohuj dlzku buffera ;ENG;back up buffer length
mov temp1,temp3 ;pocitadlo vsetkych bitov ;ENG;counter of all bits
ldi temp0,8 ;spocitat vsetky bity v bufferi ;ENG;sum all bits in buffer
SumAllBits:
add temp1,temp0
dec ByteCount
brne SumAllBits
ldi temp2,6 ;inicializuj pocitadlo jednotiek ;ENG;initialize counter of ones
pop ByteCount ;obnov dlzku buffera ;ENG;restore buffer length
push ByteCount ;zalohuj dlzku buffera ;ENG;back up buffer length
add ByteCount,USBBufptrY ;koniec buffera do ByteCount ;ENG;end of buffer to ByteCount
inc ByteCount ;a pre istotu ho zvys o 2 (kvoli posuvaniu) ;ENG;and for safety increment it with 2 (because of shifting)
inc ByteCount
BitStuffLoop:
ld temp0,Y ;nahraj prijaty byte z buffera ;ENG;load received byte from buffer
ldi bitcount,8 ;pocitadlo bitov v byte ;ENG;bits counter in byte
BitStuffByteLoop:
ror temp0 ;naplnenie carry z LSB ;ENG;filling carry from LSB
brcs IncrementBitstuff ;ak LSB=0 ;ENG;if that LSB=0
ldi temp2,7 ;inicializuj pocitadlo jednotiek +1 (ak bola nula) ;ENG;initialize counter of ones +1 (if was zero)
IncrementBitstuff:
dec temp2 ;zniz pocitadlo jednotiek (predpoklad jednotkoveho bitu) ;ENG;decrement counter of ones (assumption of one bit)
brne NeposunBuffer ;ak este nebolo 6 jednotiek za sebou - neposun buffer ;ENG;if there was not 6 ones together - don't
shift buffer
cp temp1,lastBitstufNumber ;
ldi temp2,6 ;inicializuj pocitadlo jednotiek (ak by sa nerobil bitstuffing tak sa musi zacat odznova) ;ENG;initialize
counter of ones (if no bitstuffing will be made then must be started again)
brcc NeposunBuffer ;ak sa tu uz robil bitstuffing - neposun buffer ;ENG;if already was made bitstuffing - don't shift buffer
dec temp1 ;
mov lastBitstufNumber,temp1 ;zapamataj si poslednu poziciu bitstuffingu ;ENG;remember last position of bitstuffing
cpi bitcount,1 ;aby sa ukazovalo na 7 bit (ktory sa ma vymazat alebo kde sa ma vlozit nula) ;ENG;for pointing to 7-th bit
(which must be deleted or where to insert zero)
brne NoBitcountCorrect
ldi bitcount,9 ;
inc USBBufptrY ;zvys pointer do buffera ENG;increment pointer to buffer
NoBitcountCorrect:
dec bitcount
bst BitStuffInOut,0
brts CorrectOutBuffer ;ak je Out buffer - zvys dlzku buffera ;ENG;if this is Out buffer - increment buffer length
rcall ShiftDeleteBuffer ;posun In buffer ;ENG;shift In buffer
dec temp3 ;zniz pocitadlo vynechani ;ENG;decrement counter of omission
rjmp CorrectBufferEnd
CorrectOutBuffer:
rcall ShiftInsertBuffer ;posun Out buffer ;ENG;shift Out buffer
inc temp3 ;zvys pocitadlo vynechani ;ENG;increment counter of omission
CorrectBufferEnd:
pop ByteCount ;obnov dlzku buffera ;ENG;restore buffer length
pop USBBufptrY ;obnov pointer do buffera ;ENG;restore pointer to buffer
rjmp BitStuffRepeat ;a restartni od zaciatku ;ENG;and restart from begin
NeposunBuffer:
dec temp1 ;ak uz boli vsetky bity ;ENG;if already were all bits
breq EndBitStuff ;ukonci cyklus ;ENG;finish cycle
dec bitcount ;zniz pocitadlo bitov v byte ;ENG;decrement bits counter in byte
brne BitStuffByteLoop ;ak este neboli vsetky bity v byte - chod na dalsi bit ;ENG;if not yet been all bits in byte - go
to next bit
;inak nahraj dalsi byte ;ENG;otherwise load next byte
inc USBBufptrY ;zvys pointer do buffera ;ENG;increment pointer to buffer
rjmp BitStuffLoop ;a opakuj ;ENG;and repeat
EndBitStuff:
pop ByteCount ;obnov dlzku buffera ;ENG;restore buffer length
pop USBBufptrY ;obnov pointer do buffera ;ENG;restore pointer to buffer
bst BitStuffInOut,0
brts IncrementLength ;ak je Out buffer - zvys dlzku Out buffera ;ENG;if this is Out buffer - increment length of Out buffer
DecrementLength: ;ak je In buffer - zniz dlzku In buffera ;ENG;if this is In buffer - decrement length of In buffer
cpi temp3,0 ;bolo aspon jedno znizenie ;ENG;was at least one decrement
breq NoChangeByteCount ;ak nie - nemen dlzku buffera ;ENG;if no - don't change buffer length
dec ByteCount ;ak je In buffer - zniz dlzku buffera ;ENG;if this is In buffer - decrement buffer length
subi temp3,256-8 ;ak nebolo viac ako 8 bitov naviac ;ENG;if there wasn't above 8 bits over
brcc NoChangeByteCount ;tak skonci ;ENG;then finish
dec ByteCount ;inak este zniz dlzku buffera ;ENG;otherwise next decrement buffer length
ret ;a skonci ;ENG;and finish
IncrementLength:
mov OutBitStuffNumber,temp3 ;zapamataj si pocet bitov naviac ;ENG;remember number of bits over
subi temp3,8 ;ak nebolo viac ako 8 bitov naviac ;ENG;if there wasn't above 8 bits over
brcs NoChangeByteCount ;tak skonci ;ENG;then finish
inc ByteCount ;inak zvys dlzku buffera ;ENG;otherwise increment buffer length
mov OutBitStuffNumber,temp3 ;a zapamataj si pocet bitov naviac (znizene o 8) ;ENG;and remember number of bits over (decremented
by 8)
NoChangeByteCount:
ret ;skonci ;ENG;finish
;------------------------------------------------------------------------------------------
ShiftInsertBuffer: ;posuv buffer o jeden bit vpravo od konca az po poziciu: byte-USBBufptrY a bit-bitcount ;ENG;shift buffer
by one bit to right from end till to position: byte-USBBufptrY and bit-bitcount
mov temp0,bitcount ;vypocet: bitcount= 9-bitcount ;ENG;calculation: bitcount= 9-bitcount
ldi bitcount,9
sub bitcount,temp0 ;do bitcount poloha bitu, ktory treba nulovat ;ENG;to bitcount bit position, which is necessary to clear
ld temp1,Y ;nahraj byte ktory este treba posunut od pozicie bitcount ;ENG;load byte which still must be shifted from position
bitcount
rol temp1 ;a posun vlavo cez Carry (prenos z vyssieho byte a LSB do Carry) ;ENG;and shift to the left through Carry (transmission
from higher byte and LSB to Carry)
ser temp2 ;FF do masky - temp2 ;ENG;FF to mask - temp2
HalfInsertPosuvMask:
lsl temp2 ;nula do dalsieho spodneho bitu masky ;ENG;zero to the next low bit of mask
dec bitcount ;az pokial sa nedosiahne hranica posuvania v byte ;ENG;till not reached boundary of shifting in byte
brne HalfInsertPosuvMask
and temp1,temp2 ;odmaskuj aby zostali iba vrchne posunute bity v temp1 ;ENG;unmask that remains only high shifted bits
in temp1
com temp2 ;invertuj masku ;ENG;invert mask
lsr temp2 ;posun masku vpravo - na vlozenie nuloveho bitu ;ENG;shift mask to the right - for insertion of zero bit
ld temp0,Y ;nahraj byte ktory este treba posunut od pozicie bitcount do temp0 ;ENG;load byte which must be shifted from
position bitcount to temp0
and temp0,temp2 ;odmaskuj aby zostali iba spodne neposunute bity v temp0 ;ENG;unmask to remains only low non-shifted bits
in temp0
or temp1,temp0 ;a zluc posunutu a neposunutu cast ;ENG;and put together shifted and nonshifted part
ld temp0,Y ;nahraj byte ktory este treba posunut od pozicie bitcount ;ENG;load byte which must be shifted from position
bitcount
rol temp0 ;a posun ho vlavo cez Carry (aby sa nastavilo spravne Carry pre dalsie prenosy) ;ENG;and shift it to the left
through Carry (to set right Carry for further carry)
st Y+,temp1 ;a nahraj spat upraveny byte ;ENG;and load back modified byte
ShiftInsertBufferLoop:
cpse USBBufptrY,ByteCount ;ak nie su vsetky cele byty ;ENG;if are not all entire bytes
rjmp NoEndShiftInsertBuffer ;tak pokracuj ;ENG;then continue
ret ;inak skonci ;ENG;otherwise finish
NoEndShiftInsertBuffer:
ld temp1,Y ;nahraj byte ;ENG;load byte
rol temp1 ;a posun vlavo cez Carry (prenos z nizsieho byte a LSB do Carry) ;ENG;and shift to the left through Carry (carry
from low byte and LSB to Carry)
st Y+,temp1 ;a nahraj spat ;ENG;and store back
rjmp ShiftInsertBufferLoop ;a pokracuj ;ENG;and continue
;------------------------------------------------------------------------------------------
ShiftDeleteBuffer: ;posuv buffera o jeden bit vlavo od konca az po poziciu: byte-USBBufptrY a bit-bitcount ;ENG;shift buffer
one bit to the left from end to position: byte-USBBufptrY and bit-bitcount
mov temp0,bitcount ;vypocet: bitcount= 9-bitcount ;ENG;calculation: bitcount= 9-bitcount
ldi bitcount,9
sub bitcount,temp0 ;do bitcount poloha bitu, ktory este treba posunut ;ENG;to bitcount bit position, which must be shifted
mov temp0,USBBufptrY ;uschovanie pointera do buffera ;ENG;backup pointera to buffer
inc temp0 ;pozicia celych bytov do temp0 ;ENG;position of completed bytes to temp0
mov USBBufptrY,ByteCount ;maximalna pozicia do pointera ;ENG;maximum position to pointer
ShiftDeleteBufferLoop:
ld temp1,-Y ;zniz buffer a nahraj byte ;ENG;decrement buffer and load byte
ror temp1 ;a posun vpravo cez Carry (prenos z vyssieho byte a LSB do Carry) ;ENG;and right shift through Carry (carry
from higher byte and LSB to Carry)
st Y,temp1 ;a nahraj spat ;ENG;and store back
cpse USBBufptrY,temp0 ;ak nie su vsetky cele byty ;ENG;if there are not all entire bytes
rjmp ShiftDeleteBufferLoop ;tak pokracuj ;ENG;then continue
ld temp1,-Y ;zniz buffer a nahraj byte ktory este treba posunut od pozicie bitcount ;ENG;decrement buffer and load byte
which must be shifted from position bitcount
ror temp1 ;a posun vpravo cez Carry (prenos z vyssieho byte a LSB do Carry) ;ENG;and right shift through Carry (carry
from higher byte and LSB to Carry)
ser temp2 ;FF do masky - temp2 ;ENG;FF to mask - temp2
HalfDeletePosuvMask:
dec bitcount ;az pokial sa nedosiahne hranica posuvania v byte ;ENG;till not reached boundary of shifting in byte
breq DoneMask
lsl temp2 ;nula do dalsieho spodneho bitu masky ;ENG;zero to the next low bit of mask
rjmp HalfDeletePosuvMask
DoneMask:
and temp1,temp2 ;odmaskuj aby zostali iba vrchne posunute bity v temp1 ;ENG;unmask to remain only high shifted bits in
temp1
com temp2 ;invertuj masku ;ENG;invert mask
ld temp0,Y ;nahraj byte ktory este treba posunut od pozicie bitcount do temp0 ;ENG;load byte which must be shifted from
position bitcount to temp0
and temp0,temp2 ;odmaskuj aby zostali iba spodne neposunute bity v temp0 ;ENG;unmask to remain only low nonshifted bits
in temp0
or temp1,temp0 ;a zluc posunutu a neposunutu cast ;ENG;and put together shifted and nonshifted part
st Y,temp1 ;a nahraj spat ;ENG;and store back
ret ;a skonci ;ENG;and finish
;------------------------------------------------------------------------------------------
MirrorInBufferBytes:
push USBBufptrY
push ByteCount
ldi USBBufptrY,InputBufferBegin
rcall MirrorBufferBytes
pop ByteCount
pop USBBufptrY
ret
;------------------------------------------------------------------------------------------
MirrorBufferBytes:
add ByteCount,USBBufptrY ;ByteCount ukazuje na koniec spravy ;ENG;ByteCount shows to the end of message
MirrorBufferloop:
ld temp0,Y ;nahraj prijaty byte z buffera ;ENG;load received byte from buffer
ldi temp1,8 ;pocitadlo bitov ;ENG;bits counter
MirrorBufferByteLoop:
ror temp0 ;do carry dalsi najnizsi bit ;ENG;to carry next least bit
rol temp2 ;z carry dalsi bit na obratene poradie ;ENG;from carry next bit to reverse order
dec temp1 ;bol uz cely byte ;ENG;was already entire byte
brne MirrorBufferByteLoop ;ak nie tak opakuj dalsi najnizsi bit ;ENG;if no then repeat next least bit
st Y+,temp2 ;ulozenie spat ako obrateny byte a zvys pointer do buffera ;ENG;save back as reversed byte and increment
pointer to buffer
cp USBBufptrY,ByteCount ;ak este neboli vsetky ;ENG;if not yet been all
brne MirrorBufferloop ;tak opakuj ;ENG;then repeat
ret ;inak skonci ;ENG;otherwise finish
;------------------------------------------------------------------------------------------
;CheckCRCIn: ;ENG;CheckCRCIn:
; push USBBufptrY ;ENG; kiss USBBUFPTRY
; push ByteCount ;ENG; kiss ByteCount
; ldi USBBufptrY,InputBuffercompare ;ENG; ldi USBBUFPTRY,InputBuffercompare
; rcall CheckCRC ;ENG; rcall CheckCRC
; pop ByteCount ;ENG; pope ByteCount
; pop USBBufptrY ;ENG; pope USBBUFPTRY
; ret ;ENG; lip
;------------------------------------------------------------------------------------------
AddCRCOut:
push USBBufptrY
push ByteCount
ldi USBBufptrY,OutputBufferBegin
rcall CheckCRC
com temp0 ;negacia CRC ;ENG;negation of CRC
com temp1
st Y+,temp1 ;ulozenie CRC na koniec buffera (najskor MSB) ;ENG;save CRC to the end of buffer (at first MSB)
st Y,temp0 ;ulozenie CRC na koniec buffera (potom LSB) ;ENG;save CRC to the end of buffer (then LSB)
dec USBBufptrY ;pointer na poziciu CRC ;ENG;pointer to CRC position
ldi ByteCount,2 ;otocit 2 byty CRC ;ENG;reverse bits order in 2 bytes CRC
rcall MirrorBufferBytes ;opacne poradie bitov CRC (pri vysielani CRC sa posiela naskor MSB) ;ENG;reverse bits order in CRC
(transmiting CRC - MSB first)
pop ByteCount
pop USBBufptrY
ret
;------------------------------------------------------------------------------------------
CheckCRC: ;vstup: USBBufptrY = zaciatok spravy ,ByteCount = dlzka spravy ;ENG;input: USBBufptrY = begin of message ,ByteCount
= length of message
add ByteCount,USBBufptrY ;ByteCount ukazuje na koniec spravy ;ENG;ByteCount points to the end of message
inc USBBufptrY ;nastav pointer na zaciatok spravy - vynechat SOP ;ENG;set the pointer to message start - omit SOP
ld temp0,Y+ ;nahraj PID do temp0 ;ENG;load PID to temp0
;a nastav pointer na zaciatok spravy - vynechat aj PID ;ENG;and set the pointer to start of message - omit also PID
cpi temp0,DATA0PID ;ci je DATA0 pole ;ENG;if is DATA0 field
breq ComputeDATACRC ;pocitaj CRC16 ;ENG;compute CRC16
cpi temp0,DATA1PID ;ci je DATA1 pole ;ENG;if is DATA1 field
brne CRC16End ;ak nie tak skonci ;ENG;if no then finish
ComputeDATACRC:
ser temp0 ;inicializacia zvysku LSB na 0xff ;ENG;initialization of remaider LSB to 0xff
ser temp1 ;inicializacia zvysku MSB na 0xff ;ENG;initialization of remaider MSB to 0xff
CRC16Loop:
ld temp2,Y+ ;nahraj spravu do temp2 a zvys pointer do buffera ;ENG;load message to temp2 and increment pointer to buffer
ldi temp3,8 ;pocitadlo bitov v byte - temp3 ;ENG;bits counter in byte - temp3
CRC16LoopByte:
bst temp1,7
|