📄 usb90s23x3.asm
字号:
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
reti
;********************************************************************
;* Init program
;********************************************************************
;------------------------------------------------------------------------------------------
reset: ;inicializacia procesora a premennych na spravne hodnoty
ldi temp0,StackBegin ;inicializacia stacku
out SPL,temp0
clr XH ;Infra pointer
clr YH ;USB pointer
clr ZH ;ROM pointer
sts InfraBufferBegin,YH ;znuluj dlzky Infra kodu v bufferi
sts InfraBufferBegin+1,YH ;znuluj pocitadlo infra kodov v bufferi
clr MyUpdatedAddress ;nova adresa USB - nedekodovana
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,BaudRate ;nastavitvysielaciu rychlost UART-u
out UBRR,temp0
sbi UCR,TXEN ;povolit vysielanie UART-u
sbi UCR,RXEN ;povolit prijimanie UART-u
ldi temp0,0x0F ;INT0 - reagovanie na nabeznu hranu
out MCUCR,temp0 ;
ldi temp0,1<<INT0 ;povolit externy interrupt INT0
out GIMSK,temp0
rcall InitCounter ;inicializacia citaca na TSOP zmenu
;------------------------------------------------------------------------------------------
;********************************************************************
;* 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
mov ByteCount,InputBufferLength ;dlzka vstupneho buffera
rcall DecodeNRZI ;prevod kodovania NRZI na bity
rcall MirrorInBufferBytes ;prehodit poradie bitov v bajtoch
rcall BitStuff ;odstranenie bit stuffing
rcall CheckCRCIn ;kontrola CRC
rcall PrepareUSBOutAnswer ;pripravenie odpovede do vysielacieho buffera
ldi ActionFlag,DoReadySendAnswer
rjmp Main
;********************************************************************
;* Main program END
;********************************************************************
;------------------------------------------------------------------------------------------
;********************************************************************
;* Interrupt0 interrupt handler
;********************************************************************
INT0Handler: ;prerusenie INT0
in backupSREG,SREG
push temp0
push temp1
ldi temp0,3 ;pocitadlo trvania log0
ldi temp1,2 ;pocitadlo trvania log1
;cakanie na zaciatok paketu
CheckchangeMinus:
sbis inputport,DATAminus ;cakanie az sa zmeni D- na 1
rjmp CheckchangeMinus
CheckchangePlus:
sbis inputport,DATAplus ;cakanie az sa zmeni D+ na 1
rjmp CheckchangePlus
DetectSOPEnd:
sbis inputport,DATAplus
rjmp Increment0 ;D+ =0
Increment1:
ldi temp0,3 ;pocitadlo trvania log0
dec temp1 ;kolko cyklov trvala log1
nop
breq USBBeginPacket ;ak je to koniec SOP - prijimaj paket
rjmp DetectSOPEnd
Increment0:
ldi temp1,2 ;pocitadlo trvania log1
dec temp0 ;kolko cyklov trvala log0
nop
brne DetectSOPEnd ;ak nenastal SOF - pokracuj
rjmp EndInt0HandlerPOP2
EndInt0Handler:
pop ACC
pop InfraBufptrX
pop temp3
pop temp2
EndInt0HandlerPOP:
pop USBBufptrY
pop ByteCount
mov bitcount,backupbitcount ;obnova bitcount registra
EndInt0HandlerPOP2:
pop temp1
pop temp0
out SREG,backupSREG
ldi shiftbuf,1<<INTF0 ;znulovat flag interruptu INTF0
out GIFR,shiftbuf
reti ;inak skonci (bol iba SOF - kazdu milisekundu)
USBBeginPacket:
mov backupbitcount,bitcount ;zaloha bitcount registra
in shiftbuf,inputport ;ak ano nacitaj ho ako nulty bit priamo do shift registra
USBloopBegin:
push ByteCount ;dalsia zaloha registrov (setrenie casu)
push USBBufptrY
ldi bitcount,6 ;inicializacia pocitadla bitov v bajte
ldi ByteCount,MAXUSBBYTES ;inicializacia max poctu prijatych bajtov v pakete
ldi USBBufptrY,InputShiftBufferBegin ;nastav vstupny buffer
USBloop1_6:
in inputbuf,inputport
cbr inputbuf,USBpinmask ;odmaskovat spodne 2 bity
breq USBloopEnd ;ak su nulove - koniec USB packetu
ror inputbuf ;presun Data+ do shift registra
rol shiftbuf
dec bitcount ;zmensi pocitadlo bitov
brne USBloop1_6 ;ak nie je nulove - opakuj naplnanie shift registra
nop ;inak bude nutne skopirovat shift register bo buffera
USBloop7:
in inputbuf,inputport
cbr inputbuf,USBpinmask ;odmaskovat spodne 2 bity
breq USBloopEnd ;ak su nulove - koniec USB packetu
ror inputbuf ;presun Data+ do shift registra
rol shiftbuf
ldi bitcount,7 ;inicializacia pocitadla bitov v bajte
st Y+,shiftbuf ;skopiruj shift register bo buffera a zvys pointer do buffera
USBloop0: ;a zacni prijimat dalsi bajt
in shiftbuf,inputport ;nulty bit priamo do shift registra
cbr shiftbuf,USBpinmask ;odmaskovat spodne 2 bity
breq USBloopEnd ;ak su nulove - koniec USB packetu
dec bitcount ;zmensi pocitadlo bitov
nop ;
dec ByteCount ;ak sa nedosiahol maximum buffera
brne USBloop1_6 ;tak prijimaj dalej
rjmp EndInt0HandlerPOP ;inak opakuj od zaciatku
USBloopEnd:
cpi USBBufptrY,InputShiftBufferBegin+3 ;ak sa neprijali aspon 3 byte
brcs EndInt0HandlerPOP ;tak skonci
lds temp0,InputShiftBufferBegin+0 ;identifikator paketu do temp0
lds temp1,InputShiftBufferBegin+1 ;adresa do temp1
brne TestDataPacket ;ak je dlzka ina ako 3 - tak to moze byt iba DataPaket
TestIOPacket:
cp temp1,MyAddress ;ak to nie je urcene (adresa) pre mna
brne TestDataPacket ;tak to moze byt este Data Packet
TestSetupPacket:;test na SETUP paket
cpi temp0,nNRZISETUPPID
brne TestOutPacket ;ak nie je Setup PID - dekoduj iny paket
ldi State,SetupState
rjmp EndInt0HandlerPOP ;ak je Setup PID - prijimaj nasledny Data paket
TestOutPacket: ;test na OUT paket
cpi temp0,nNRZIOUTPID
brne TestInPacket ;ak nie je Out PID - dekoduj iny paket
ldi State,OutState
rjmp EndInt0HandlerPOP ;ak je Out PID - prijimaj nasledny Data paket
TestInPacket: ;test na IN paket
cpi temp0,nNRZIINPID
brne TestDataPacket ;ak nie je In PID - dekoduj iny paket
rjmp AnswerToInRequest
TestDataPacket: ;test na DATA0 a DATA1 paket
cpi temp0,nNRZIDATA0PID
breq Data0Packet ;ak nie je Data0 PID - dekoduj iny paket
cpi temp0,nNRZIDATA1PID
brne NoMyPacked ;ak nie je Data1 PID - dekoduj iny paket
Data0Packet:
cpi State,SetupState ;ak bol stav Setup
breq ReceiveSetupData ;prijmi ho
cpi State,OutState ;ak bol stav Out
breq ReceiveOutData ;prijmi ho
NoMyPacked:
ldi State,BaseState ;znuluj stav
rjmp EndInt0HandlerPOP ;a prijimaj nasledny Data paket
AnswerToInRequest:
push temp2 ;zazalohuj dalsie registre a pokracuj
push temp3
push InfraBufptrX
push ACC
cpi ActionFlag,DoReadySendAnswer ;ak nie je pripravena odpoved
brne NoReadySend ;tak posli NAK
rcall SendPreparedUSBAnswer ;poslanie odpovede naspat
and MyUpdatedAddress,MyUpdatedAddress ;ak je MyUpdatedAddress nenulova
brne SetMyNewUSBAddress ;tak treba zmenit USB adresu
ldi State,InState
ldi ActionFlag,DoPrepareOutContinuousBuffer
rjmp EndInt0Handler ;a opakuj - cakaj na dalsiu odozvu z USB
ReceiveSetupData:
push temp2 ;zazalohuj dalsie registre a pokracuj
push temp3
push InfraBufptrX
push ACC
rcall SendACK ;akceptovanie Setup Data paketu
rcall FinishReceiving ;ukonci prijem
ldi ActionFlag,DoReceiveSetupData
rjmp EndInt0Handler
ReceiveOutData:
push temp2 ;zazalohuj dalsie registre a pokracuj
push temp3
push InfraBufptrX
push ACC
cpi ActionFlag,DoReceiveSetupData ;ak sa prave spracovava prikaz Setup
breq NoReadySend ;tak posli NAK
rcall SendACK ;akceptovanie Out paketu
clr ActionFlag
rjmp EndInt0Handler
NoReadySend:
rcall SendNAK ;este nie som pripraveny s odpovedou
rjmp EndInt0Handler ;a opakuj - cakaj na dalsiu odozvu z USB
;------------------------------------------------------------------------------------------
SetMyNewUSBAddress: ;nastavi novu USB adresu v NRZI kodovani
clr MyAddress ;vychodzi stav odpovede - mojej nNRZI USB adresy
ldi temp2,0b00000001 ;maska na xorovanie
ldi temp3,8 ;pocitadlo bitov
SetMyNewUSBAddressLoop:
mov temp0,MyAddress ;zapamatat si koncovu odpoved
ror MyUpdatedAddress ;do carry vysielany bit LSB (v smere naskor LSB a potom MSB)
brcs NoXORBit ;ak je jedna - nemen stav
eor temp0,temp2 ;inak sa bude stav menit podla posledneho bitu odpovede
NoXORBit:
ror temp0 ;posledny bit zmenenej odpovede do carry
rol MyAddress ;a z carry do koncovej odpovede na miesto LSB (a sucasne prehodenie LSB a MSB poradia)
dec temp3 ;zmensi pocitadlo bitov
brne SetMyNewUSBAddressLoop ;ak pocitadlo bitov nie je nulove opakuj vysielanie s dalsim bitom
clr MyUpdatedAddress ;znulovanie adresy ako priznak jej buduceho nemenenia
rjmp EndInt0Handler
;------------------------------------------------------------------------------------------
FinishReceiving: ;korekcne akcie na ukoncenie prijmu
cpi bitcount,7 ;prenes do buffera aj posledny necely byte
breq NoRemainingBits ;ak boli vsetky byty prenesene, tak neprenasaj nic
inc bitcount
ShiftRemainingBits:
rol shiftbuf ;posun ostavajuce necele bity na spravnu poziciu
dec bitcount
brne ShiftRemainingBits
st Y+,shiftbuf ;a skopiruj shift register bo buffera - necely byte
NoRemainingBits:
mov ByteCount,USBBufptrY
subi ByteCount,InputShiftBufferBegin-1 ;v ByteCount je pocet prijatych byte (vratane necelych byte)
mov InputBufferLength,ByteCount ;a uchovat pre pouzitie v hlavnom programe
ldi USBBufptrY,InputShiftBufferBegin ;pointer na zaciatok prijimacieho shift buffera
ldi InfraBufptrX,InputBufferBegin+1 ;data buffer (vynechat SOP)
MoveDataBuffer:
ld temp0,Y+
st X+,temp0
dec ByteCount
brne MoveDataBuffer
ldi ByteCount,nNRZISOPbyte
sts InputBufferBegin,ByteCount ;ako keby sa prijal SOP - nekopiruje sa zo shift buffera
ret
;------------------------------------------------------------------------------------------
;********************************************************************
;* Other procedures
;********************************************************************
;------------------------------------------------------------------------------------------
USBReset: ;inicializacia USB stavoveho stroja
ldi temp0,nNRZIADDR0 ;inicializacia USB adresy
mov MyAddress,temp0
clr State ;inicializacia stavoveho stroja
clr BitStuffInOut
clr OutBitStuffNumber
clr ActionFlag
clr RAMread ;bude sa vycitavat z ROM-ky
clr ConfigByte ;nenakonfiguravany stav
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -