Generelle Informationen
Die beiden Mikrocontroller sind sehr ähnlich beschaltet und nehmen auch vergleichbare Aufgaben wahr. Die Erklärung gliedert sich daher in die Funktionen beider Mikrocontroller und gibt auch Aufschluss über die Erzeugung des internen Ablenksignals, mit dem das Videomodul des EE3023 simuliert werden kann.
Horizontaler Mikrocontroller
Der horizontale Mikrocontroller übernimmt die Erzeugung der horizontalen Sync-Signale für VGA und FBAS. Wenn ein Videosignal anliegt, dann erhält er an einem seiner Interrupt-Eingänge (D2 und D3 für INT0 und INT1) das jeweilige Taktsignal. Dieses Taktsignal sorgt für den Aufruf eines Unterprogramms, das den Sync-Impuls am Ausgang C0 ein- und ausschaltet. Der folgende kurze Code für das FBAS-Signal an INT0 verdeutlicht das:
ISR(INT0_vect)
{
int i;
// Bildlagekorrektur
for( i = porch_delay; i < max_delay_time; i++)
NOP8;
// Sync wird aufgerufen
hsync_on;
NOP100;
hsync_off;
}
„NOP“ steht dabei für eine Pause, der Mikrocontroller tut in dieser Zeit für einen Taktzyklus nichts. NOP8 meint 8 solcher Pausen, analog ist es bei 100. Das Sync-Signal hat damit eine definierte Länge.
Zusätzlich wird hier bereits eine Bildlagekorrektur durchgeführt, die es erlaubt, das Bild in horizontaler oder vertikaler Richtung exakt einzustellen. Dazu bedient sich das Programm eines Tricks. Der eingehende Sync-Impuls wird nicht direkt weitergegeben, sondern maximal bis zur nächsten Zeile verzögert. Damit kann man recht genau einstellen, wo die Videozeile am Bildschirm beginnt und wo sie endet. Die Bildlagekorrektur fügt dazu einfach weitere Pausen ein, bevor das Sync-Signal ausgegeben wird. Wenn man die Abstufung fein genug wählt, erreicht man eine gute Darstellung auf dem Bildschirm. Die Ermittlung des besten Werts ist allerdings eine aufwendige Sache. Eine nachträgliche Einstellbarkeit war im Prototypen vorgesehen, darauf konnte aber nach der Abgleichphase komplett verzichtet werden. Der VGA-Teil läuft analog, nur wird hier zwischen VGA (640×480) und SVGA (800×600) unterschieden, weil beide unterschiedliche Timings haben. Die folgenden Bilder demonstrieren die Zeilenlage-Korrektur – einmal richtig, einmal verstellt.
Die Erkennung von VGA- oder SVGA-Eingangssignalen wird ebenfalls im horizontalen Mikrocontroller durchgeführt. Beide unterscheiden sich durch eine unterschiedliche Horizontalfrequenz (31,4 KHz und 37,6 kHz). Es wurde daher ein internes Ablaufzähler-Unterprogramm geschaffen, der prüft, wie viele Zeilen (INT-Aufrufe) inzwischen eingegangen sind. Innerhalb einer Sekunde sind das entweder 37600 oder 31400. Zur schnelleren Bearbeitung wird der Zähler im 76Hz-Takt aufgerufen und prüft dann, ob mehr oder weniger als 450 Zeilen dargestellt wurden – seine Schwelle liegt also bei 450x76Hz=34kHz.
ISR(TIMER2_COMPA_vect)
{
…
if (linecount > 450) // wird im 76Hz-Takt aufgerufen 450x76Hz=34kHz
vga_mode = VGA800;
else
vga_mode = VGA640;
…
}
Die Information, welcher VGA-Modus gewählt wurde, teilt der Mikrocontroller der Außenwelt über den Ausgang D0 mit.
Vertikaler Mikrocontroller
Der vertikale Mikrocontroller arbeitet analog zum horizontalen. Er erhält seine Steuersignale ebenfalls über die INT-Eingänge D2 und D3, hier sind die Frequenzen allerdings deutlich niedriger mit 50Hz (FBAS) und 60Hz (VGA/SVGA). Auch hier wird der Verzögerungstrick angewendet, um die Bildlage zu optimieren. Die beiden Unterprogramme zur Erzeugung der Sync-Signale erhöhen zudem noch bei jedem Aufruf einen Zähler um 1, damit werden die eingehenden Bilder gezählt.
Dieser Zähler wird von einem Ablaufzähler-Unterprogramm ausgewertet, das prüft, ob seit dem letzten Aufruf eine gewisse Anzahl Bilder (=Aufrufe der Interrupt-Unterprogramme) erzeugt wurden. Ist das der Fall, dann liegt am aktiven Videoeingang ein Signal an. Fehlt dieses Signal aber, dann wird der Zähler nicht erhöht, und das Ablaufzähler-Unterprogramm erkennt, dass kein externes Signal mehr anliegt. Es schaltet dann um auf „internen Modus“ und teilt dies dem horizontalen Mikrocontroller über den Ausgang D6 mit. Gleichzeitig wird noch die passende LED an Ausgang B4 aktiviert.
ISR(TIMER1_COMPA_vect)
{
if (sync_avail > 3)
// Das ist der Zähler, der von den Interrupt-Unterprogrammen hochgezählt wird
{
PORTD &= ~(1<<PD6); // Interner Generator deaktiviert
PORTB |= (1<<PB4); // LED deaktivieren (Achtung, LED arbeitet invertiert)
}
else
{
PORTD |= (1<<PD6); // Interner Generator eingeschaltet
PORTB &= ~(1<<PB4); // LED aktivieren (Achtung, LED arbeitet invertiert)
}
sync_avail = 0;
}
Der vertikale Mikrocontroller ist außerdem für die Ansteuerung der Info-LEDs (an B1-B4) zuständig, die Auskunft geben über den jeweils aktiven Modus (intern/extern und FBAS/VGA/SVGA).
Der interne Modus
Zur Simulation des Videomoduls des EE3023 und natürlich zur Schonung der Bildröhre bei fehlendem Eingangssignal wurde ein interner Modus geschaffen, der selbständig Sync-Signale erzeugt, wenn kein externes Signal anliegt. Die Erkennung hierfür wurde bereits weiter oben beschrieben. In diesem Modus hat der vertikale Mikrocontroller keine weiteren Aufgaben, alle Signale werden komplett vom horizontalen Mikrocontroller erzeugt.
Hier kommt bei FBAS und VGA (intern wird kein SVGA unterstützt) gleichermaßen ein Ablaufzähler-Unterprogramm zum Einsatz. Diese Unterprogramme zeichnen sich dadurch aus, dass sie nach einer exakt definierten Zeit aufgerufen werden – in unserem Falle zum Beginn einer jeden Zeile. Über Pause-Befehle hält sich der Mikrocontroller während der gesamten Zeile im Unterprogramm auf und schaltet wechselweise die Ausgänge C1-C4 (für Q1-Q4) aus und ein, so dass dort höherfrequente, zur Zeile synchrone Impulse verfügbar sind.
Am Ende der Zeile wird ein Zeilenzähler um eins erhöht, bis die Gesamtzahl an Zeilen erreicht ist (bei VGA 600, bei FBAS 313 wegen des Halbbildverfahrens). Anhand dieses Zeilenzählers werden nun auch die Ausgänge B1-B4 (für Q5-Q8) aktiviert, jeweils für eine Dauer einiger Zeilen, so dass dort höherfrequente, zum Bild synchrone Impulse verfügbar sind.