Clack-BASIC Compiler & 16-Bit Relais-Architektur
Hochpräzise Drei-Adress-Code Übersetzung, bitweise Arithmetik und hardwareangepasste Taktzyklen für Martin und Peter's spektakulären 16-Bit Relaiscomputer.
Der von Peter konstruierte Computer arbeitet vollständig mit mechanischen Schwachstromrelais für Register und Ablaufsteuerung sowie Diodenmatrizen für logische und arithmetische Funktionen. Die Taktzyklen müssen die physikalische Trägheit der Relaiszungen (~8–12 ms Anzug, ~4–6 ms Abfall) sowie Kontaktprellen berücksichtigen.
⚙️ Register-Architektur
Die CPU besitzt vier primäre 16-Bit Register sowie ein Statusregister für Bedingungsabfragen:
ACC(Akkumulator): Hauptrechenregister für ALU-Operationen und I/O.B(Hilfsregister): Zweiter Operand für arithmetische/logische Operationen.PC(Programmzähler): Zeigt auf die aktuelle Adresse im 1024-Worte Speicher.SP(Stapelzeiger): Adressiert den Hardware-Stack ab0x037Fabwärts.FLAGS: Relaisgestützte Zustandsspeicher: Zero (Z), Carry (C), Sign (S), Overflow (O).
⏱️ Relais-Schaltverhalten & Prellzeit
Mechanische Kontakte vibrieren beim Schließen mehrere Millisekunden. Die Taktsteuerung schützt die ALU vor fehlerhaften Übergangszuständen:
- Anzugszeit: 8–12 ms bis zum sicheren Schließen der Arbeitskontakte.
- Prellzeit (Bounce): 1.5–3 ms Kontaktprellen mit Funkenlöschdioden.
- Abtastfenster: Flankenwechsel wird erst nach Ablauf des Prellzeit-Monoflops freigegeben.
- Taktfrequenz: Realbetrieb bei ~15–30 Hz; im Simulator bis 10.000 Hz beschleunigbar.
Speicherbelegungsplan (1024 Worte à 16 Bit)
| Adressbereich (Hex) | Adressbereich (Dezimal) | Größe | Funktion / Zuordnung | Zugriff |
|---|---|---|---|---|
0x0000 – 0x001F |
0 – 31 | 32 Worte | Zero-Page: Schnelle Direktvariablen (A–Z), Systemregister, Temporärvariablen | Lesen / Schreiben (1 Zyklus) |
0x0020 – 0x02FF |
32 – 767 | 736 Worte | Programmcode & Bytecode: Kompilierte Clack-BASIC Drei-Adress-Befehle | Ausführen / Lesen |
0x0300 – 0x037F |
768 – 895 | 128 Worte | Call-Stack: Rücksprungadressen für GOSUB / RETURN und lokale Push-Werte |
Stapel (wächst abwärts ab 0x037F) |
0x0380 – 0x03BF |
896 – 959 | 64 Worte | 32×32 Relais-Matrix Framebuffer: 64 Worte à 16 Bit = 1024 Bildpunkte | Direktzugriff via PSET / LINE / CLS |
0x03C0 – 0x03FF |
960 – 1023 | 64 Worte | Hardware I/O & Steuerung: Serielles Interface, Tastaturpuffer, FPGA-Bridge | Memory-Mapped I/O |
Clack-BASIC wurde speziell für die 16-Bit Wortbreite und die Taktzyklus-Eigenschaften von Peter's Relaiscomputer entwickelt. Der Compiler generiert hochoptimierten Drei-Adress-Code, vermeidet rechenintensive Stack-Frames und übersetzt komplexe Ausdrücke in minimale Registertransfers.
| Befehl / Syntax | Kategorie | Beschreibung & Hardware-Abbildung |
|---|---|---|
A = 42 / DIM X(10) |
Variablen | 16-Bit vorzeichenbehaftete Ganzzahlen (-32768 bis 32767). Arrays werden linear im oberen Speicher allokiert. |
IF A > B THEN ... ELSE ... |
Kontrollfluss | Vergleich über Hardware-Flags (CMP). Verzweigung via Bedingungs-Jumps (JZ, JNZ, JGT, JLT). |
FOR I = 1 TO 10 STEP 2 ... NEXT |
Schleifen | Hardware-optimierte Schleifenzähler mit Register-Bindung. |
GOSUB 500 ... RETURN |
Unterprogramme | Sichert den Programmzähler auf dem Hardware-Stack (0x0300–0x037F) und verzweigt. |
WHILE X > 0 ... WEND |
Schleifen | Bedingte Kopfschleife mit Auswertung vor jedem Durchlauf. |
SQR(X) NEU v1.5.5 |
Arithmetik | Ganzzahlige Quadratwurzel: 8-Schritt divisionsfreier Shift-and-Subtract Algorithmus in ≤16 Taktzyklen. |
SQR(X, DEC) NEU v1.5.5 |
Arithmetik | Festkomma-Wurzel: Berechnet Wurzeln mit bis zu 2 Nachkommastellen (z.B. SQR(2, 2) → 141 = 1.41) ohne Division. |
CLS |
Matrix-Grafik | Löscht die 32×32 Relais-Matrix durch schnelles Beschreiben der 64 Framebuffer-Worte mit 0. |
PSET(X, Y, C) |
Matrix-Grafik | Setzt (C=1) oder löscht (C=0) den Bildpunkt an Koordinate (X, Y) im Bereich 0–31. |
LINE(X1, Y1, X2, Y2, C) |
Matrix-Grafik | Zeichnet eine Linie mittels hardwarenaher Bresenham-Ganzzahlarithmetik direkt in die Relais-Matrix. |
PIXELMOVE(DIR) |
Matrix-Grafik | Hardware-Scroll der gesamten 32×32 Matrix (DIR: 1=Up, 2=Down, 3=Left, 4=Right). |
POKE Addr, Val / PEEK(Addr) |
Speicherzugriff | Direkter 16-Bit Schreib- und Lesezugriff auf jede physikalische Speicheradresse des Relaiscomputers. |
📐 Technischer Deep-Dive: Die divisionsfreie Wurzelfunktion in v1.5.5
Da ein Relaiscomputer für eine Ganzzahl-Division bis zu 32 Zyklen mit Relais-Klickfolgen benötigt, implementiert Clack-BASIC v1.5.5 das Wurzelziehen als divisionsfreien 8-Schritt Bit-für-Bit Algorithmus (Shift-and-Subtract). Für 16-Bit Ganzzahlen benötigt die Berechnung exakt 8 feste Iterationsstufen:
10 REM ========================================================
20 REM CLACK-BASIC v1.5.5 SQR DEMO // 16-BIT RELAISCOMPUTER
30 REM ========================================================
40 CLS
50 PRINT "TEST 1: GANZZAHLIGE WURZELN"
60 FOR X = 1 TO 10
70 Y = SQR(X * X)
80 PRINT "SQRT("; X * X; ") = "; Y
90 NEXT X
100 PRINT "----------------------------------------"
110 PRINT "TEST 2: HOCHPRÄZISE FESTKOMMA-WURZEL"
120 REM SQR(2, 2) berechnet Wurzel 2 mit 2 Nachkommastellen (x100)
130 F = SQR(2, 2)
140 W_INT = F / 100
150 W_DEC = F MOD 100
160 PRINT "SQRT(2) = "; W_INT; "."; W_DEC; " (ERGEBNIS: 1.41)"
170 END
Der Clack-BASIC Compiler übersetzt den Quelltext direkt in die Maschinencodes von Peter's Relais-CPU. Jedes Befehlswort besteht aus einem 6-Bit Opcode-Feld, Modus-Bits und einem 10-Bit Adress-/Literal-Feld.
| Opcode (Hex) | Mnemonic | Operanden | Funktion (RTL) | Relais-Zyklen |
|---|---|---|---|---|
0x01 | LOAD | [addr] | ACC ← Mem[addr] | 2 (~30 ms) |
0x02 | STORE | [addr] | Mem[addr] ← ACC | 2 (~30 ms) |
0x03 | LOADI | val | ACC ← val (16-Bit Sofortwert) | 1 (~15 ms) |
0x04 | ADD | [addr] | ACC ← ACC + Mem[addr], Flags | 2 (~30 ms) |
0x05 | SUB | [addr] | ACC ← ACC - Mem[addr], Flags | 2 (~30 ms) |
0x06 | CMP | [addr] | Flags ← ACC - Mem[addr] (ACC unverändert) | 2 (~30 ms) |
0x07 | JMP | addr | PC ← addr | 1 (~15 ms) |
0x08 | JZ | addr | IF Z=1 THEN PC ← addr | 1 (~15 ms) |
0x09 | JNZ | addr | IF Z=0 THEN PC ← addr | 1 (~15 ms) |
0x0A | CALL | addr | PUSH PC; PC ← addr | 3 (~45 ms) |
0x0B | RET | - | POP PC | 2 (~30 ms) |
0x0C | OUT | port | Port[port] ← ACC | 1 (~15 ms) |
0x0D | IN | port | ACC ← Port[port] | 1 (~15 ms) |
0x1F | HALT | - | Taktgenerator stoppen, Relais in Ruhelage | 1 |
🌌 1. Mandelbrot-Fraktal auf 32×32 Relais-Matrix
Dieses Programm läuft real auf Peter's 16-Bit Relaiscomputer! Es berechnet die Mandelbrot-Menge mittels 16-Bit Festkomma-Arithmetik (Skalierungsfaktor 256) und schaltet die Relais der 32×32 LED-Matrix entsprechend ein.
10 REM ======================================================== 20 REM MANDELBROT-MENGE 32x32 FUER PETER'S RELAISCOMPUTER 30 REM 16-Bit Festkomma-Arithmetik (Skalierung: 256 = 1.0) 40 REM ======================================================== 50 CLS 60 MAXITER = 16 70 FOR Y = 0 TO 31 80 CI = (Y - 16) * 16 90 FOR X = 0 TO 31 100 CR = (X - 22) * 16 110 ZR = 0 120 ZI = 0 130 FOR I = 1 TO MAXITER 140 ZR2 = (ZR * ZR) / 256 150 ZI2 = (ZI * ZI) / 256 160 IF (ZR2 + ZI2) > 1024 THEN GOTO 220 170 ZI = (ZR * ZI) / 128 + CI 180 ZR = ZR2 - ZI2 + CR 190 NEXT I 200 PSET(X, Y, 1) 210 GOTO 230 220 PSET(X, Y, 0) 230 NEXT X 240 NEXT Y 250 END
Das Foto zeigt das originale LED-Anzeigefeld des Relaiscomputers nach Durchlauf der obigen Mandelbrot-Berechnung. Die Apfelmännchen-Struktur ist auf den 1024 Relaispunkten scharf erkennbar!
💻 Clack CLI Schnellstart
Nach dem Download kann der Compiler direkt im Terminal ausgeführt werden:
# Ausführungsrechte vergeben (unter Linux / macOS) chmod +x clack-linux-amd64 # BASIC Programm kompilieren zu Relais-Maschinencode ./clack-linux-amd64 build mandelbrot.bas -o mandelbrot.bin # Programm im virtuellen 16-Bit Emulator ausführen ./clack-linux-amd64 run mandelbrot.bas # Maschinencode disassemblieren ./clack-linux-amd64 disasm mandelbrot.bin