📄 usb2lpt2.a51
字号:
;FX2-Firmware f黵 USB2LPT2, haftmann#software 08/05
;Bis jetzt wird nur ein dptr benutzt (also kein DPS), nur Registerbank 0
;Zu 黚ersetzen mit ASEM51; EEPROM-Datei erstellen mit
;HEX2BIX -F 0xC2 -I -V 0x16C0 -P 0x06B3
;Pro OUT-Befehl werden zwei Bytes in die OUT-Pipe geschrieben.
;F黵 jeden IN-Befehl wird ein Byte [Adresse] in die OUT-Pipe gesetzt,
; als Folge kommt ein Byte [Daten] in die IN-Pipe. Genaueres siehe "upv"!
;Seriennummern-Position: 1 Byte @ FFFFh (alt), 4 Byte @ FFFCh (Intel, neu)
;06xxxx EEPROM+XRAM-Routinen
;060622 Gekaufte VID+PID eingetragen
;060629 Einzelpin-Richtungsumschaltung
;060630 Open-Collector-Simulation (Daten- und Steuerpins)
;060706 Richtungsbit-Simulation korrigiert (stets 0 bei Mode 0 und 2)
;060710 EPP: allgemeine Fehlerbeseitigung, getestet
;060711 Schattenregister f黵 Steuerport, Code-Erweiterbarkeit f黵 Anwender
;060809 DirectIo, korrigiertes Open-Collector-Verhalten (Steuerport), EEPROM
;060811 Drei ungenutzte PortD-Leitungen auf drei Massepins geroutet
;070128 Richtungsbits ge鋘dert auf 0=Eingang, 1=Ausgang (wie EZUSB und ATmega)
;070128 Steuerport-Richtungsfestlegung 黚er High-Nibble von GpifIdleCfg
;070209 Achtelung der Helligkeit allzu heller blauer LEDs mit Schaltbit
;Zu tun:
$nopaging
$nosymbols
$nomod51
$nolist
$include(ezusbfx2.mcu)
$include(makros.i51)
$list
$genonly ;das "Innere" von Makros
$condonly ;das "Innere" von IFxx
DateYear equ 2007 ;"Versionskennung"
DateMonth equ 2
DateDay equ 9
Interfaces equ 2 ;1 = ohne "USB-Druckerunterst黷zung"
;(so l鋝st es sich besser debuggen)
MyId equ 1 ;0 = Cypress-ID (Debuggen mit Cypress-Tools)
Always_Renum equ 0 ;1: Firmware-Update im Ger鋞emanager versagt
Gpif equ 0 ;Benutze GPIF - oder Handarbeit f黵s Drucken
;###############
;## Schaltung ##
;###############
;Datenport (Basisadresse+0) = PortB (mit korrekter Bit-Anordnung, = FIFO-Port)
;Statusport (Basisadresse+1) = PortA (Bits 5-4-3 auf Portbits 5-6-1)
; und RDYx (Bits 7-6 auf Portbits 0-1)
;Rev.3: = PortD (Bits 7-3 auf Portbits 7-3), RDYx gleich
;Rev.4: zus鋞zlich PortD (Bits 2-0 auf Extra-Bits 2-0)
;Steuerport (Basisadresse+2) = PortA (Bit 2 auf Portbit 2)
; und CTLx (Bits 0-1-3 auf Portbits 0-1-2)
;Rev.3: = PortA (Bits 3-0 auf Portbits 3-0), CTLx gleich
;Die Zuweisung auf CTLx und RDYx erfolgte f黵 Implementierbarkeit von
;SPP, ECP und EPP mithilfe von GPIF (also sehr schnell!),
;die 黚rige Zuweisung auf PortA nach g黱stigster Leiterbahnf黨rung.
;Problem: Steuerport ist nicht r點klesbar! Korrektur in Revision 3,
; durch Routing der CTLx-Leitungen auf PortD
;Die Symbole PE,ONL,ERR,INI werden nur f黵 Rev.2 verwendet. JTAG Rev.3
BSY EQU 0 ;RDY1 (/7) (ist mit D6 verbunden) IOD.7
ACK EQU 1 ;RDY0 ( 6) IOD.6
PE EQU 5 ;IOA.5 ( 5) (ist mit D6 verbunden) IOD.5
ONL EQU 6 ;IOA.6 ( 4) D/P TDO IOD.4
ERR EQU 1 ;IOA.1 ( 3) Ucc Ucc IOD.3
SEL EQU 2 ;CTL2 (/3) IOA.3
INI EQU 2 ;IOA.2 ( 2) IOA.2
AF EQU 1 ;CTL1 (/1) IOA.1
STB EQU 0 ;CTL0 (/0) IOA.0
; ;D4 /PROG (zieht TDO auf Low)
; ;D3 /CTRL (aktiviert 2 Ausgangstreiber)
; ;D2 PROG TMS
; ;D1 CCLK TCK
; ;D0 DIN TDI
Ledr2 equ IOA.0 ;LOW-aktiv IOA.4
Led2r2 equ IOA.7 ;LOW-aktiv IOA.5
Led equ IOA.4
Led2 equ IOA.5
DefIOA equ 0FFh ;alles High, auch LEDs
DefOEAr2 equ 10011101b
;IOA.1 und IOA.3 sind noch frei, evtl. Steuerung der Pull-UpWiderst鋘de
; in Rev. 3 zur Energieeinsparung bei Idle, IOA.1 f黵 ACK-Interrupt
DefOEA equ 10110100b
;###############
;## Endpoints ##
;###############
;Pipe Funktion EZUSB FX2 ?
;0 OUT-Adressen, OUT-Daten, IN-Adressen EP2Out EP2(Out)EP1
;1 IN-Daten EP2In EP6(In) EP1
;2(=0) USB-Druckerunterst黷zung Vorw鋜tskanal EP4Out EP4(Out)EP2
;3(=1) USB-Druckerunterst黷zung R點kkanal EP4In EP8(In) EP6
;4(=0) JTAG Out EP6 EP4
;5(=1) JTAG In EP6 EP8
;-----------
;## DATEN ## Der Datenbereich wird beim Firmware-Start mit Nullen gel鰏cht
;-----------
DSEG AT 20h ;bitadressierbar
IntReq: ds 1 ;f黵 USB-Interruptrequests, bitadressierbar
Configuration: ds 1 ;hier: Null (adressiert) oder Eins (konfig.)
AltSetting1: ds 1 ;Null, Eins oder Zwei (nur f黵 2. Interface)
bits: ds 1 ;diverse Bits
HighSpeed BIT bits.0 ;Kopie von UsbIrq.HsGrant
Led_B BIT bits.1 ;Solange gelbe LED blinkt
Led2_B BIT bits.2 ;Solange blaue (High-Speed-)LED blinkt
Rev2 BIT bits.3 ;Zur Verzweigung bei dennoch gleicher Firmware
FeatureChanged BIT bits.4 ;Feature-Byte in EEPROM brennen (persistent)
Led2State BIT bits.5 ;Eigentlicher Zustand der blauen LED
Data5V BIT bits.6 ;wie OCData && !direction
Control5V BIT bits.7 ;wie (SPP && !TPControl) || OCControl
;===Druckerport===
DCR: ds 1 ;Device Control Register (+2)
ackIntEn BIT DCR.4 ;1=ein, r點klesbar, aber nicht unterst黷zt
direction BIT DCR.5 ;0=OUT, 1=IN, klebt auf 0 bei Mode=0 oder =2
ECR: ds 1 ;Extended Control Register (ECP 402)
fifoe BIT ECR.0 ;1 wenn FIFO leer
fifof BIT ECR.1 ;1 wenn FIFO voll
ECR_Bits: ds 1 ;Mit immer nur einem Bit gesetzt
EPPTimeOut: ds 1 ;Bit0=0: kein TimeOut aufgetreten
;Bit2=0: Interrupt aufgetreten (zz. ungenutzt)
;Alle anderen Bits m黶sen =1 sein!
Feature: ds 1
OCData BIT Feature.0 ;Offene-Senke-Simulation f黵 Daten (+0)
TPControl BIT Feature.1 ;Totempfahl auch bei SPP (bei Rev.2 immer 1)
OCControl BIT Feature.2 ;Offene-Senke-Simulation f黵 Steuerport (+2)
DarkBlue BIT Feature.5 ;dunklere blaue LED
DirectIo BIT Feature.6 ;keine Invertierungen, kein Datenrichtungsbit
PullUps BIT Feature.7 ;Deaktivierung der externen Pullups ab Rev.3
;===I睠===
I2C_ALen: ds 1 ;entspricht etwa wIndexH beim Vendor-Request A2
I2C_ALen0 BIT I2C_ALen.0 ; 1 = 1 Byte, oder 2 Bytes vertauscht
I2C_ALen1 BIT I2C_ALen.1 ; 1 = 2 Bytes (sonst 0 oder 1 Byte)
I2C_NoStop BIT I2C_ALen.2
I2C_NoStart BIT I2C_ALen.3
I2C_Paging BIT I2C_ALen.4 ; 1 = Paging aktiv (nicht wIndexH)
I2C_Verify BIT I2C_ALen.5 ; zusammen mit Paging immer Verify
DSEG AT 30h ;nicht bitadressierbar
FIFOSIZE equ 16
;===FIFO===... hat hier eine Tiefe von FIFOSIZE W鰎tern zu je 9 Bit
Fifo: ds FIFOSIZE*2 ;Wegen ECP brauchen wir 9 bit Breite!
fifor: ds 1 ;Fifo-Lesezeiger
fifow: ds 1 ;Fifo-Schreibzeiger
;===allgemein===
Led_T: ds 1 ;"Nachblinkzeit" der LED in ms
Led_F: ds 1 ;"Blinkfrequenz" in ms (halbe Periode)
Led_C: ds 1 ;Blink-Z鋒ler
Led2_T: ds 1
Led2_F: ds 1
Led2_C: ds 1
FrameCnt: ds 1 ;zum Mitz鋒len "ganzer" USB-Rahmen (HighSpeed)
UniIdxL: ds 1 ;Index in OUT4BUF zum byteweisen Lesen
UniIdxH: ds 1
ep2ll: ds 1 ;L鋘genz鋒ler f黵 EP2-Verarbeitung
ep2lh: ds 1
;=== Variablen f黵 I睠/EEPROM ===
I2C_Addr: ds 1 ;I睠-Adresse (EEPROM)
I2C_PMask: ds 1 ;F黵 seiten-weises EEPROM-Schreiben,
;00 = einzelbyteweise, 07 = 8-Byte-Seite, 1F = 32-Byte-Seite usw.
;07 (8bit), 1F (16bit) oder (1<<High-Nibble von wIndexH)-1 (Request ED)
;Die PMask wird mit dem LOW-Teil der laufenden Adresse geODERt; bei
;Ergebnis Null wird der I睠-Transfer unterbrochen und das Brennen ausgel鰏t.
IF Gpif
OutB equ GpifSglDatLX
TRISB MACRO v
STX GpifIdleCS,v
ENDM
ELSE
OutB equ IOB
TRISB MACRO v
IFNB <v>
mov OEB,#v
ELSE
mov OEB,a
ENDIF
ENDM
ENDIF
;--------------
;## PROGRAMM ##
;--------------
CSEG AT 0
ljmp main ;am Reset-Vektor
SAVEORG 6,0
dwi %(DateYear-1980)*512+DateMonth*32+DateDay
SAVEORG 2Eh
Scratch:ds 1 ;f黵 EEPROM-Transfer
usr2f: RETC ;@002F Ansprung bei Ausgabebyte > 20h, ersetzen mit AJMP
usr31: RETC ;@0031 unbekannter Request 黚er EP0, ersetzen mit AJMP
SAVEORG RESUME ;RESUME-ISR @33h (erforderlich, sonst geht das Wecken nicht)
clr EICON.4
reti
usr36: ret ;@0036 Zyklischer Ansprung, ersetzen mit AJMP (oder LJMP)
ORG 1000h ;4 Kilobyte f黵 User
;--------------------------------------------------------------------
ResetFifos:
STX GpifAbort
SyncDelay
STX FifoReset,80h
SyncDelay
STX ,2
SyncDelay
STX ,4
SyncDelay
STX ,6
SyncDelay
STX ,8
SyncDelay
STX ,0
SyncDelay
STX OutPktEnd,82h
SyncDelay
STX
SyncDelay
STX OutPktEnd,84h
SyncDelay
STX
ret
;EEPROM-Adresse (gerade; Schreibadresse) am I睠-Bus
EADDR equ 0A0h ;f黵 8-bit-EEPROM, 16-bit-EEPROMS haben EADR+2
;EEPROM-Default-"Seitengr鲞e" zum Brennen mehrerer Bytes auf einmal
EPAGE8 equ 8 ;f黵 8-bit-EEPROM 24LC01/02
EPAGE16 equ 32 ;f黵 16-bit EEPROM 24LC32/64
;Andere EEPROM-Typen m黶sen per wIndex ausgew鋒lt werden.
;Eine "Seitengr鲞e" von 1 f黨rt zum Einzelbyte-Brennen (viel langsamer)
;Die Auswahl 8/16 bit erfolgt automatisch anhand I2CS.4 wie im EZUSB-Kern
;======================
;== Byte-Ein/Ausgabe ==
;======================
i2c_wr: ;Byte auf I睠 schreiben (kann blockieren!)
;PE: A=Ausgabe-Byte
;PA: CY=1 bei Fehler oder NAK, ACC.4=ID1
STX I2DAT
dec r0 ;auf I2CS
i2c_w: LDX
mov c,ACC.2 ;BERR-Bit
jc i2c_err
jnb ACC.0,i2c_w ;DONE-Bit
orl c,/ACC.1 ;ACK-Bit=0 -> C=1
ret
i2c_rd: ;Byte von I睠 lesen (kann blockieren!)
;PE: R4=Anzahl noch zu lesender Bytes (f黵 LASTRD und STOP)
;PA: A=Eingabe-Byte
mov r0,#LOW(I2CS)
i2c_r: LDX
mov c,ACC.2 ;BERR-Bit
jc i2c_err
jnb ACC.0,i2c_r ;DONE-Bit
i2c_d: ;Dummy-Lesezugriff (Seiteneinstieg mit A=0 und R0=I2CS)
jb I2C_NoStop,i2c_b
cjne r4,#2,i2c_a
setb ACC.5 ;LASTRD setzen
i2c_a: cjne r4,#1,i2c_b
setb ACC.6 ;STOP setzen
i2c_b: STX ;LASTRD bzw. STOP setzen
LDX NEXT ;I2DAT lesen
i2c_err:ret
;==============================
;== I睠(EEPROM)-Adressierung ==
;==============================
EAdr: ;I睠 starten und (Adress-)Bytes ausgeben
;PE: DPTR=Adresse (DPL allein, wenn ALEN<2)
;PA: CY=1 bei Fehler
;VR: A,R0,R2
;N: Diese Routine kann bis 10 ms blockieren, bis der EEPROM bereit ist
; (weil er sich bis zum Fertigschreiben I睠-busseitig tot stellt)
LDX I2CS
jb ACC.6,EAdr ;Stoppsequenz abwarten
mov r2,#0 ;max. 256 Versuche, 10 ms = 120000 CPU-Takte
eal: jb I2C_NoStart,ea_nostart
STX I2CS,80h ;(4) Startsequenz ausgeben
ea_nostart:
mov a,I2C_Addr ;(2) I睠-Adresse: Schreiben
call i2c_wr ;(>=25)
jnc ea1 ;(3) EEPROM k鰊nte mit Brennen besch鋐tigt sein
jb ACC.2,eae ;(3) wenn BERR nicht noch einmal versuchen
jnb I2C_Paging,eae ;(3) raus mit Fehler (nicht neu versuchen)
mov r0,#144 ;(2)
djnz r0,$ ;(144*3) warten
djnz r2,eal ;(3) ... Adressierung wiederholen!
eae: ret ;raus (ggf. mit Fehler)
ea1: ;Adressbyte-Ausgabe (Tabelle s.u.)
jnb I2C_ALen0,ea_x0
mov a,DPL0 ;EEPROM-Adresse Low-Teil - oder Low-Teil zuerst
call i2c_wr
jc i2c_err
jnb I2C_ALen1,eae ; kein Fehler: fertig
mov a,DPH0 ;EEPROM-Adresse High-Teil
jmp i2c_wr
ea_x0:
jnb I2C_ALen1,eae ; kein Fehler: fertig ohne ein Adressbyte
mov a,DPH0 ;EEPROM-Adresse High-Teil zuerst
call i2c_wr
jc i2c_err
mov a,DPL0 ;EEPROM-Adresse Low-Teil als zweites
jmp i2c_wr ;immer schreiben und Ende
;Adressbyte-Ausgabe tabellarisch
; I2C_ALen wIndexH ! I睠-Ausgabe
;ALen1 ALen0 ALEN ! 1.Byte 2.Byte
;0 0 0 ! - -
;0 1 1 ! DPL - DPL = wValueL
;1 0 2 ! DPL DPH DPH = wValueH
;1 1 3 ! DPH DPL
;=============================
;== I睠(EEPROM)-Ein/Ausgabe ==
;=============================
EWrite: ;(Boot-EEPROM oder beliebiges) I睠-Ger鋞 schreiben
;PE: DPTR=(EEPROM-)Adresse (Ziel)
; I2C_Addr = I睠-Adresse
; I2C_ALen = I睠-Adressl鋘ge sowie 黚rige Bits
; I2C_PMask= Seiten-Maske
; AutoPtr=Puffer-Adresse (zu schreibende Daten)
; R4=L鋘ge der Daten (0 = keine Daten)
;PA: CY=1 bei Fehler, dann R4=verbliebene Bytes im Puffer
; DPTR erh鰄t
;VR: A,DPTR,R0,R2,R4
call EAdr
jc ewe
inc r4
sjmp ewf
ewl:
LDX1
call i2c_wr ;1 Byte schreiben (noch nicht brennen)
jc ewe
inc dptr ;EEPROM-Adresse mitz鋒len
jnb I2C_Paging,ewf
mov a,I2C_PMask
anl a,DPL0
jz ewp ;Seite zu Ende!
ewf: djnz r4,ewl ;in Seite, n鋍hstes Byte
jb I2C_NoStop,ewr
ewe: STX I2CS,40h ;Stoppsequenz
ewr: ret
ewp: STX I2CS,40h ;Stoppsequenz, damit brennen
djnz r4,EWrite ;weitermachen, n鋍hster Block
ret
EE_W: jnb I2C_Verify,EWrite ;sofort zum Schreiben gehen!
push DPL0 ;Adresse zwecks Vergleichen retten
push DPH0
push AR4
call EWrite
pop AR4
pop DPH0
pop DPL0 ;Adresse zur點kstellen
MOVW AutoPtr1,Out0Buf;auch Vergleichspuffer zur點k
setb F0
jnc ERead ;Vergleichen
ret
ERead: ;Boot-EEPROM lesen oder 黚erpr黤en
;PE: DPTR=EEPROM-Adresse (Quelle)
; I2C_Addr = I睠-Adresse
; I2C_ALen = I睠-Adressl鋘ge sowie NoStart und NoStop-Bits
; AutoPtr=Puffer-Adresse (Lese-Puffer), R1=XAutoDat
; R4=L鋘ge Daten/Puffer (0 = nicht erlaubt!)
; F0=0: lesen, F0=1: pr黤en/vergleichen (Verify)
;PA: CY=1 bei Fehler, dann R4=verbliebene Bytes im Puffer
; DPTR erh鰄t
;VR: A,DPTR,R0,R2,R4
jb I2C_NoStart,erns ;Hier: Auch keine Adressbytes ausgeben!
call EAdr
jc ere
STX I2CS,80h ;Noch eine Startsequenz ausgeben
erns: mov a,I2C_Addr ;I睠-Adresse
inc a ;Leseadresse
call i2c_wr
jc ere
inc r4 ;Problem: Klappt nicht mit R4=0
call i2c_d ;Dummy-Lesezugriff von I2DAT
dec r4
erl:
call i2c_rd ;Byte lesen
jc ere
jb F0,erv ;Vergleichen
STX1
sjmp er1
erv: mov r0,a
LDX1
xrl a,r0 ;A=0 wenn gleich
jnz eru ;raus mit Fehler wenn ungleich
er1: inc dptr ;EEPROM-Adresse mitz鋒len
djnz r4,erl
jb I2C_NoStop,er9 ;Stopp-Unterdr點kung nur bei regul鋜em Ende!
db 0E5h ;mov a,xx
eru: setb c
ere: STX I2CS,40h ;Stoppsequenz
er9: ret
;===================================
;== Arbeitszellen-Initialisierung ==
;===================================
EReqInit: ;A2-Request auswerten und drei I睠-Parameter zusammenstellen
;PE: wIndex = USB-Parameter (ACHTUNG bei EZUSB Control Panel [Rindfleisch])
;VR: A,R0,I2C_Addr,I2C_ALen,I2C_PMask
LDX SetupDat+4 ;wIndexL
jnz eri_nBootRom
EReqInitBoot: ;Seiteneinstieg f黵 Startup
LDX I2CS ;bei wIndexL=0 Boot-ROM automatisch w鋒len
mov c,ACC.4 ;ID1-Bit = 1 bei 16-bit-EEPROM
mov a,#EADDR
mov ACC.1,c ;ggf. aus A0 ein A2 machen
mov I2C_Addr,a
clr a
addc a,#1 ;Adressl鋘ge 1 oder 2 Bytes
mov I2C_ALen,a
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -