0010Audiokassetten als Datenspeicher
08.07.2016
Das Diskettenlaufwerk für den C64 war anfangs noch sehr teuer. Als günstige Alternative gab’s die „Datasette“ – einen Kassettenrekorder mit C64-Anschluss. Aber wie funktioniert das Speichern von Daten auf Audiokassetten eigentlich genau?
Während das Diskettenlaufwerk 1541 in den 1980ern um die $400 kostete, gabs Datasetten schon um $70. Kein Wunder – technisch ist eine Datasette nicht viel mehr als ein normaler Kassettenrekorder, der über ein spezielles Kabel mit dem C64 verbunden werden kann1.
Speichern und Laden von Programmen
Wenn man ein BASIC-Programm geschrieben hat und es auf Kassette speichern möchte, geht das so:
- Man tippt am C64
SAVE "MEIN PROGRAMM"
- Der C64 meldet
PRESS RECORD & PLAY ON TAPE
- Man drückt die entsprechenden Tasten auf der Datasette, woraufhin die Aufnahme beginnt.2
- Eine gefühlte Ewigkeit (also ca. 30 Sekunden) später stoppt das Band wieder und C64 meldet sich mit
READY.
zurück – die Aufnahme ist fertig.
Das Laden funktioniert analog mit LOAD "MEIN PROGRAMM"
– vorausgesetzt, man hat die Kassette vorher an den Anfang zurückgespult.
Auf einer Kassette können auch mehrere Programme gespeichert sein (deswegen vergibt man beim Speichern einen Dateinamen), es gibt aber kein Inhaltsverzeichnis. Um ein bestimmtes Programm zu laden, muss der C64 daher das komplette Band einlesen und durchsuchen – so lange, bis er das Programm gefunden hat oder das Ende des Bandes erreicht ist.3
Wegen des fehlenden Inhaltsverzeichnisses sollte man sich tunlichst händisch notieren, welche Programme auf einer Kassette gespeichert sind. Auch das nachträgliche Ändern (Überschreiben) eines gespeicherten Programms ist eigentlich nur möglich, wenn es das letzte Programm auf der Kassette ist – ansonsten werden nachfolgende Daten überschrieben, falls sich die Länge des Programms geändert hat.
Alles in allem ist so eine Datasette also verdammt unpraktisch.
Aber irgendwie cool.
Audio-Kodierung der Daten
Wie sind die Daten eigentlich physisch auf der Kassette gespeichert?
Als Töne! Wenn man eine vom C64 bespielte Kassette in einem normalen Kassettenrekorder abspielt, hört sich das so an:
Mit einem Audioeditor wie Audacity digitalisiert erkennt man folgende Struktur:
Die Daten sind in einzelne Blöcke aufgeteilt. Jeder Block beginnt mit einem „Leader“, der noch keine Daten enthält, aber dem C64 erlaubt, sich mit dem Laufwerk zu synchronisieren. Anschließend folgen die eigentlichen Daten und eine kurze Pause, bevor der nächste Block folgt.
Wo in diesen Tönen stecken jetzt die eigentlichen Daten? Beim Schreiben erzeugt der C64 Rechteckwellen – sogenannte „Pulses“ – in drei unterschiedlichen Dauern bzw. Frequenzen4
- Short Pulse: ca. 350 µs (2.860 Hz)
- Medium Pulse: ca. 510 µs (1.960 Hz)
- Long Pulse: ca. 670 µs (1.490 Hz)
Bei entsprechender hoher Zoomstufe sieht man diese Pulses im Audioeditor – die theoretischen Rechteckwellen sind in der Praxis ziemlich abgerundet, aber noch klar erkennbar:
Misst man die Zeit zwischen zwei Nulldurchgängen (fallende Flanke, also wenn das Signal „von oben“ durch die Nulllinie geht), dann ergeben sich die oben beschriebenen Pulsdauern5. Im folgenden Bild hab ich die ersten paar Pulses am Übergang von Leader zu Daten entsprechend beschriftet:
Der Leader besteht ausschließlich aus Short Pulses. Die eigentlichen Daten verwenden dann alle drei Varianten, wobei immer zwei aufeinanderfolgende Pulses gemeinsam betrachtet werden müssen:
- Long Pulse + Medium Pulse: New-Data-Marker (markiert den Beginn eines Bytes)6
- Short Pulse + Medium Pulse: Bit 0
- Medium Pulse + Short Pulse: Bit 1
Mit diesem Wissen lässt sich dann das erste Byte dekodieren:
Konkret ist dieses Byte (und auch jedes weitere) so aufgebaut:
- New-Data-Marker
- 8 Datenbits in LSB-0-Reihenfolge
- 1 Prüfbit: Wenn in den Datenbits eine gerade Anzahl von 1-Bits vorkommt, dann ist dieses Prüfbit 1, ansonsten ist es 0.
In unserem Beispiel ergeben sich also die Bits 10010001
und das zugehörige korrekte Prüfbit 0
(die Anzahl der 1-Bits ist ungerade). Wegen der LSB-0-Reihenfolge muss man die Bits von hinten lesen, die gewohnte Darstellung wäre also 10001001
, was dezimal 137
bzw. hexadezimal 0x89
entspricht.
Dass das erste Byte diesen Wert hat, ist kein Zufall: Der erste Datenblock beginnt mit der Bytefolge 0x89 0x88 0x87 0x86 0x85 0x84 0x83 0x82 0x81
, bevor die „wirklichen“ Daten kommen (auch hier gehts wieder um Synchronisation).
Andere Formate und Schnelllader
Zum Abschluss bleibt noch zu sagen, dass ich hier nur das vom C64 verwendete Standard-Format für Daten auf Kassette beschrieben habe. Dieses Format ist recht fehlertolerant, aber auch ziemlich ineffizient7. Fast alle kommerziell erhältlichen Kassetten haben daher eigene, effizientere Formate verwendet und dafür eigene Laderoutinen („Loaders“) mitgebracht. Eine ausführliche Übersicht dazu gibt es auf c64tapes.org, ebenso wie eine detaillierte Beschreibung des Standard-Formats.
Update 20.10.2016: Lightning Talk
Auf der EuRuKo 2016 hab ich einen Lightning Talk dazu gehalten:
Slides (PDF, 5 MB)
-
Über das Kabel kann der C64 abfragen, ob gerade eine der Laufwerkstasten gedrückt ist (allerdings nicht, welche), und den Laufwerksmotor starten8 und stoppen. ↩
-
Außerdem schaltet der C64 seinen Bildschirm ab: Die Routinen für das Laden/Speichern auf Kassette sind so zeitkritisch, dass zu Beginn alle Interrupts deaktiviert werden – und damit auch die Bildschirmausgabe. ↩
-
Mit kluger Verwendung des mechanischen Zählwerks lässt sich das zumindest ein bisschen optimieren: Hat man sich die Anfangsposition eines gespeicherten Programms notiert, kann man das Band zunächst an diese Position spulen und den Ladevorgang gleich von dort beginnen. ↩
-
Diese Modulationstechnik nennt sich Frequency Shift Keying (Frequenzumtastung) und wird z.B. auch von Faxgeräten benutzt (die sich daher auch ganz ähnlich anhören). ↩
-
Die tatsächlichen Dauern können mehr oder weniger stark abweichen, in meinem Beispiel sind alle Pulse etwa um etwa 12% zu lang, Short Pulses dauern also 390 µs statt 350 µs usw. Grund für die Abweichungen sind Toleranzen der Mechanik in den Laufwerken – insbesondere, wenn Kassetten mit einem anderen Laufwerk gelesen werden, als ursprünglich zum Bespielen verwendet wurde. Aber genau deswegen existiert der „Leader“ am Beginn der Aufnahme – nachdem der ausschließlich aus Short Pulses besteht, kann der C64 hier die tatsächliche Länge dieser Pulse ermitteln und einen entsprechenden Korrekturfaktor berechnen, um anschließend alle 3 Puls-Typen verlässlich erkennen zu können9. ↩
-
Es gibt auch noch einen „End-Data-Marker“ (Long + Short) nach dem letzten Byte kommt – frühere C64-Versionen haben diesen Marker allerdings nicht geschrieben, und auch sonst ist er nicht wirklich wichtig (das letzte Byte lässt sich auch daran erkennen, dass danach keine weiteren Pulse mehr folgen). ↩
-
Die effektive Übertragungsgeschwindigkeit lag im Bereich von 60–70 Bytes pro Sekunde. ↩
-
Die „Play“-Taste muss man trotzdem manuell drücken: Damit startet man ja nicht nur den Laufwerksmotor, sondern bewegt über ein Gestänge auch den Schreib-/Lesekopf an die entsprechende Position. Und diese Bewegung kann der C64 nicht fernsteuern. ↩
-
Diese ganze schöne Synchronisation hilft natürlich nicht, wenn sich die Geschwindigkeit der Kassette (und damit die Länge der Pulse) während dem Abspielen ändert (auf gut deutsch: wenn das Band eiert). Falls diese Schwankungen zu groß werden, können die Daten einfach nicht mehr gelesen werden. ↩
genial, herzlichen Dank für die ausführlichen Infos!
Sowas habe ich gesucht:-).