Zum Hauptinhalt Zur Navigation

TTL-Computer programmieren: Nach dem Schock kommt der Spaß

Er besteht nur aus Logikbausteinen und friert bei Programmierfehlern direkt ein. Nachdem wir uns reingefuchst hatten, hatten wir aber riesigen Spaß mit dem Gigatron.
/ Johannes Hiltscher
14 Kommentare News folgen (öffnet im neuen Fenster)
Um den Gigatron zu programmieren, braucht es nur einen Arduino Uno, einen Monitor mit VGA-Anschluss und vier Kabel. (Bild: Johannes Hiltscher, Golem.de)
Um den Gigatron zu programmieren, braucht es nur einen Arduino Uno, einen Monitor mit VGA-Anschluss und vier Kabel. Bild: Johannes Hiltscher, Golem.de

Den TTL-Computer Gigatron zusammenzulöten, ist eine spaßige Sache , auch dank des durchdachten Designs. Aber macht es genau so viel Spaß, ihn zu programmieren? Schließlich haben sich die Entwickler die Mikroarchitektur selbst ausgedacht, der Befehlssatz entspricht keinem anderen Prozessor. Das bedeutet: Wir können nicht einfach einen passenden C-Compiler installieren und loslegen.

Die Dokumentation auf der Homepage ist zudem recht spärlich, im Github-Repository des Projekts(öffnet im neuen Fenster) ist auch die Programmierung des Gigatron dokumentiert. Allerdings ist sie nicht besonders übersichtlich, die notwendigen Informationen müssen wir uns aus mehreren Textdateien zusammensuchen.

Kleinere Programme lassen sich direkt in den Basic-Interpreter eingeben, größere werden mittels der Anwendung Loader direkt in den Arbeitsspeicher geladen. Außerdem könnten wir einen eigenen EPROM (Erasable Programmable Read-Only Memory) mit einem selbst in Assembler geschriebenen Programm beschreiben und gegen den mitgelieferten Speicher tauschen.

Auch in C kann der Gigatron programmiert werden, im Repository findet sich ein passender Compiler namens glcc . Als Kompromiss zwischen Basic und Assembler haben die Entwickler eine Programmiersprache namens Gigatron Control Language (GCL) entwickelt. Sie wird in Bytecode übersetzt, der von einer virtuellen Maschine (VM) auf dem Gigatron ausgeführt wird. Das Prinzip ist ähnlich wie bei Micropythons Frozen Bytecode (g+) . Für das echte Retro-Gefühl haben wir uns an GCL gewagt.

Tiny Basic nutzt virtuelle Maschine

Ähnlich wie Java oder Python baut auch der beim Gigatron genutzte Interpreter Tiny Basic auf einer VM auf. Die unterstützt sogar 16-Bit-Arithmetik, der reale Prozessor rechnet nur mit 8 Bit. GCL-Code wird in den Bytecode der VM übersetzt und von dieser ausgeführt. Auch der C-Compiler übersetzt in diesen Bytecode. Die VM hat einen großen Vorteil gegenüber Assembler-Programmierung: Sie enthält bereits die Logik zur Ausgabe von Bild- und Tonsignalen.

Game of Life auf dem Gigatron im Zeitraffer
Game of Life auf dem Gigatron im Zeitraffer (01:00)

Programme werden ausgeführt, wenn der Prozessor gerade nicht mit den Ausgaben beschäftigt ist. Damit lassen sich zwar nicht alle Möglichkeiten des Gigatron nutzen, für den Einstieg ist es aber die sinnvollste Variante. Das vorinstallierte Spiel Racer etwa verschiebt den Bildschirm zeilenweise, um Kurven darzustellen. Für solche Effekte sind eigene Systemfunktionen erforderlich, die komplexe Operationen wie die Ausgabe von Grafiken ermöglichen. Die sind in nativem Gigatron-Assembler geschrieben, können aber nur aus dem ROM ausgeführt werden. Diese Möglichkeit zu nutzen, bedeutet also größeren Aufwand – zu viel für den Einstieg.

Allzu viel können wir vom Gigatron übrigens nicht erwarten: Der größte Teil des 32 kByte großen Arbeitsspeichers ist für den Framebuffer reserviert, den der Prozessor Byte für Byte in den entsprechenden Ausgabepuffer kopiert. Programme werden nur während der vertikalen und horizontalen Austastlücke (V- und H-Blank) ausgeführt.

Außerdem sind die simulierten Striche zwischen den Scanlines mehr als ein optisches Element: Da das Bild mit 640 x 480 Pixeln ausgegeben wird, der Gigatron aber intern nur mit 160 x 120 Pixeln arbeitet, verringern sie den Aufwand bei der Bildausgabe. Jede dieser schwarzen Zeilen steht für die Abarbeitung unseres Codes zur Verfügung, da nur einmal am Anfang der Schwarzwert und am Ende der Synchronisationspuls geladen werden müssen.

Aber sehen wir uns einmal die Programmierung an.

Eine anspruchsvolle Programmiersprache

Von Hochsprachen verwöhnte Programmierer können beim Blick auf ein GCL-Programm leicht einen Schock bekommen: Operationen werden durch Sonderzeichen (Punkt, Komma, Klammern) dargestellt, außerdem sind die Möglichkeiten stark begrenzt. Das liegt an der Architektur der VM: Es handelt sich um eine Akkumulator-Architektur, der Akkumulator ist das einzige frei nutzbare Register. Daneben existieren noch Programmzähler (PC), Stack-Zeiger (SP) und das Link-Register (LR), das bei Funktionsrufen die Rücksprungadresse speichert. Alle Register haben 16 Bit.

Fast alle Operationen laufen über den Akkumulator. Daher gingen wir nach dem ersten Blick auf die Beispielprogramme fälschlicherweise davon aus, GCL nutze die umgekehrte polnische Notation(öffnet im neuen Fenster) . Einen Wert zu einer Variablen zu addieren sieht etwa so aus: Line 8+ . Das sind allerdings zwei Operationen: Der Variablenname am Anfang lädt ihren Inhalt in den Akkumulator, der Ausdruck 8+ addiert einen konstanten Wert zum Akkumulator.

Auch die Mikroarchitektur des Prozessors bringt Einschränkungen mit sich: So dürfen Funktionen etwa keine 256-Byte-Grenzen überschreiten, wir müssen selbst dafür sorgen, dass der Code passend auf diese sogenannten Seiten verteilt ist. Der Compiler, ein Python-Script, hilft dabei mit recht brauchbaren Fehlermeldungen. Variable dürfen nur in der ersten Speicherseite liegen, allerdings können wir über die direkte Verwendung von Adressen (sprich: Zeiger) auf den gesamten Speicher zugreifen. Rufen wir aus einer Funktion eine andere auf, müssen wir zudem selbst das Link-Register auf dem Stack sichern.

Nach dem ersten Erfolg geht es schneller

Wir probieren uns zunächst an einem Programm, das einfach nur den Bildschirm mit einer festen Farbe füllt. Die Farbe eines Pixels lässt sich ändern, indem ein entsprechender Wert an die passende Speicheradresse geschrieben wird.

Ebenso herrlich direkt wie die Ausgabe von Grafik ist die Reaktion des Gigatron auf Programmierfehler: Schreiben wir an die falsche Adresse, friert das System einfach ein. Ein Punkt an der falschen Stelle kann dafür sorgen, dass anstelle der Farbe eines Pixels eine Variable der VM oder unser eigener Code geändert wird. Dann wird der Bildschirm schwarz und es heißt: Kabel ziehen, wieder einstecken, Fehler suchen und einen neuen Anlauf starten.

Das passiert uns einige Male, bevor das erste Programm läuft. Es zeigt bereits das geringe Potenzial von GCL-Code: Den kompletten Bildschirminhalt zu ändern, dauert mit dem unten gezeigten Code einige Sekunden. Die Beispielprogramme ändern deshalb stets nur einzelne Pixel oder nutzen in nativem Gigatron-Code geschriebene Systemfunktionen.

        
{ Farbe auf 0 setzen}
0 Color=
[do
    $800 Pos= { Zeiger auf Frame Buffer }

    { obere 8 Bit (Y) in AC laden, prüfen ob < 128 }
    [do >Pos, 127& if<>0 { Test, ob Speicherende erreicht }
        { untere 8 Bit (X) in AC laden, 160 abziehen -> Test auf Zeilenende }
        [do <Pos, 160- if<>0
            Color Pos. { Pixel färben }
            <Pos++ { X inkrementieren (im Speicher) }
        loop]
        >Pos++ { Zeile zu Ende, Y inkrementieren }
        0 <Pos. { X auf 0 setzen }
    loop]
    { nächste Farbe }
    <Color++
loop]

Dann wagen wir uns an eine größere Herausforderung: Eine Umsetzung von Conway's Game of Life(öffnet im neuen Fenster) auf dem Gigatron. Wer sich den Code ansehen möchte, findet ihn hier(öffnet im neuen Fenster) . Während wir für das erste Programm gute zwei Stunden benötigt haben, geht uns das zweite bereits deutlich schneller von der Hand. Fehler zu finden, ist allerdings eine Herausforderung und erfordert wache Augen, da die Möglichkeiten zum Debuggen sehr eingeschränkt sind. Zumindest gibt es einen Emulator, der ebenfalls im Github-Repository des Projekts zu finden ist.

Eigene Programme auf den Gigatron zu bekommen, ist hingegen sehr einfach.

Der Gigatron macht auch beim Programmieren Spaß

Um Programme in den Speicher des Gigatron zu laden, empfehlen die Entwickler, einen Arduino Uno als Programmieradapter zu verwenden. Der wird an den Joystick-Port angesteckt, von dem der Loader Daten liest, und mit einem Sketch aus dem Repository programmiert. Anschließend lassen sich mit einem Python-Script Basic-Programme und vorkompilierter Code im Gigatron-spezifischen Format GT1, das der GCL-Compiler erzeugt, übertragen.

Da das Repository auch mehrere Code-Beispiele umfasst, kann das direkt ausprobiert werden. Da es sich bei unserem Arduino um einen Klon mit anderem USB-Seriell-Wandler handelt, müssen wir dem Python-Script durch Angabe der passenden Gerätedatei auf die Sprünge helfen. Dann klappt die Übertragung sehr einfach, das Script führt zunächst einen Reset aus, startet dann den Loader, überträgt das Programm und startet es. Auch hier haben die Entwickler viel Arbeit in die Nutzbarkeit investiert. Kommen wir damit zum Fazit.

Spaßige Code-Knobelei

Auch wenn es beim ersten Blick auf GCL-Code nicht so scheinen mag: Den Gigatron damit zu programmieren, macht nach kurzer Zeit richtig Spaß. Ideen lassen sich schnell und direkt umsetzen, die Suche nach den selbst produzierten Fehlern ist mehr Herausforderung als nervig – sofern der Weg das Ziel ist und es nicht darum geht, etwas fertig zu bekommen. Aber genau das soll der Gigatron ja auch sein: eine interessante Herausforderung mit Lernpotenzial.

Die frickelig anmutende Programmierung mit GCL oder Basic ist dabei gerade wichtiger Bestandteil des Computergefühls der 1970er Jahre – so weit wir das als Spätgeborene beurteilen können. Das Drumherum haben die Entwickler, wie auch den Gigatron selbst, mit viel Arbeit und guten Ideen sehr komfortabel gestaltet. Wer einen passenden Arduino zu Hause hat, kann direkt mit dem Programmieren loslegen. Lediglich die Dokumentation zur Programmierung würden wir uns ausführlicher wünschen, ein umfangreich kommentiertes Beispielprogramm wäre hilfreich.


Relevante Themen