;	B U F F E R
;
; dient als Pufferspeicher zwischen einer schnellen Datenquelle und einer
; langsamen Datensenke.
; Die ueber PIO1 kommenden Daten werden in einem Ringpuffer zwischengespeichert
; und ueber PIO2 wieder ausgegeben. Die Input- wie die Output-PIO erzeugt
; einen Interrupt, der die Ein- bzw. Ausgabe des naechsten Zeichens ausloest.
;
; Verfahren nach E.Gaulke ("Z80-EMUF als Spooler", mc 10/1983, p. 98-100)
; 
; Version 0.0	27.04.84
; 
	.Z80
; 
PIO1A	EQU	0F0H		;PORT A DATA
PIO1B	EQU	0F1H		;PORT B DATA
PIO2A	EQU	0F4H		;PORT A DATA
PIO2B	EQU	0F5H		;PORT B DATA
;
ANF	EQU	1000H		;RINGBUFFER ANFANG
END	EQU	87FFH-12	;ENDE UND PLATZ FUER STACK
;
	ORG 100H
	JP INIT
;
	ORG 108H
INTVEK:	DEFW EIN	;INTERRUPT VEKTOREN
	DEFW AUS
;
	ORG 200H
INIT:	LD HL,TAB1	;PIOS INITIALISIEREN
INIA:	LD C,(HL)
	INC HL
	LD B,(HL)
	INC HL
	OTIR
	LD A,(HL)
	OR A
	JR NZ,INIA	;TABELLENENDE ERREICHT?
;
	LD SP,87FFH
	EI
	IM 2
	LD C,00001011B	;FLAG VEKTOR 
	LD HL,ANF
	LD DE,ANF
	IN A,(PIO1A)	;EINGABE INTERRUPT ERMOEGLICHEN
;
LOOP:	JR LOOP		;DUMMY HAUPTPROGRAMM
;
;	INPUT INTERRUPT SERVICE 
;
EIN:	BIT 1,C		;EIN=DISABLE?
	JR Z,EINE
	CALL EIN1	;NEIN, ZEICHEN EINLESEN
	BIT 3,C		;AUSGABE FERTIG?
	CALL NZ,AUS1	;JA, ZEICHEN AUSGEBEN
	RES 3,C		;FERTIG=NEIN
	EI
	RETI
;
EINE:	SET 4,C		;ZEICHEN DA=JA
	EI
	RETI
;
;	NAECHSTES INPUT-ZEICHEN
;
EIN1:	CALL ABF1	;POINTER UND FLAGS UMSETZEN
	CALL EIN2	;ZEICHEN AUS PIO1 LESEN
	RET
;
ABF1:	SET 2,C		;AUS=ENABLE
	SCF
	BIT 0,C
	JR Z,BFAL	;FALL B?
	PUSH BC		;NEIN, FALL A
	PUSH HL
	LD BC,END
	SBC HL,BC	;INPUT POINTER AM ENDE?
	POP HL
	POP BC
	RET NZ		;NEIN, NOCH PLATZ
	RES 0,C		;JA, FALL=B
	OR A
	LD HL,ANF
	SBC HL,DE
	JR NZ,BFA1	;OUTPUT POINTER AM ANFANG?
	RES 1,C		;JA, EIN=DISABLE
BFA1:	LD HL,END+1	;ZEICHEN HINTER ENDE ABLEGEN
	CALL EIN2
	LD HL,ANF	;INPUT POINTER AUF ANFANG
	POP AF		;DIREKT ZURUECK ZUR SERVICE ROUTINE
	RET
;
BFAL:	EX DE,HL	;FALL B
	PUSH HL
	SBC HL,DE	;INPUT POINTER EINS HINTER OUTPUT POINTER?
	POP HL
	EX DE,HL
	RET NZ		;NEIN, NOCH PLATZ
	RES 1,C		;JA, EIN=DISABLE
	RET
;
;	OUTPUT INTERRUPT SERVICE
;
AUS:	BIT 2,C		;AUS=DISABLE?
	JR Z,AUSE
	CALL AUS1	;NEIN, ZEICHEN AUSGEBEN
	BIT 4,C		;ZEICHEN DA?
	CALL NZ,EIN1	;JA, EINLESEN
	RES 4,C		;ZEICHEN DA=NEIN
	EI
	RETI
;
AUSE:	SET 3,C		;FERTIG=JA
	EI 
	RETI
;
;	NAECHSTES OUTPUT-ZEICHEN
;
AUS1:	CALL ABF2	;FLAGS UND POINTER UMSETZEN
	CALL AUS2	;ZEICHEN IN PIO2 SCHREIBEN
	RET
;
ABF2:	SET 1,C		;EIN=ENABLE
	SCF
	BIT 0,C
	JR Z,BFBL	;FALL=B?
	PUSH HL		;NEIN, FALL A
	SBC HL,DE	;OUTPUT POINTER EINS HINTER INPUT POINTER?
	POP HL
	RET NZ		;NEIN, NOCH WEITER ZURUECK
	RES 2,C		;JA, AUS=DISABLE
	RET
;
BFBL:	PUSH DE		;FALL B
	EXX
	POP HL
	LD BC,END
	SBC HL,BC	;OUTPUT POINTER AM ENDE?
	EXX
	RET NZ		;NEIN, NOCH PLATZ
	SET 0,C		;JA, FALL=A
	PUSH HL
	OR A
	LD DE,ANF
	SBC HL,DE
	JR NZ,BFB1	;INPUT POINTER AM ANFANG?
	RES 2,C		;JA, AUS=DISABLE
BFB1:	LD DE,END+1	;ZEICHEN HINTER ENDE AUSGEBEN
	CALL AUS2
	LD DE,ANF	;OUTPUT POINTER AUF ANFANG
	POP HL
	POP AF		;DIREKT ZURUECK ZUR SERVICE ROUTINE
	RET
;
;	AUS PIO1 LESEN
;
EIN2:	IN A,(PIO1A)
	LD (HL),A
	INC HL
	RET
;
;	AUS PIO2 SCHREIBEN
;
AUS2:	LD A,(DE)
	OUT (PIO2A),A
	INC DE
	RET
;
;	INITIALISIERUNGSTABELLE DER PIOS
;
TAB1:	DEFB	PIO1A+2		;PIO1 PORT A CONTROL
;	...
;
TAB2:	DEFB	PIO2A+2		;PIO2 PORT A CONTROL
;	...
;
	DEFB	0		;TABELLENENDE
;
	END
