📄 usb2lpt2.a51
字号:
sjmp eri_Auto
eri_nBootRom:
clr ACC.0 ;Hier: Schreibadresse!
mov I2C_Addr,a
LDX NEXT ;wIndexH
anl a,#0Fh ;Low-Nibble
mov I2C_ALen,a ;黚ernehmen, wie es ist
LDX ;noch einmal wIndexH
swap a
anl a,#0Fh ;High-Nibble
jnz eri_nAuto
eri_Auto: ;bei HINIBBLE(wIndexH)=0 Paginierung automatisch
mov a,I2C_Addr
anl a,#0F0h
xrl a,#0A0h ;Irgendein serieller EEPROM-Typ (Axh)?
jnz eri_e ;nein, keine (automatische) Paginierung
mov a,I2C_ALen
cjne a,#1,eri_n1 ;Adress-L鋘ge 1? (Und kein NoStop/NoStart?)
mov a,#EPAGE8-1 ;Maske setzen
sjmp eri_s
eri_n1: cjne a,#2,eri_e ;Adress-L鋘ge 2? Alles andere: ohne Auto-Paging!
mov a,#EPAGE16-1 ;Maske setzen
sjmp eri_s
eri_nAuto:
mov r0,a ;Bitmaske erzeugen: 1->00, 2->01, 3->03
clr a ;4->07, 5->0F, 6->1F, 7->3F, 8->7F, 9->FF
sjmp eri_f
eri_l: setb c
rlc a ;nach links schieben, Einsen einf黦en
eri_f: djnz r0,eri_l
eri_s: mov I2C_PMask,a
setb I2C_Paging ;Auto-Paging aktivieren
setb I2C_Verify ;Verify aktivieren (vorerst gemeinsam)
eri_e: RETNC ;(wom鰃lich sp鋞er auch beim Lesen, wenn erf.)
;=============================
;== EEPROM- und RAM-Zugriff ==
;=============================
MemR: LODS ;lesen (Zweiter Autopointer versagt
STX1 ;sowieso wegen Bug im FX2!!)
djnz r4,MemR
ret
MemW: LDX1
STOS ;schreiben
djnz r4,MemW
ret
Partial_64:
;Subtrahiert 64 (bzw. R4) von der Gesamtl鋘ge; R7=0 wenn letzter Block
mov r4,#64
Partial_r4:
mov a,r6
subb a,r4
jnc pa1
clr c
djnz r7,pa1 ;Letzte "Runde" mit R7=0
LD r4,a,r6
inc r4
ret
pa1: mov r6,a
ret
LongEP0:
;Diese Routine funktioniert "absichtlich" nicht bei L鋘gen >=FF00h,
;Control-Transfers sind ohnehin auf 1000h (4KB) beschr鋘kt.
;Behandlung aller "langen" EP0-Transfers, mit selbstmodifizierendem Code
;dptr=Zeiger Leseroutine (R1=AutoPtr-EP0Buf, DPTR=wValue, R4=L鋘ge)
;R7:R6=Zeiger Schreibroutine (dito, f黵 OUT-Transfers)
;Alle diese Routinen bekommen DPTR=wValue, R4=Transferl鋘ge, R1=AutoDat,
;und d黵fen R6, R7 nicht ver鋘dern. (R7=0 f黵 letzten Teiltransfer)
;F0 ist (zun鋍hst) gel鰏cht
;R4=bmRequestType
clr F0
mov a,DPH0
mov r5,DPL0 ;retten
mov dptr,#PatchR+1
STORX
mov a,r5
STORX NEXT
mov a,r7
mov dptr,#PatchW+1
STORX ;High-Teil
mov a,r6
STORX NEXT ;Low-Teil
LDX SetupDat+2 ;wValueL
mov DPL0,a
LDX NEXT ;SetupDat+3
mov DPH0,a
LDX SetupDat+6 ;wLengthL
add a,#0FFh
mov r6,a
LDX NEXT ;wLengthH
addc a,#0 ;erh鰄en f黵 Funktion von Partial_xx
mov r7,a
cjne r4,#01000000b,a3_no ;bmRequestType
jz LEP0E ;Keine Daten!
LEP0W: WAIT_EP0_OUT
mov r4,a
call Partial_R4
MOVW AutoPtr1,Out0Buf
mov r1,#LOW(XAutoDat1)
PatchW: lcall 0
jc LEP0E
mov a,r7
jnz LEP0W ;n鋍hste Runde, sowie CY=0
ret
a3_no: cjne r4,#11000000b,err2 ;bmRequestType
jz LEP0E
LEP0R: call Partial_64
WAIT_EP0_IN
push AR4 ;retten f黵 In0BC
MOVW AutoPtr1,In0Buf
mov r1,#LOW(XAutoDat1)
PatchR: lcall 0
pop ACC
jc LEP0E
STX In0BC
mov a,r7
jnz LEP0R ;n鋍hste Runde, sowie CY=0
LEP0E: ret
err2: RETC
;=========================
;== Routinen f黵 Ende 0 == ;PE: R0=SetupDat, R4=SDAT[0], R5=SDAT[2]
;========================= R6=SDAT[4], R7=SDAT[5]
IF MyID
ClassOut equ 00100001b ;Klassenrequest (Drucker)
ClassIn equ 10100001b
ELSE
ClassOut equ 01000000b ;VendorRequest zum Test im EzMr
ClassIn equ 11000000b
ENDIF
;CountString: String Nr. R5-1 aus Descriptor-Liste ausw鋒len
;PE: DPTR=String-Beschreiber-Liste (gerade Adresse!)
; DPS=0 (sonst geht's nicht!)
; R5=String-Nummer+1
;PA: CY=1 wenn String-Liste "vorfristig" zu Ende
; DPTR=String-Beschreiber (stets gerade Adresse)
;VR: dptr,r5,a
cs_l: LOADX
jz cs_ep0stall
add a,dpl0
mov dpl0,a
jnc CountString
inc dph0
CountString:
djnz r5,cs_l
RETNC
cs_ep0stall: RETC
ep_cs:
;Rechnet Endpoint-ID in INxCS/OUTxCS-Adresse um
;PE: R6=[SetupDat+4]=Enden-Adresse
;PA: R0=Zeiger auf EPxCS (Low-Teil)
;VR: A,R0,C
mov a,r6
;Zehn m鰃liche F鋖le: 01 81 02 82 04 84 06 86 08 88
cjne a,#1,ep_cs1 ;01
mov a,#0FFh ;FF
sjmp ep_cs2
ep_cs1: rr a ; 40 01 41 02 42 03 43 04 44
anl a,#7 ; 00 01 01 02 02 03 03 04 04
ep_cs2: add a,#LOW(EP1InCS)
mov r0,a
ret
ResTog: ;Togglebit von R6=Endpoint r點ksetzen
mov a,r6
mov c,ACC.7
mov ACC.4,c
anl a,#1Fh
ResTo: STX TOGCTL ;Toggle-Bit adressieren
setb ACC.5
STX ;Togglebit zur點ksetzen
ret
ResTogAll: ;Alle Togglebits r點ksetzen, VR: R5
mov r5,#1Fh
ResTo0: mov a,r5
call ResTo ;alle au遝r EP0Out (der geht immer)
djnz r5,ResTo0
ret
GetStatus:
cjne r4,#ClassIn,gs_nid ;GET_DEVICE_ID? (Nur Interface 1)
;hier: GetDeviceId
;cjne r7,#1,err1 ;Interface, muss 1 sein
ajmp GetDeviceId
;sjmp nullin ;zwei Nullen senden, zurzeit kein String
gs_nid:
cjne r4,#80h,gs_no_dev ;GS_DEVICE
nullin: clr a ;kein WakeUp(Bit1), kein SelfPower(Bit0)
wordin: STORX In0Buf
STORX NEXT,0
STX In0BC,2
ret
gs_no_dev:
cjne r4,#81h,gs_no_if ;GS_INTERFACE
jmp nullin ;auch zwei Nullen melden
gs_no_if:
cjne r4,#82h,err1 ;GS_ENDPOINT
call ep_cs
LDX ;STALL-Bit angeln
anl a,#1
jmp wordin
ClearFeature: ;numerisch gleich: GetPortStatus
cjne r4,#ClassIn,cf_nps ;Klassenrequest
;hier: GetPortStatus
;cjne r6,#1,err1 ;nur Interface 1
acall in1
anl a,#00111000b
ajmp OneByteIn ;Info-Byte senden
cf_nps:
cjne r4,#2,err1
cjne r5,#0,err1 ;einziges Feature: STALL
call ep_cs ;Endpoint zur Control+Status-Adresse umrechnen
STX ,0 ;STALL entfernen
jmp ResTog
SoftReset:
cjne r4,#ClassOut,err1
;cjne r6,#1,err1 ;nur Interface 1
clr IOA.INI ;RESET-Impuls ausgeben
LDX GpifIdleCtl
anl a,#70h
orl a,#011b ;SEL=L, AF=H, STB=H
STX
setb IOA.INI
ret
SetFeature:
cjne r4,#2,err1 ;FT_ENDPOINT
cjne r5,#0,err1 ;einziges Feature: STALL
call ep_cs ;Endpoint zur Control+Status-Adresse umrechnen
STX ,1 ;STALL setzen
ret
err1: RETC
GetDescriptor:
cjne r4,#80h,err1 ;nur DEVICE_IN
LDX SetupDat+3 ;wValueH
cjne a,#01h,gd_no_dev ;GD_DEVICE
mov dptr,#DeviceDescriptor
gd_sto: mov a,DPH0
STX SudPtrH
mov a,DPL0
STX NEXT
ret
gd_no_dev:
cjne a,#02h,gd_no_conf ;GD_CONFIGURATION
orl c,HighSpeed
gd_cd: mov dptr,#ConfigDescFS
jnc gd_sto
mov dptr,#ConfigDescHS
clr c
jmp gd_sto
gd_no_conf:
cjne a,#03h,gd_no_str ;GD_STRING
mov dptr,#StringDesc
inc r5
call CountString
jc err1
jmp gd_sto
gd_no_str:
cjne a,#06h,gd_no_qual ;GD_QUALIFIER
mov dptr,#DeviceQualifier
jmp gd_sto
gd_no_qual:
cjne a,#07h,err1 ;GD_OTHERSPEED
orl c,/HighSpeed
jmp gd_cd
GetConfiguration:
cjne r4,#80h,err1 ;nur DEVICE_IN
mov a,Configuration ;Entweder konfiguriert oder unkonfiguriert
OneByteIn:
STORX In0Buf
STX In0BC,1
ret
SetConfiguration:
cjne r4,#0,err1 ;nur DEVICE_OUT
mov a,r5
add a,#-2
jc err1 ;nur Konfiguration 0 oder 1
mov Configuration,r5
ret
GetAltSet:
cjne r4,#81h,err1 ;nur INTERFACE IN
cjne r6,#1,as_n1
mov a,AltSetting1
jmp OneByteIn
as_n1: jnc err1 ;wenn Interface > 1
clr c
clr a
jmp OneByteIn
SetAltSet:
cjne r4,#1,err1 ;nur INTERFACE OUT
; cjne r6,#0,as_n0 ;Interface 0: h#s Parallelport
; ret
as_n0:
cjne r6,#1,ep0s2 ;Interface 1: USB-Druckerunterst黷zung
mov a,r5
add a,#-3
jc ep0s2 ;Nur Alternative 0, 1 oder 2 zulassen
mov AltSetting1,r5
; STX OutPktEnd,84h ;EP4 (doppelt gepuffert) scharfmachen
; STX
sude: ret
SUD_Tab:
ajmp GetStatus ;0 - auch: GET_DEVICE_ID
ajmp ClearFeature ;1 - auch: GET_PORT_STATUS
ajmp SoftReset ;2 (normalerweise err1)
ajmp SetFeature ;3
ep0s2: RETC ;4
RETC ;SetAddress ;5, sollte nicht vorkommen
ajmp GetDescriptor ;6
RETC ;SetDescriptor ;7
ajmp GetConfiguration;8
ajmp SetConfiguration;9
ajmp GetAltSet ;10
ajmp SetAltSet ;11
;RETC ;SyncFrame ;12
HandleSUD: ;liefert CY=1 f黵 err1
LDX SetupDat+0 ;bmRequestType -> R4
mov r4,a
LDX NEXT ;SetupDat+1: bRequest -> A
cjne a,#0A2h,hs1 ;EEPROM-Zugriff?
call EReqInit ;wIndex heranziehen
mov dptr,#ERead
MOVR r6,r7,EE_W
jmp LongEP0
hs1: cjne a,#0A3h,hs2 ;XRAM-Zugriff?
mov dptr,#MemR
MOVR r6,r7,MemW
jmp LongEP0
hs2: mov r7,a
add a,#-12 ;nur 0..11 zulassen
jc ep0s2
LDX NEXT ;SetupDat+2: wValueL -> R5
mov r5,a
LDX SetupDat+4 ;wIndexL -> R6
mov r6,a
LDX NEXT ;SetupDat+5: wIndexH ->
xch a,r7
call usr31 ;darf bei CY=1 kein Register 鋘dern!
jnc sude ;bei CY=0 ist's des Users Eigenverantwortung
JMPTBL SUD_Tab
;==============================
;== Routinen f黵 Druckerport ==
;==============================
SetECR: ;ECR-Byte setzen, FIFOs leeren
anl a,#0F8h
orl a,#5 ;FIFO leer setzen
mov ECR,a
swap a
rr a
anl a,#7
inc a
mov r3,a
clr a
setb c
se1: rlc a
djnz r3,se1 ;Bit draus machen, testet sich besser
mov ECR_Bits,a
mov c,ECR_Bits.4 ;EPP-Bit
mov a,#0FFh
subb a,#0
mov EppTimeout,a ;beim Einschalten von EPP auf Null, sonst 1
mov a,ECR_Bits
anl a,#00000101b ;Bei SPP oder SPP-FIFO auf Ausgabe schalten!
jz se3 ;kein Schalten am Richtungsbit!
clr direction
acall DirChanged ;Ausgabetreiber stets aktiv - je nach OC-Simul.
se3: mov fifor,#Fifo
mov fifow,#Fifo
ret
;===SPP-FIFO===========================
;Die Emulation der SPP-FIFO-Betriebsart
;Ein "echtes" Parallelport legt stets den FIFO-Kopf aufs Datenport...
SppXfer:
jb fifoe,exf ;wenn FIFO leer ist nichts zu tun
LDX GpifReadyStat
jb ACC.BSY,exf ;wenn besch鋐tigt dann geht's nicht
mov r0,fifor
mov OutB,@r0 ;Datenbyte anlegen, Treiber muss aktiv sein
LDX GpifIdleCtl
clr ACC.STB
STX ;Strobe aktivieren
acall IncFifoR ;Lesezeiger erh鰄en (und Zeit verbrauchen)
LDX GpifIdleCtl
setb ACC.STB
STX ;Strobe zur點knehmen
exf: ret
;===EPP===========================
;A auf IdleCtl ausgeben und max. 10 祍 auf WAIT=H warten
;PE: R0=LOW(GpifIdleCtl), A=GpifIdleCtl-Byte, R3=ASTB/DSTB-Maske
;PA: EppTimeOut.0, A=abgetastete Portpins
;VR: R0=LOW(GpifReadyStat),R1=A,R3
wait_epp:
LDX GpifIdleCtl
mov r1,a ;retten
anl a,r3 ;ASTROBE/DSTROBE (ggf. WRITE)low
STX
mov a,r3
rrc a ;Bit0 (Strobe = WRITE) extrahieren
jc sw0
push OEB ;bei Schreibzugriff: Zustand retten,...
mov OEB,#0FFh ;tempor鋜 alles Ausgabe
sw0: ;max. 10 祍 warten bis WAIT=H
mov r3,#15 ;15 Runden
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -