Die Entwickler des ATARI ST haben offenbar ein kleines Detail übersehen oder für zu unwichtig gehalten, denn das Videosignal des Rechners wird auch dann nicht abgeschaltet, wenn der Rechner längere Zeit nicht benutzt wird.
Da dieser Umstand auf die Dauer unschöne Brennspuren auf der Fluoreszensschicht des Bildschirms hinterläßt und die Fummelei am Helligkeitsregler nicht die eleganteste Lösung ist, habe ich ein kleines Programm geschrieben, welches das Videosignal abschaltet wenn die Tastatur/Maus des Rechners 5 Minuten lang nicht benutzt wird. Das Bild erscheint wieder, wenn eine Taste gedrückt oder die Maus bewegt wird.
Das Programm wird im AUTO-Ordner untergebracht, damit es bei einem Systemstart installiert wird.
Die Funktion des Programms möchte ich anhand des dokumentierten Quellcodes erläutern:
Vorausschickend bleibt zu sagen, daß an der Speicheradresse SFF8200 das Register für die Video-Anzeige liegt. In diesem Register steuert das Bit 0 die Synchronisation des Bildes. Wird dieses Bit auf ’T gesetzt,werden die intern erzeugten Synchronisationssignale abgeschaltet und der Bildschirm erscheint dunkel. Zu beachten bleibt, daß bei gesetztem Bit der VBL-Interrupt, der verschiedene periodische Systemaufgaben ausführt, simuliert werden muß:
’60000’ geladen. Da der Timer mit einer Frequenz von 200 Hz Interrupts erzeugt und der Zähler in der eigenen Routine nach jedem Interrupt um 1 dekrementiert wird, ist nach 60000/200 = 300 Sekunden oder 5 Minuten! der Zähler auf ’0’ gezählt; ein Zähler für die Simulation des VBL-Interrupt’s wird mit 3 geladen; dieser Zähler wird in der neuen Timer-Routine bei jedem Aufruf um 1 dekrementiert und bei Erreichen von ’0’ wird der VBL-Interrupt simuliert. Dies gibt eine Simulationsfrequenz von 200/3 = 66.66... Hz. Ein Flag für Keyboard-Interrupts wird mit ’0’ vorbesetzt; danach werden die Interrupt-Vektoren für den Timer und das Keyboard auf die neuen Routinen gesetzt und die alten Vektoren jeweils an das Ende der eigenen Routinen geschrieben; zusätzlich wird noch der Vektor auf den VBL-Handler in die neue Timer-Routine geschrieben.
Wenn dies der Fall ist, wird das Keyboard-Interruptflag getestet und, falls es gesetzt ist, der Bildschirm eingeschaltet. Ist das Interruptflag nicht gesetzt,wird der Zähler für die VBL-Simulation erniedrigt und bei Bedarf der VBL-Interrupt ausgeführt.
War bei Anruf der Timer-Routine der Bildschirm noch eingeschaltet, wird der Timer-Zähler um ’1’ erniedrigt. Ist der Zähler noch nicht auf ’0’ gezählt (die 5 Minuten sind noch nicht abgelaufen) wird die alte Timer-Routine angesprungen.
Andernfalls wird das Keyboardflag gelöscht, der nächste VBL-Interrupt abgewartet und dann der Bildschirm abgeschaltet. Die neue Timer-Routine wird in jedem Fall mit dem Aufruf der alten Routine beendet.
Anmerkung:
Der Inhalt des Datenregisters D0 muß gerettet werden, da in einer Interrupt-Routine die Registerinhalte nicht verändert werden dürfen.
****************************************
* CRT-SAVER *
* H.-J. Moes *
* Dorfstraße 19 *
* 7854 Inzlingen *
* *
****************************************
v_shift = $ff820a * adresse des videoshifters
.text
move.l a7,a5 * alten Stackpointer retten
move.1 #uss,a7 * Stackpointer auf userstack
move.1 4(a5),a5 * adresse der basepage
move.l #$100,d7 * laenge der basepage '
add.l 12(a5),d7 * laenge des textsegment
add.1 20(a5),d7 * laenge des datensegment
add.l 28(a5),d7 * laenge des bss-segment
clr.l -(sp) * userstack wird Supervisorstack
move.w #$20,-(sp) * in Supervisormodus schalten
trap 1
move.l d0,ssp * alten supervisorstack-pointer retten
addq.l #6,sp
bsr init * initialisierung
move.l ssp,-(sp) * supervisorstack-pointer zurueck
move.w #$20,-(sp) * supervisormodus abschalten
trap 1
addq.l #6,sp * .stack-korrektur
clr.w -(sp) * kein fehler
move.l d7,-(sp) * programmlaenge
move.w #$31,-(sp) * keep process
trap 1
init pea initstring * begruessungsstring ausgeben
move.w #$09,-(sp) * Print line
trap 1
addq.l #6,sp
move.w #65535,d0
halt subq.w #1,d0 * verzoegerungsschleife
bne halt
move.w #60000,count * zaehler fuer timerdurchlaeufe
move.b #3,vblcount * zaehler fuer simulierten VBL-interrupt
move.b #0,keyflag * flag fuer keyboard-interrupt
move.l $118,keyalt + 2 * alter keyboard-/midi-interrupt
move.l #keybrd,$118
move.l $114,timealt+2 * alter timer c - interrupt
move.l #timer,$114
move.l $70,vbl+2 * vbl-vektor eintragen
rts
keybrd move.w #60000,count * zaehler neu laden
bset #0,keyflag * flag setzen
keyalt jmp $100000 * alte keyboard-/midi-routine aufrufen
timer btst #0,v_shift * externe Synchronisation ?
beq ein * bildschirm ist eingeschaltet
aus btst #0,keyflag * tastaturinterrupt aufgetreten ?
bne _ein * ja
subq.b #1,vblcount * VBL-zaehler dekrementieren
bne timealt * noch keine 3 timerdurchlaeufe
move.b #3,vblcount * zaehler neu laden
andi.w #$f8ff,SR * Interruptmaske low
pea timealt * nach VBL-simulation in alte timerroutine
move.w SR,-(sp) * interrupt-stackzustand simulieren
vbl jmp $100000 * VBL-handler anspringen
_ein bclr #0,v_shift * auf interne Synchronisation schalten
timealt jmp $100000 * in alte timerroutine springen
*
ein subq.w #1,count * zeit abgelaufen
bne timealt * nein
bclr #0,keyflag * flag loeschen
move.w SR,-(sp) * Statusregister retten
andi.w #$f8ff,SR * interruptmaske low
move.1 d0,-(sp) * datenregister retten
move.l $466,d0 * zaehler fuer ausgefuehrte VBL-interrupts
warte cmp.1 $466,d0 * auf naechsten VBL-interrupt warten
beq warte
bset #0,v_shift * auf externe Synchronisation schalten
move.l (sp)+,d0 * register zurueckholen
move.w (sp) + ,SR * Statusregister zurueckholen
bra timealt * in alte timerroutine
*
. data
initstring .dc.b $1b,$45 * ESC E clear home
.de.b $1b,$59,32+3,32+3 * ESC Y
.dc.b ’CRT-Saver ST-Computer HJ Moes’
.dc.b $0d,0
vblcount .dc.b 0 * zaehler fuer VBL-simulation
keyflag .dc.b 0 * flag fuer keyboard-interrupt
. even
ssp .dc.l 0 * Speicher fuer alten Supervisorstack-pointer
count .dc.w 0 * zaehler fuer timer C - interrupts
.ds.1 50
uss .dc.l 0 * userstack
* assembliert mit folgendem Batch-File :
* as68 -1 -u %l.s
* link68 %1.68k = %l.o
* relmod %1.68k %l.prg
_________________________________________________
10 ' CRT.PRG Lader
11 Filename$="CRT.PRG"
12 OPEN "O",1,FilenameS
13 READ Wert
14 REPEAT
15 PRINT #1, CHR$ {Wert);
16 Summe=Summe+Wert
17 READ Wert
18 UNTIL Wert=-1
19 READ Pruefsumme
20 IF Pruefsumme<>Summe THEN
21 PRINT "Fehler In Datas"
22 ENDIF
23 CLOSE 1
100 DATA 96,26,0.0.1,56,0,0,0.254
101 DATA 0,0,0,0,0,0,0,0,0,0
102 DATA 0,0,0.0,0,0,0,0,42.79
103 DATA 46.124,0,0,2,50,42,109,0,4
104 DATA 46,60,0,0,1,0,222,173,0,12
105 DATA 222.173,0,20,222,173,0,28,66,167
106 DATA 63,60.0.32.78,65,35,192,0,0
107 DATA 1,100,92,143,97.24,47,57.0,0
108 DATA 1,100.63,60.0,32,78.65,92,143
109 DATA 66,103,47,7.63,60,0,49,78,65
110 DATA 72,121.0.0,1,56,63,60,0.9
111 DATA 78,65.92,143,48,60,255,255,83,64
112 DATA 102,252.51,252,234,96,0,0.1,104
113 DATA 19,252.0,3,0,0,1,98,19,252
114 DATA 0,0,0,0,1,99,35,249.0,0
115 DATA 1,24,0,0,0,188,35,252,0,0
116 DATA 0,170,0.0,1,24,35,249,0.0
117 DATA 1,20,0,0.1,0,35,252,0,0
118 DATA 0,192,0,0,1,20,35,249,0,0
119 DATA 0,112,0,0,0,242,78,117,51,252
120 DATA 234,96,0,0,1,104,8.249.0,0
121 DATA 0 0,1,99,78,249,0,16,0,0
122 DATA 8,57,0,0,0.255,130,10,103,58
123 DATA 8,57,0,0,0,0,1,99,102,34
124 DATA 83,57,0,0,1,98,102,34,19,252
125 DATA 0,3,0,0,1,98,2,124,248,255
126 DATA 72,121,0,0,0.254,64,231,78,249
127 DATA 0,16,0,0,8,185,0,0,0,255
128 DATA 130,10,78,249,0,16,0,0,83,121
129 DATA 0,0,1,104.102,242,8,185,0,0
130 DATA 0,0,1,99,64.231.2.124,248.255
131 DATA 47,0,32,57,0,0,4,102,176,185
132 DATA 0,0,4,102,103,248,8,249,'0,0
133 DATA 0,255,130,10,32,31,70,223,96,198
134 DATA 27,69,27,89,35,35,67,82,84,45
135 DATA 83,97,118,101.114,32,32,32,83,84
136 DATA 45,67.111,109,112,117,116,101,114,32
137 DATA 32,72,46,74,46,32,77,111,101,115
138 DATA 13,0,0,0,0,0,0,0,0,0
139 DATA 0,0,0,0,0,0,0,0,0,0
140 DATA 0,0,0,0,0.0.0,0,0,0
141 DATA 0,0,0,0,0,0,0,0,0,0
142 DATA 0,0,0,0,0,0,0,0,0,0
143 DATA 0,0,0,0,0,0,0,0,0,0
144 DATA 0,0,0,0,0,0,0,0,0.0
145 DATA 0,0,0,0,0,0,0,0,0,0
146 DATA 0.0,0,0,0,0,0.0,0,0
147 DATA 0.0,0,0,0,0,0,0,0.0
148 DATA 0,0,0,0,0,0,0,0,0,0
149 DATA 0,0,0.0,0,0,0.0.0,0
150 DATA 0,0,0.0,0,0,0,0,0,0
151 DATA 0,0,0,0,0,0,0,0,0,0
152 DATA 0,0,0,0,0,0,0.0,0.0
153 DATA 0,0,0,0,0,0,0,0,0,0
154 DATA 0,0,0,0,0,0,0,0,0,0
155 DATA 0,0,0,0,0,0,0,0,0,0
156 DATA 0,0,0.0,0,0,0,0,0,0
157 DATA 0,0,0,0,0,0,0.0,0,0
158 DATA 0,0,0,0,0,0,0,0,0,0
159 DATA 0,0,0,0,0,0,0,4,36,10
160 DATA 24,24,8,8,10.6,14,6,14,10
161 DATA 8,24,8,10,10,28,10,0,26
9998 DATA -1
9999 DATA 24015
(H.S.Moes)