; File Name   :	CLOCK.CPM

		cpu	z80

hi              function x,(x>>8)&255
lo              function x,x&255

		org 	100h

		jp	clock
clock:
		ld	hl, (oldisr)
		ld	a, h
		or	l
		jr	z, clockon


clokoff:	di
		ld	de, (oldisr)
		ld	a, i
		ld	h, a
		ld	l, 6
		ld	(hl), e
		inc	hl
		ld	(hl), d
		ld	hl, 0
		ld	(oldisr), hl
		ei
		ld	de, aClockoff ; "Uhr-Anzeige gestoppt!\r\nMit erneutem Auf"...
		ld	c, 9
		jp	5


clockon:	ld	de, aClockon ; "Residente Uhr fuer CP/M-Z9001\r\nvon F.Sc"...
		ld	c, 9
		call	5
		di
		; Code in RAM kopieren (hinter BIOS)
		ld	hl, loc_257
		ld	de, ROMCLK
		ld	bc, ROMEND-ROMCLK
		ldir
		; Interruptroutine der Uhr verbiegen
		ld	a, i
		ld	h, a
		ld	l, 6
		ld	e, (hl)
		inc	hl
		ld	d, (hl)
		ld	(oldisr), de
		ld	a, hi(ROMCLK)
		ld	(hl), a
		dec	hl
		ld	a, lo(ROMCLK)
		ld	(hl), a
		ei
		ret


aClockon:	db	"Residente Uhr fuer CP/M-Z9001\r\n"
		db	"von F.Schwarzenberg\r\n"
		db	"Erneuter Aufruf fuehrt zum Abschalten\r\n"
		db	"der Uhr-Anzeige.\r\n"
		db	"Mit CCP-Kommando "
		db  	16h
		db	"\iCLK hh:mm:ss\i"
		db  	16h
		db	" kann\r\n"
		db	"Uhrzeit gestellt werden!\r\n$"
		
aClockoff:	db	"Uhr-Anzeige gestoppt!\r\n"
		db	"Mit erneutem Aufruf kann Uhr-Anzeige\r\n"
		db	"wieder gestartet werden!\r\n$"

; ---------------------------------------------------------------------------

loc_257:	equ	$

		phase	0E720h

ROMCLK:		push	hl		; HL sichern, wird am Ende restauriert
		ld	hl, romclk1
		push	hl
		ld	hl, (oldisr)	
		jp	(hl)		; erst orig. Routine (FCC2H) aufrufen, dann romclk1
		
screenadr:	equ	0EC23h

; Ausgabe der aktuellen Uhrzeit, vgl. mit PRITI (F4A8H) des Z9001-OS
romclk1:	di
		push	af
		push	bc
		push	de
		ld	hl, screenadr-400h	; Adr im Farbspeicher
		ld	d, h
		ld	e, l
		ld	(hl), 4		; Hintergrundfarbe blau
		inc	de
		ld	bc, 4
		ldir			; 4 Byte mit Hintergrundfarbe blau füllen
		
		ld	c, 2		; Anzahl der Durchläufe insg. 2 für HOUR und MIN
		ld	de, 1Dh		; ab hier im OS-Systemspeicher HOUR, MIN, SEC
		ld	hl, screenadr	; Adr im Zeichenspeicher

romclk2:	ld	a, (de)
		or	a
		jr	z, romclk4	; wenn 0

		ld	b, a		; sonst Umwandlung in BCD-Zahl durch Hochzählen
		xor	a		; zu Beginn A = 0
romclk3:	add	a, 1		; 1 addieren
		daa			; und nach BCD konvertieren
		djnz	romclk3		; sooft wie nötig

romclk4:	ld	(hl), a		; in Bildwiederholspeicher eintragen
		ld	a, 33h		; in druckbare Zeichen umwandeln:
		rrd			; BCD-Rotation mit Reg. HL
					; A(untere Tetrade) -> HL(obere Tetrade) -> HL(untere Tetrade) -> A(untere Tetrade)
					; z.B. vorher (HL)=12, A=33, nachher (HL)=31 == '1', A=32 == '2'
		inc	hl		; nächste Adr. Bildwiederholspeicher
		ld	(hl), a		; zweite Ziffer eintragen
		inc	hl		; nächste Adr. Bildwiederholspeicher
		inc	de		; nächste Zahl
		dec	c		; nächsten Durchlauf (MIN)
		jr	z, romclk5	; wenn fertig
		
		; zw. HOUR und MIN Blinkzeichen eintragen
		ld	a, (blnkchr)	; Blinkzeichen wechseln
		xor	14h		; 3AH (':') xor 14h = 2Eh ('.')
		ld	(blnkchr), a	
		ld	(hl), a
		inc	hl
		jr	romclk2

romclk5:	pop	de
		pop	bc
		pop	af
		pop	hl		; zugehöriges push hl steht bei ROMCLK
		ei
		ret			; orig. Routine hat schon RETI ausgeführt

oldisr:		dw 0			; Merkzelle Adr. orig. Interruptroutine der Uhr
blnkchr:	db ':'			; (3Ah)


ROMEND:		equ	$

		dephase

		end
