;Include-Datei für Videotextdekoder als TSR
;Hochoptimiert auf Geschwindigkeit und Codegröße
;Version für c't-Videotextkarte und das h#s-Derivat derselben
;API-Beschreibung:
;I2CBasis: Standard (c't): 100h, 1F0h, 200h, 220h, 300h, 3E0h
;aber: 1F0: Kollision mit Festplatte
; 200: Kollision mit Gameport
; 220: Kollision mit SoundBlaster
; 300: Kollision mit einigen Prototypen- und Netzkarten
;I2CBasis: Standard (h#s): 100h, 104h, 108h, 210h, 300h, 3e0h, 3e4h (,10ch)
;bis auf 300h keine bisher bekannten Kollisionen
;SCHNITTSTELLEN
;proc SI2C ;Sende CX Bytes zum VTD aus Puffer SI
;PE: CX=I2CAnzahl (0 = Null Bytes)
; SI=Puffer im Datensegment, DS im Datensegment
;PA: CY=1: Fehler; dann Ansprung der Critical-Error-Routine
; SI=SI+CX (wenn fehlerfrei)
;VR: SI
;proc RI2C ;Empfange CX Bytes vom VTD nach Puffer DS:SI
;PE: CX=I2CAnzahl (0 = Null Bytes)
; SI=Puffer im Datensegment, DS im Datensegment
;PA: CY=1: Fehler; dann Ansprung der Critical-Error-Routine
; SI=SI+CX (wenn fehlerfrei)
;VR: SI
;SStrI2C: ;PASCAL-String SI schicken
;SBufEI2C: ;Mit ein paar Steuerzeichen via STOS gefüllten Puffer ausgeben
;PE: DI zeigt hinter das letzte aufgefüllte Zeichen im Puffer
;PA: CX=Anzahl
;VR: CX
;SBufI2C: ;I2CAnzahl:CX; fest aus Buf, PA:CY, VR:FLAGS
;RBufI2C: ;I2CAnzahl:CX; fest aus Buf, PA:CY, VR:FLAGS
;proc I2CInit
;PE: -
;PA: AL=Statusbyte
;CY=1: I2C-Fehler (z.B. Karte nicht auf dieser Adresse)
; call StopI2C
;I2CStat:
;proc AddWaitI2C
;Warte-INs hinzufügen
;CY=1: Keine weiteren Wait-States möglich
;proc SubWaitI2C
;Warte-INs entfernen
;CY=1: Wait-States sind bereits Null
;proc ProgAcq
;Programmiert VTD auf die Suche nach
;PE: DX=Seite, Bit 15=Wildcard-Flag
; CX=Unterseite, Bit 15=Wildcard-Flag
; BH=Akquisitor-Nummer 0..3(..7)
;PA: CY=1: Fehler auf I2C-Bus
;VR: AX, ein paar Bytes von [Buf]
;proc GetPageInfo
;hole aus [SI] (Abbild der Zeile 25) die Angaben über:
;DX- Seite
;CX- Unterseite
;BX- C-Bits
;AH- HamErrors
;VR:AX,SI
;****** CCT-Hardwarezugriff-Routine (Ebene I) ******
;+++ Ebene 1a: Bitzugriff +++
INPU: in al,dx
adr0: in al,dx ;4 Waits in Form von INs
in al,dx
in al,dx
in al,dx
ret
proc StartI2C ;Start für I²C-Bus
;DX ist standardmäßig bei SDAH
;(DX-2=SCLH, DX-1=SCLL, DX=SDAH, DX+1=SDAL)
mov dx,[I2CBasis]
xchg ah,al ;am Anfang: SDA=SCL=HIGH
inc dx
inc dx
inc dx
call INPU; SDAL
call INPU; SDAL ;4µs
dec dx
dec dx
call INPU; SCLL ;sdal;scll am Schluß: SDA=SCL=LOW
inc dx
xchg al,ah
ret
endp
StopI2C: ;Ende der Übertragung
mov dx,[I2CBasis]
inc dx
inc dx
proc StopI2Ci ;Ende der Übertragung (intern DX=SDAH-Adr)
inc dx
call INPU; SDAL ;Am Anfang: SDA=X, SCL=LOW
dec dx
dec dx
dec dx
call INPU; SCLH
call INPU; SCLH ;4µs
inc dx
inc dx
call INPU; SDAH ;am Schluß: SDA=SCL=HlGH
ret
endp
;+++ Ebene 1b: Bytezugriff +++
proc SByI2C ;1 Byte senden
;PE: AL: Zu sendendes Byte
; DX=SDAH-Adresse
;PA: CY=Fehler (fehlende Empfangsquittung des SAA)
;VR: AH
push cx
mov cx,8
xchg ah,al ;Datenbyte nach AH
@@l:
rol ah,1 ;Bit7 herausshiften, ohne AH zu zerstören
jc @@1
inc dx
call INPU; SDAL
dec dx
jr @@2
@@1:
call INPU; SDAH
in al,dx ;Kontrolle, ob kein anderer stört
shr al,1 ;(Warten hier nicht erforderlich!)
cmc
jc @@e
@@2:
dec dx
dec dx
call INPU; SCLH ;2µs
call INPU; SCLH ;4µs, Empfänger braucht Zeit zum Einsampeln
inc dx
call INPU; SCLL
inc dx
loop @@l
call INPU; SDAH
dec dx
dec dx
call INPU; SCLH
inc dx
inc dx
call INPU; SDAH ;zum Einlesen
shr al,1
@@e:
dec dx
call INPU; SCLL
inc dx
xchg al,ah ;unverändert
pop cx
ret
endp
proc RByI2C
;PE: Bit0(AL)=1: Letztes Byte erwartet
; DX: SDAH-Adresse
;PA: AL:Datenbyte
; CY=1: Fehler beim Empfang (Irgendwas klemmt auf der Leitung)
; (tritt höchstens bei gesetztem Bit0(AL) auf!)
;VR: AX, DX
push cx
mov cx,8
xchg ah,al
call INPU; SDAH ;SCL ist schon Low
dec dx
jr @@l1
@@l: ;(In DIESER Schleife ist DX=SCLL=Basis+1!)
call INPU; SCLL ;In der Schleife 4µs SCL auf LOW lassen
@@l1:
dec dx
call INPU; SCLH
inc dx
inc dx
call INPU; SDAH ;Bit einlesen
shr al,1
rcl ah,1 ;Bit einschieben und (am Ende) Bit0 ausschieben
dec dx
call INPU; SCLL
loop @@l ;Nächstes Datenbit
inc dx
jc @@1 ;Wenn allerletztes Byte
inc dx
call INPU; SDAL ;Quittungsbit
dec dx
clc ;Hier gibts nie einen Fehler
jr @@2
@@1:
call INPU; SDAH ;Zeit schinden! - Kein Quittungsbit
in al,dx ;Leitung abhorchen
shr al,1 ;Störung?
cmc ;CY=1, wenn Datenbit D0=0
@@2:
dec dx
dec dx
call INPU; SCLH
call INPU; SCLH ;4µs
inc dx
call INPU; SCLL
inc dx
xchg al,ah
pop cx
ret
endp
;#################################################### (ab hier
;### Fundamentale Pufferlese- und Schreibroutinen ### hardware-
;#################################################### unabhängig)
;+++ Ebene 1c: Pufferzugriff +++
CCTW equ 22h ;Bausteinadresse zum Schreiben
CCTR equ 23h ;Bausteinadresse zum Lesen
proc SI2C ;Sende CX Bytes zum VTD aus Puffer SI
;PE: CX=I2CAnzahl (0 = Null Bytes)
; SI=Puffer im Datensegment, DS im Datensegment
;PA: CY=1: Fehler; dann Ansprung der Critical-Error-Routine
; SI=SI+CX (wenn fehlerfrei)
;VR: SI
push ax cx dx
mov al,CCTW
cld
inc cx
call StartI2C
@@l:
call SByI2C
jc @@e
lodsb
loop @@l
dec si ;!!!
@@e:
JR I2Cexi
endp
proc RI2C ;Empfange CX Bytes vom VTD nach Puffer DS:SI
;PE: CX=I2CAnzahl (0 = Null Bytes)
; SI=Puffer im Datensegment, DS im Datensegment
;PA: CY=1: Fehler; dann Ansprung der Critical-Error-Routine
; SI=SI+CX (wenn fehlerfrei)
;VR: SI
push ax cx dx
mov al,CCTR
call StartI2C
call SByI2C
jc @@e
jcxz @@e
@@l:
cmp cx,2 ;CY=1 wenn CX=1
sbb al,al ;AL=1 wenn CX=1; AL=0 sonst
call RByI2C
jc @@e ;Fehler beim Empfang
mov [si],al
inc si
loop @@l
@@e:
I2Cexi: call StopI2Ci
pop dx cx ax
jnc @@x
call [pI2Cerr] ;Error Handler!
@@x: ret
endp
;###################################################
;### Speziellere Pufferlese- und Schreibroutinen ###
;###################################################
;+++ Schreiben +++ (SStrI2C, SBufEI2C, SBufI2C, SI2C)
SStrI2C: ;PASCAL-String SI schicken
push si
mov cl,[si]
inc si
mov ch,0
jr SBI2C
SBufEI2C: ;Mit ein paar Steuerzeichen via STOS gefüllten Puffer ausgeben
;PE: DI zeigt hinter das letzte aufgefüllte Zeichen im Puffer
;PA: CX=Anzahl
;VR: CX
push si
mov cx,di
mov si,ofs Buf0
sub cx,si
jr SBI2C
SBufI2C: ;I2CAnzahl:CX; fest aus Buf, PA:CY, VR:FLAGS
push si
mov si,ofs Buf
SBI2C: call SI2C
pop si
ret
;+++ Lesen +++ (RBufI2C, RI2C)
RBufI2C: ;I2CAnzahl:CX; fest aus Buf, PA:CY, VR:FLAGS
push si
mov si,ofs Buf
call RI2C
pop si
ret
;################################
;### Initialisierungsroutinen ###
;################################
proc I2CInit
;PE: -
;PA: AL=Statusbyte
;CY=1: I2C-Fehler (z.B. Karte nicht auf dieser Adresse)
call StopI2C
I2CStat:
mov [wo Buf],100h ;R11B adressieren
mov cx,2
call SBufI2C
jc @@e
mov [wo Buf],1401h ;Mode TCS on
call SBufI2C
jc @@e
mov [by Buf],0bh
dec cx ;Anzahl=1
call SBufI2C
jc @@e
call RBufI2C
jc @@e
mov al,[by Buf] ;Status und ROM-Versions-Byte
mov [wo Buf],000h
inc cx ;Anzahl=2
call SBufI2C
@@e: ret
endp
proc AddWaitI2C
;Warte-INs hinzufügen
;CY=1: Keine weiteren Wait-States möglich
mov bx,[Waits]
cmp bx,4
cmc
jc @@e
mov [byte adr0+bx],0ech ;= IN al,dx
inc [Waits]
@@e: ret
endp
proc SubWaitI2C
;Warte-INs entfernen
;CY=1: Wait-States bereits auf Null
mov bx,[Waits]
cmp bx,1 ;Kleiner 1?
jc @@e
dec bx
mov [byte adr0+bx],0C3h ;= RET
mov [Waits],bx
@@e: ret
endp
proc I2Cstderr
bset [ctrl0],bit 7
inc [I2CErrors]
stc
ret
endp
Detected encoding: OEM (CP437) | 1
|
|