
*
* Routinen zur Steuerung des GAL-Brenners
*
* assemblieren: as -n -c -d port.asm
*





GAL16V8		EQU	1		; GAL-Typ
GAL20V8		EQU	2

IC1		EQU	3		; IC-Nummer
IC3		EQU	0
IC4		EQU	1
IC5		EQU	2
IC6		EQU	0
IC7		EQU	1

ON		EQU	1		; für LED-Steuerung
OFF		EQU	0

PROG		EQU	1		; Edit-Mode für GAL
VERIFY		EQU	0



ciaapb		EQU	$BFE101
ciabpa		EQU	$BFD000
ciaapbd		EQU	$BFE301




	public	_InitGALer		; GALer initialisieren
	public	_WriteByte		; Byte in Schiebereg. schreiben
	public	_ReadByte		; Byte aus Schiebereg. lesen
	public	_SetGAL			; GAL-Type festlegen
	public	_VeditOn		; Edit-Spannung aufbauen
	public	_VeditOff		; Edit-Spannung abschalten
	public	_LED			; LED ansteuern
	public	_EnableVcc		; Vcc anlegen
	public	_DisableVcc		; Vcc abschalten
	public	_EnableVEdit		; Edit-Spannung anlegen
	public	_DisableVEdit		; Edit-Spannung abschalten
	public	_EnableOutput		; Ausgangs-Treiber aktivieren
	public	_DisableOutput		; Ausgangs-Treiber deaktiviern
	public	_SetRow			; Adresse an RAG0-RAG5 anlegen
	public	_SDIn			; Lege ein Bit an SDIn-Eingang
	public	_SDOut			; Bit vom SDOut-Ausgang holen
	public	_Clock			; Clock-Impuls an SCLK-Eingang
	public	_STRImpuls		; STR-Impuls erzeugen
	public	_EditMode		; setzt Bits für Edit-Mode


	XDEF	_GALType
	XDEF	_outIC1
	XDEF	_outIC3
	XDEF	_outIC4
	XDEF	_outIC5


	XREF	_LVODelay

	XREF	_DOSBase
	XREF	_WaitForTimer


	cseg


* GALer initialisieren: Datenleitung vom Par.-Port auf Ausgang, alle
* Ausgänge von IC1 auf LOW (kein OutputEnable für IC3,4,5 aber Register-
* Inhalt von IC3,4,5 auf LOW stellen)
* Parameter: keine
_InitGALer:
	move.b	#$ff,ciaapbd		; Datenleitungen auf Ausgang schalten
	or.b	#%00001000,ciaapb	; PD3=H: Adressdecoder deaktivieren!
	and.b	#%00001000,ciaapb	; alle anderen Datenleitungen auf LOW
			; ACHTUNG!!!: PD3 darf nur auf LOW-Pegel gehen
			; (Adressdecoder aktiviert werden), wenn durch PD0 und
			; PD1 das IC das angesprochen werden soll, bereits
			; selektiert ist. Ansonsten bekommt ein IC einen Takt-
			; impuls und beim nächsten Strobe liegen dann die
			; falschen Daten an.
	move.w	#IC1,-(sp)
	clr.w	-(sp)
	bsr	_WriteByte		; Ausgänge von IC1 auf LOW	
	addq.l	#4,sp			; Stack korrigieren
	move.w	#IC3,-(sp)
	clr.w	-(sp)
	bsr	_WriteByte		; Ausgänge von IC3 auf LOW	
	addq.l	#4,sp			; Stack korrigieren
	move.w	#IC4,-(sp)
	clr.w	-(sp)
	bsr	_WriteByte		; Ausgänge von IC4 auf LOW	
	addq.l	#4,sp			; Stack korrigieren
	move.w	#IC5,-(sp)
	clr.w	-(sp)
	bsr	_WriteByte		; Ausgänge von IC5 auf LOW	
	addq.l	#4,sp			; Stack korrigieren
	rts



* SetGAL:
* Setzte GAL-Type fest (GAL16V8, GAL20V8)
* Aufruf: SetGAL(type);
*
_SetGAL:
	move.w	4(sp),_GALType
	rts



* VeditOn:
* schaltet den Sperrwandler an (IC9); siehe auch VeditOff
* Auruf: VeditOn();
_VeditOn:
	move.w	#IC1,-(sp)
	or.w	#%00001,_outIC1		; Q1 von IC1 auf HIGH => VeditOn
	move.w	_outIC1,-(sp)
	bsr	_WriteByte		; IC1 setzen
	addq.l	#4,sp			; Stack korrigieren
	rts

* VeditOff:
* schaltet den Sperrwandler aus (IC9); siehe auch VeditOn
* Auruf: VeditOff();
_VeditOff:
	move.w	#IC1,-(sp)
	and.w	#%11111110,_outIC1	; Q1 von IC1 auf LOW => VeditOff
	move.w	_outIC1,-(sp)
	bsr	_WriteByte		; IC1 setzen
	addq.l	#4,sp			; Stack korrigieren
	rts


* EnableVEdit:
* schaltet die Edit-Spannung (+16.5V) auf Pin 2 oder Pin 4 vom Textool
* (abhänging vom eingestellten GAL-Typ)
* Aufruf: EnableVEdit();
_EnableVEdit:
	move.w	#IC1,-(sp)		; IC1 einstellen
	cmp.w	#GAL16V8,_GALType	; 16V8 eingestellt?
	bne.s	1$			; nein, dann wird 20V8 angenommen!
	moveq	#%00000100,d0		; Q3 von IC1 auf HIGH
	bra.s	2$
1$	moveq	#%00000010,d0		; Q2 von IC1 auf HIGH
2$	or.w	d0,_outIC1
	move.w	_outIC1,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	rts

* DisableVEdit:
* schaltet die Edit-Spannung (+16.5V) an Pin 2 oder Pin 4 aus
* (abhänging vom eingestellten GAL-Typ)
* Aufruf: DisableVEdit();
_DisableVEdit:
	move.w	#IC1,-(sp)		; IC1 einstellen
	cmp.w	#GAL16V8,_GALType	; 16V8 eingestellt?
	bne.s	1$			; nein, dann wird 20V8 angenommen!
	move.w	#%11111011,d0		; Q3 von IC1 auf LOW
	bra.s	2$
1$	move.w	#%11111101,d0		; Q2 von IC1 auf low
2$	and.w	d0,_outIC1
	move.w	_outIC1,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	rts




* LED:
* schaltet die LED aus bzw. an
* Aufruf: LED(ON/OFF);
_LED:
	cmp.w	#ON,4(sp)
	bne.s	2$
	or.w	#%01000000,_outIC1
	bra.s	1$
2$	and.w	#%10111111,_outIC1
1$	move.w	#IC1,-(sp)
	move.w	_outIC1,-(sp)
	bsr	_WriteByte		; IC1 setzen
	addq.l	#4,sp			; Stack korrigieren
	rts



* EnableVcc:
* schaltet die Spannungsversorgung ein; siehe auch DisableVcc
* bei GAL16V8: Pin22 vom Textool-Sockel
* bei GAL20V8: Pin24 vom Textool-Sockel
* Aufruf: EnableVcc();
_EnableVcc:
	move.w	#IC1,-(sp)		; IC1 selektieren
	cmp.w	#GAL16V8,_GALType	; 16V8 eingestellt?
	bne.s	1$			; nein, dann wird 20V8 angenommen!!!
	moveq	#%00011000,d0		; Q4,5 von IC1 auf HIGH=>+5V an Pin22
	bra.s	2$
1$	moveq	#%00010000,d0		; Q5 auf HIGH => +5V an Pin 24	
2$	or.w	d0,_outIC1
	move.w	_outIC1,-(sp)
	bsr	_WriteByte		; IC1 setzen
	addq.l	#4,sp			; Stack korrigieren
	rts

* DisableVcc:
* schaltet die Spannungsversorgung aus; siehe auch EnableVcc
* bei GAL16V8: Pin22 vom Textool-Sockel
* bei GAL20V8: Pin24 vom Textool-Sockel
* Aufruf: DisableVcc();
_DisableVcc:
	move.w	#IC1,-(sp)		; IC1 selektieren
	cmp.w	#GAL16V8,_GALType	; 16V8 eingestellt?
	bne.s	1$			; nein, dann wird 20V8 angenommen!!!
	move.w	#%11100111,d0		; Q4,5 von IC1 auf LOW
	bra.s	2$
1$	move.w	#%11101111,d0		; Q5 auf HIGH => +5V an Pin 24	
2$	and.w	d0,_outIC1
	move.w	_outIC1,-(sp)
	bsr	_WriteByte		; IC1 setzen
	addq.l	#4,sp			; Stack korrigieren
	rts



* EnableOutput:
* OutputEnable-Eingang (OE) von IC3, IC4, IC5 auf HIGH
* Aufruf: EnableOutput();
_EnableOutput:
	move.w	#IC1,-(sp)
	or.w	#%00100000,_outIC1
	move.w	_outIC1,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	rts

* DisableOutput:
* OutputEnable-Eingang (OE) von IC3, IC4, IC5 auf LOW
* Aufruf: DisableOutput();
_DisableOutput:
	move.w	#IC1,-(sp)
	and.w	#%11011111,_outIC1
	move.w	_outIC1,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	rts



* ReadByte:
* lese ein Byte aus dem IC "ICx", wobei ICx=IC6 (nur ein Bit) oder IC7 ist
* Aufruf: byte=ReadByte(IC);
* PD3 ist bereits HIGH (muß es auch!, siehe _InitGAL und Beschreibung zu PD3)
_ReadByte:
	clr.w	d0
	cmp.w	#IC6,4(sp)		; IC6 angesprochen?
	bne.s	IC7$			; nein, dann IC7$
	or.b	#%00000001,ciaapb	; PD0 auf HIGH=>HIGH am Clk vom IC7
					; PD0 auf HIGH setzen=>IC6a selektiert
	move.b	ciabpa,d0
	not.b	d0			; invertieren
	and.b	#%00000001,d0		; BUSY-Bit ausmaskieren
	bra.s	ready$			; Pin22 (über IC6) ist ausgelesen
IC7$

	and.b	#%11111110,ciaapb	; PD3 ist HIGH=>Lesen möglich
	nop
	or.b	#%00000100,ciaapb	; PD2 (Strobe) auf HIGH-> Daten werden
	and.b	#%11111011,ciaapb	; vom Eingangsreg. in das Schiebereg.
					; übernommen. Dann PD2 wieder auf LOW.
					; PD3 ist auf HIGH=>Lesen ist möglich

	moveq	#7,d2			; Schleifenzähler
l$	rol.b	#1,d0
	move.b	ciabpa,d1		; BUSY-Bit holen
	and.b	#%00000001,d1		; BUSY-Bit ausmaskieren
	or.b	d1,d0			; BUSY-Bit in D0 eintragen
	and.b	#%11111110,ciaapb	; PD0 auf LOW=>LOW am Clk-Eingang (IC7)
	or.b	#%00000001,ciaapb	; PD0 auf HIGH=>HIGH am Clk-Eingang
					; ==> nächstes Bit steht am Ausgang
	nop
	nop
	and.b	#%11111110,ciaapb	; PD0 auf LOW=>IC6b ist selektiert (=>lesen möglich)
	dbf	d2,l$			; 8 Bits auslesen
	not.b	d0			; invertieren
ready$	rts				; D0=Rückgabewert (gelesenes Byte)



* WriteByte:
* schreibt das Byte "byte" in das IC "IC", wobei IC=IC1, IC3, IC4 oder IC5
* sein kann
* zuerst wird das MSB übertragen!!!
* Aufruf: WriteByte(byte,IC)
_WriteByte:
	movem.l	d0-d3,savereg		; Register retten
	move.w	4(sp),d0		; Datenbyte nach D0
	move.w	6(sp),d1		; IC nach D1
				; geschriebenes Byte mitprotokolieren
	cmp.w	#IC1,d1
	bne.s	1$
	move.w	d0,_outIC1
	bra.s	cont$
1$	cmp.w	#IC3,d1
	bne.s	2$
	move.w	d0,_outIC3
	bra.s	cont$
2$	cmp.w	#IC4,d1
	bne.s	3$
	move.w	d0,_outIC4
	bra.s	cont$
3$	move.w	d0,_outIC5
cont$

	and.b	#%11111100,ciaapb	; PD0 und PD1 setzen (IC aus-
	or.b	d1,ciaapb		; wählen)
	and.b	#%11110111,ciaapb	; Adressdecoder aktivieren

	moveq	#7,d3			; Schleifenzähler
	ror.b	#3,d0			; MSB nach D4 (Datenleitung)
loop$	move.b	d0,d2			; Datenbyte sichern
	and.b	#%00010000,d2		; Datenbit ausmaskieren
	or.b	d2,ciaapb		; Datenbit (PD4) vom Par.-Port setzen

	or.b	#%00001000,ciaapb	; Clock-Impuls durch PD3 geben
	and.b	#%11110111,ciaapb	; LOW-HIGH Übergang

	and.b	#%11101111,ciaapb	; Datenbit (PD4) auf LOW

	rol.b	#1,d0			; nächstniedrigeres Bit senden
	dbf	d3,loop$

	or.b	#%00001000,ciaapb	; Adressdecoder wieder deaktivieren!!!
					; (sehr WICHTIG, siehe _InitGAL:)
	or.b	#%00000100,ciaapb	; PD2 (Strobe) auf HIGH-> Daten werden
	and.b	#%11111011,ciaapb	; vom Schieberegister in das Datenreg.
					; übernommen. Dann PD2 wieder auf LOW.
	movem.l	savereg,d0-d3
	rts


* SetRow:
* Adresse an RAG0-RAG5 anlegen
* Aufruf: SetRow(row);
* row:	  zu adressierende Zeile (0-63)
_SetRow:

				    ; RAG5 setzen (Pin bei 16 und 20V8 gleich)
	move.w	4(sp),d0		; row holen
	and.w	#$fe,_outIC5		; Bit0(=RAG5) löschen
	asr.b	#5,d0			; Bit0 von D0=RAG5
	or.w	d0,_outIC5		; RAG5=Bit von D0=> RAG5 gesetzt

	cmp.w	#GAL16V8,_GALType	; GAL16V8?
	bne.s	GAL20V8$		; nein, dann GAL20V8 annehmen
GAL16V8$			    ; RAG0 setzen
	move.w	4(sp),d0		; row holen
	and.w	#$ef,_outIC3		; Bit4(=RAG0) löschen
	and.w	#1,d0			; Bit0 von "row" ausmaskieren
	asl.b	#4,d0
	or.w	d0,_outIC3		; Bit4(=RAG0) setzen
				    ; RAG1-RAG4 setzen
	move.w	4(sp),d0		; row holen
	and.w	#$0f,_outIC4		; Bit4-7(=RAG1-RAG4) löschen
	and.w	#%00011110,d0		; Bit1-4 von "row" ausmaskieren
	asl.w	#3,d0			; an Bit4-7 schieben
	or.w	d0,_outIC4		; RAG1-RAG4 setzen
	bra.s	write$
GAL20V8$			    ; RAG0 für GAL20V8 setzen
 	move.w	4(sp),d0		; row holen
	and.w	#%11011111,_outIC3	; Bit5(=RAG0) löschen
	and.w	#1,d0			; Bit0 von "row" ausmaskieren
	asl.b	#5,d0
	or.w	d0,_outIC3		; Bit5(=RAG0) setzen
				    ; RAG4 setzen
	move.w	4(sp),d0		; row holen
	and.w	#%01111111,_outIC4	; Bit7(=RAG4) löschen
	and.w	#%00010000,d0		; Bit4 von "row" ausmaskieren
	asl.w	#3,d0
	or.w	d0,_outIC4		; Bit7(=RAG4) setzen
				    ; RAG1-RAG3 setzen
	move.w	4(sp),d0		; row holen
	and.w	#%11100011,_outIC4	; Bit2-4(=RAG1-RAG3) löschen
	and.w	#%00001110,d0		; Bit1-3 aus "row" ausmaskieren
	asl.w	#1,d0
	or.w	d0,_outIC4		; RAG1-RAG3 setzen

write$				    ; errechnete Werte in ICs schreiben
	move.w	#IC3,-(sp)
	move.w	_outIC3,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	move.w	#IC4,-(sp)
	move.w	_outIC4,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	move.w	#IC5,-(sp)
	move.w	_outIC5,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	rts



* SDIn:
* lege ein Bit an den SDIn-Eingang (Pin 11 vom Textool-Sockel)
* Aufruf: SDIn(bit);    bit: 0=LOW; 1=HIGH
_SDIn:
	move.w	4(sp),d0		; Bit holen
	asl.b	#2,d0			; an die richtige Stelle schieben
	and.w	#%11111011,_outIC5	; SDIn-Bit löschen
	or.w	d0,_outIC5		; Bit auf LOW oder HIGH setzen
	move.w	#IC5,-(sp)
	move.w	_outIC5,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	rts


* SDOut:
* ein Bit aus dem SDOut-Ausgang lesen
* Pin 14 (GAL16V8), Pin 15 (GAL20V8) am Textool-Sockel
* Aufruf: bit=SDOut();
* bit: 0: SDOut-Pin ist LOW; 1: SDOut-Pin ist HIGH
_SDOut:
	move.w	#IC7,-(sp)		; ein Byte aus IC7 holen
	bsr	_ReadByte		; Bit0=Pin14, Bit1=Pin15
	addq.l	#2,sp
	cmp.w	#GAL16V8,_GALType	; GAL16V8 eingestellt?
	bne.s	1$			; nein, dann GAL20V8
	and.w	#1,d0			; Bit0 ausmaskieren
	bra.s	2$			; D0=Bit
				    ; GAL20V8
1$	asr.w	#1,d0			; SDOut-Bit an Bit-Pos. 0
	and.w	#1,d0
2$	rts




* Clock:
* erzeuge Clock-Impuls (Low-High-Low-Übergang) am SCLK-Eingang (Pin 10
* vom Textool-Sockel
* Aufruf: Clock();
_Clock:

	or.w	#%00000010,_outIC5	; SCLK-Bit auf HIGH
	move.w	#IC5,-(sp)
	move.w	_outIC5,-(sp)
	bsr	_WriteByte
	addq.w	#4,sp
	nop				; etwas warten
	nop
	nop
	nop
	and.w	#%11111101,_outIC5	; SCLK-Bit auf LOW
	move.w	#IC5,-(sp)
	move.w	_outIC5,-(sp)
	bsr	_WriteByte
	addq.w	#4,sp
	rts



* STRImpuls:
* setzt /STR-Eingang (Pin 13 am Textool-Socker) für 10 ms auf LOW
* Aufruf: STRImpuls();
_STRImpuls:
	movem.l	d0-d7/a0-a6,savereg	; Register retten

	and.w	#%11110111,_outIC5	; STR-Pin auf LOW
	move.w	#IC5,-(sp)
	move.w	_outIC5,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp

	move.l	#10000,-(sp)		; 10000us=10ms
	clr.l	-(sp)			; 0 Sekunden warten
	jsr	_WaitForTimer		; 10 ms Low-Impuls
	addq.l	#8,sp			; Stack korrigieren

	or.w	#%00001000,_outIC5	; STR-Pin wieder auf HIGH
	move.w	#IC5,-(sp)
	move.w	_outIC5,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp

	movem.l	savereg,d0-d7/a0-a6	; Registerinthalte zurückholen
	rts



* Edit-Mode:
* schaltet das GAL in den Edit-Mode
* Aufruf: EditMode(mode);
* mode:   PROG	 -  GAL programmieren
*	  VERIFY -  GAL lesen
_EditMode:
	movem.l	d0-d7/a0-a6,savereg	; Register sichern
	move.w	4(sp),d0		; "mode" holen
	cmp.w	#GAL16V8,_GALType	; GAL16V8?
	bne.s	1$			; nein, dann 1$
	move.w	#IC3,-(sp)		; IC3 setzen
	move.w	#%00000000,d1
	asl.b	#5,d0			; Mode-Bit zu Bit 5 schieben
	or.w	d0,d1			; P,/V-Bit setzen
	move.w	d1,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	move.w	#IC4,-(sp)
	move.w	#%00000000,-(sp)	; IC4 initialisieren
	bsr	_WriteByte
	addq.l	#4,sp
	move.w	#IC5,-(sp)
	move.w	#%00011000,-(sp)	; IC5 initialisieren
	bsr	_WriteByte
	addq.l	#4,sp
	bra.s	2$
1$				    ; GAL20V8
	move.w	#IC3,-(sp)		; IC3 setzen
	move.w	#%00000000,d1
	asl.b	#6,d0			; Mode-Bit zu Bit 6 schieben
	or.w	d0,d1			; P,/V-Bit setzen
	move.w	d1,-(sp)
	bsr	_WriteByte
	addq.l	#4,sp
	move.w	#IC4,-(sp)
	move.w	#%00000000,-(sp)	; IC4 initialisieren
	bsr	_WriteByte
	addq.l	#4,sp
	move.w	#IC5,-(sp)
	move.w	#%00101000,-(sp)	; IC5 initialisieren
	bsr	_WriteByte
	addq.l	#4,sp
2$
	bsr	_VeditOn		; Edit-Spannung aufbauen
	bsr	_EnableOutput		; Bits anlegen
	bsr	_EnableVcc		; Vcc anlegen
	move.l	_DOSBase,a6
	moveq	#20,d1			; Prellzeit der Relais überbrücken
	jsr	_LVODelay(a6)
	bsr	_EnableVEdit		; Edit-Spannung anlegen
				    ; GAL befindet sich jetzt im Edit-Mode
	movem.l	savereg,d0-d7/a0-a6	; Registerinhalte zurückholen
	rts





	dseg

; Zwischenspeicher, um Register zu retten ohne den Stack zu benützen
savereg:	ds.l	15		; 8 Datenregister, 7 Adressregister

_outIC1:	dc.w	0
_outIC3:	dc.w	0
_outIC4:	dc.w	0
_outIC5:	dc.w	0
_GALType:	dc.w	0


	END
