;**********************************************************
;*
;* CTC Emulator für KC Emulator (U857)
;*
;*****
;
; es: Adreßbereich KC
; ds: Windows automatisches Datensegment [HInstance]
; si: Z80-Instruktionszeiger ("program counter" PC)
; ch: Taktzähler
; di: zeigt auf regs.hl oder regs.ix oder regs.iy
; dx: enthält HL/(M) oder IX/(IX+d) oder IY/(IY+d)
;
IDEAL
%TITLE "KCEMU U857 (CTC) emulator library"
model small, pascal
P286
warn pro ;Protected-Mode-Fehler anmeckern
extrn SetTimer: Proc
extrn CancelTimer: Proc;
extrn PortsInstL: Word: 256; {array[0..255] of Word}
extrn cticks: DWord;
extrn RaiseIrq: Proc
public CtcOut
;Ausgabe-Aufruf mit AX=Portadresse, BL=Datenbyte, DI=LOW(Portadresse)*2
public CtcIn
;Eingabe-Aufruf mit AX=Portadresse, DI=LOW(Portadresse)*2, RET:AL=Datenbyte
public Event_CTC
;type TCtc0=record {Ein CTC-Kanal besteht aus:}
; ks,zk,rz,iv: Byte;
; getp,putp: TNearProc;
; from: LongInt;
; end; {Kanalsteuerwort, Zeitkonstante, Rückwärtszähler und Interruptvektor}
; TCtc=array[0..3] of TCtc0
struc TIntInfo
iv db ?
ii db ?
pr dw ?
ends
II_Request =01h
II_InService =02h
struc TCtc0
ii TIntInfo <>; {alles zum Interrupt}
ks db ?; {Kanalsteuerwort}
zk db ?; {Zeitkonstante}
rz db ?; {Rückwärtszähler}
ei db ?; {ExtraInfo}
getp dw ?; {Prozedurzeiger: Flankenzeit holen}
putp dw ?; {Prozedurzeiger: Ausgabe Nadelimpuls oder Frequenz}
from dd ?; {Zählerstartpunkt}
ends
;typedef TCtc 4 dup (TCtc0)
CTC equ <(TCtc0 di)>
TII equ <(TIntInfo di)>
CODESEG
proc TimerIrq
;PE: DI: Zeiger auf TCtc0
call RaiseIRQ
;NORET
endp
proc MakeTick
;Wenn CTC bereit, neue Zeitmessung auslösen
;PE: DI=Zeiger auf CTC
;VR: AX,BX,DX
mov ax,[word LOW cticks]
mov [word LOW CTC.from],ax
mov ax,[word HIGH cticks]
mov [word HIGH CTC.from],ax
mov bh,[CTC.ks]
test bh,40h ;Betriebsart Zähler?
jnz @@zaehler
mov ax,16
test bh,20h ;Großer Vorteiler?
jz @@TeilerOK
mov ax,256
jmp @@TeilerOK
@@zaehler:
call [CTC.getp] ;Teiler holen
@@TeilerOK:
mov bh,0
cmp bl,1 ;CY=1 wenn BL=0
adc bh,bh ;aus ZK=0 mache ZK=256
mul bx ;DX:AX fertig
call [CTC.putp] ;Tonausgabe (o.ä.) setzen
;Wenn EI und Kanal vorhin rückgesetzt, dann Uhr starten:
mov bl,[CTC.ks]
and bl,82h
cmp bl,80h ;EI und kein RESET
jne @@e
pusha
push di ;ID
push dx ax ;TimeExp
push offset TimerIrq
push di ;User=ID
call SetTimer
popa
@@e: ret
endp
proc CtcOut
mov di,[PortsInstL+di] ;Instanz-Zeiger (NEAR) holen
or di,di
jz @@fail
test [CTC.ks],4 ;Bit 2 = Zeitkonstante folgt?
jnz @@ZK
test bl,1 ;Bit 0 = Kanalsteuerwort?
jnz SetKS
;Faule Annahme: CS0 ist mit A0 und CS1 ist mit A1 verbunden,
;sowie die TCtc0-Strukturen liegen im Array hintereinander
test al,3 ;Nur Kanal0 darf IV erhalten!
jnz @@nosetiv
and bl,not 7 ;nun IV, untere Bits löschen
mov cl,4
@@l_setiv:
mov [CTC.ii.iv],bl
add bl,2
add di,SIZE TCtc0
dec cl
jnz @@l_setiv
@@nosetiv:
ret
SetKS:
mov al,[CTC.ks]
mov [CTC.ks],bl
test bl,2
jz @@noreset
@@IntOff:
push ax
xor ax,ax
cwd
call [CTC.putp] ;Ausgabe nullsetzen
push si di
push di
call CancelTimer ;Keine Aktivität mehr!
pop di si
pop ax
ret
@@noreset:
xor al,bl
test al,80h ;Änderung des Interrupt-Status?
jz @@noEIchange
test bl,80h
jz @@IntOff
test bl,4 ;Folgt Zeitkonstante?
jnz @@noEIchange ;ja, Timer auf später verschieben
push ax
call MakeTick ;ISR aktivieren
pop ax
@@noEIchange:
ret
@@ZK:
push ax
and [CTC.ks],not 6 ;wieder rücksetzen (auch RESET)
mov [CTC.zk],bl ;Zeitkonstante laden
call MakeTick
pop ax
ret
@@fail:
INT 3
ret
endp
proc CtcIn
mov di,[PortsInstL+di] ;Instanz-Zeiger (NEAR) holen
mov al,[CTC.rz]
ret
endp
proc DefGetP
xor ax,ax ;kein Teiler
DefPutP:
ret
endp
proc Event_CTC
;PE: AH=Message, DI=Instanz-Datenzeiger (außer bei AH=1)
;PA: AL oder AX je nach Message
;Dieser Callback wird 1x pro Einheit automatisch aufgerufen (außer AH=1).
;VR: Das Register DI darf keinesfalls verändert werden.
; Die Register BX und (bes.) SI sollten nicht verändert werden.
dec ah
jz @@GetDataSize ;AH=1
dec ah
jz @@InitData ;AH=2
sub ah,5 ;IOEV_Reset
jne @@e
;KCEV_Reset: wParam zeigt auf Instance-Daten
;Aktion: Rücksetzen des Kanalsteuerworts
mov [TII.ii],0 ;kein Request oder InService
mov bl,2 ;Reset
call SetKS
jmp @@e
@@GetDataSize:
mov ax,4*256+(SIZE TCtc0)
jmp @@e
@@InitData:
xchg ch,cl
mov [TII.pr],cx ;Priorität setzen
mov [CTC.getp],offset DefGetP
mov [CTC.putp],offset DefPutP
jmp @@e
@@e: clc
ret
endp
END
Detected encoding: OEM (CP437) | 1
|
|