* * 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