Source file: /~heha/hs/kcemu/[Download]kcemu_052.exe/SRC/KCCTC.ASM

;**********************************************************
;*
;*  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
Wrong umlauts? - Assume file is ANSI (CP1252) encoded