← ST-Computer 08 / 1987

ST-Tips: Ab ins Dunkle - Der Bildschirmabschalter

Grundlagen

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ß:

  • Berechnung der ProgrammlĂ€nge; die ProgrammlĂ€nge wird nach der Initialisierung an das GEMDOS mit der Funktion $31 (keep process) ĂŒbergeben um das Programm im Speicher resident zu halten
  • Supervisor-Modus einschalten, Programm initialisieren, User-Modus einschalten
  • mit dem Aufruf der GEMDOS-Funktion $31 kehrt das Programm ins Desktop zurĂŒck
  • im Initialisierungs-Teil wird ein ZĂ€hler fĂŒr System-Timer-Interrupts mit

’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.

  • in der neuen Keyboard-Routine wird der ZĂ€hler fĂŒr Timer-Interrupts wieder mit ’60000’ geladen, das Interruptflag gesetzt und dann die alte Interrupt-Routine angesprungen
  • in der neuen Timer-Routine wird zuerst geprĂŒft ob der Bildschirm schon abgeschaltet ist.

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)