64net/2, nie mehr Disketten

Allgemeines

Wie 64HDD ist auch 64net eine Alterrnative zur 1541 und Konsorten. Der grosser Vorteil, das Programm läuft auf einer Vielzahl von Systemen, einzigste Voraussetzung auch hier, ein Parallelport. Für mich war entscheidend dass 64net unter Linux läuft. Doch mit der aktuellen Version 0.9.0 hatte ich Anlaufschwierigkeiten, der Transfer stockte oft. Der Client war eine Routine der den Kernel ins RAM kopierte und modifizierte. Dabei wurde jedoch massiv in den Kernal eingegriffen. Nicht ganz optimal. Also setzte ich mich mit dem Autor in Verbindung und setzte das Protokoll zwischen C64 und 64net komplett neu auf. Mittlerweile gibt es im CVS eine Version mit wesentlich stabilerem Transfer. Die Änderungen im Kernal wurden soweit reduziert dass eigentlich nur noch die sendbyte und getbyte Routinen für den seriellen Bus Änderungen enthalten. Für besseren Durchsatz wurden jedoch auch die Load und Saveroutine ergänzt. Gerade im Gegensatz zur 64HDD wird der Vorteil deutlich: Auch beim Laden von Directories sind die Ladezeiten extrem verkürzt und auch das Speichern erfolgt mit Parallelübertragung. Momentan sind bei Nutzung von Hardwarehandshaking maximale Datenraten von ca. 25kb/s erreichbar (inkl. Laden/Speichern unter ROM). Durch das Ändern der zentralen Routinen sendbyte/getbyte werden auch Programme wie der TurboAssembler, die nicht die Kernal Load-/Saveroutinen verwenden, unterstützt.

Das Übertragungsprotokoll

Da die Übertragung auf sehr niedrigem Level stattfindet müssen wir uns lediglich über die Übertragung einzelner Bytes, sowie Fehler- und ATN-Signalisierung Gedanken machen. Da der Server auf einem Multitaskingsystem läuft muss zudem eine asynchrone Übertragung möglich sein. Dies wird durch ein gegenseitiges Handshaking (Request/Acknowledge) realisiert. Der Userport bietet hierzu freundlicherweise alles was man hierzu benötigt. Die ATN Leitung des seriellen Bus kann hier direkt abgegriffen werden. Für die Daten sind 8 bidirektionale Ports (PB0-PB7) vorhanden. Handshaking zum PC geschieht über PA2 ($dd00, Bit 2), die Gegenrichtung über FLAG2 ($dd0d, Bit 4). Eine Fehlerübermittlung ist nur in eine Richtung nötig (Vom PC zum C64). Hier bietet das serielle Schieberegister eine gute Möglichkeit. In einem Fehlerfall können wir hier mit nur zwei weiteren Leitungen (SP2, CNT2) ein ganzes Byte übertragen dass dann schon den fertigen Fehlercode im Register $dd0c repräsentiert. Wie findet nun eine Übertragung eines Bytes im Detail statt? Sourcecode erklärt hier wohl wieder am besten:

getbyte
        lda #$00
        sta $dd03 ;Datenrichtungsregister für PB0-PB7 auf Input setzen

        lda $dd0d ;Warten bis Daten verfügbar sind
        bne *-3

        ldx $dd01 ;Daten lesen

        lda $dd00 ;Acknowledge senden durch Umdrehen des Status von PA2
        eor #$04
        sta $dd00

        txa
        rts

sendbyte
        tax
        lda $dd0d ;Warten bis PC empfangsbereit
        bne *-3

        lda #$ff
        sta $dd03 ;Datenrichtungsregister für PB0-PB7 auf Output setzen

        stx $dd01 ;Daten auf Bus setzen

        lda $dd00 ;Signalisieren das gültige Daten auf Bus sind
        eor #$04
        sta $dd00
        rts

In dieser Anordnung kann man mit diesem Code auch Hardwarehandshaking betreiben. Immer wenn ein Portzugriff auf $dd01 geschieht (stx $dd01, ldx $dd01) wird der Pegel an Pin PC2 für einen Taktzyklus low. Einerseits kann man damit auf PC Seite einen Interrupt triggern, was sich aber vor allem mit dem Userleveltreiber ppdev als unzuverlässlich, bzw. nicht funktionabel, erwiesen hat. Die bessere Variante ist es ein J/K-Flipflop wie etwa den 7473 in das Kabel zwischen PC und C64 zu integrieren. Damit lässt sich das kurze Signal an PC2 in ein Signal umwandeln das pro Strobe seinen Zustand zwischen low und hi wechselt, so wie wir es bereits mit PA2 simulieren. Dadurch wird das Setzen von PA2 überflüssig, pro übertragenes Byte werden als 10 Taktzyklen auf C64-Seite gespart, was sich in einer wesentlich höheren Übertragungsrate niederschreibt (ohne Flipflop ~16kb/s, mit Flipflop ~25kb/s). Ein zusätzlicher Vorteil ist, dass sich auf der PC-Seite nichts am Code ändert.
PinFunktionSkizze
1CKClock-Eingang Flipflop 174LS73
1CLRClear-Eingang Flopflop 1
1KK-Eingang Flipflop 1
VccBetriebsspannung: +5V
2CKClock-Eingang Flipflop 2
2CLRClear-Eingang Flipflop 2
2JJ-Eingang Flipflop 2
1JJ-Eingang Flipflop 1
1QInvertierter Ausgang Flipflop 1
1QAusgang Flipflop 1
GNDMasse
2KK-Eingang Flipflop 2
2QAusgang Flipflop 2
2QInvertierter Ausgang Flipflop 2
Pinbelegung des 74LS73 J/K-Flipflops
flipflop_cable Das 64net/2 Kabel mit Flipflop ist wie links zu sehen beschaltet. Das Flipflop wird vom Userport mit Strom versorgt. Der Strobes liefernde Ausgang PC2 dient dabei als Clock für das 1. Flopflop, das zweite Flipflop bleibt unbenutzt. Ein 10kOhm Pullup-Widerstand sorgt dabei für einen hohen Level solange PC2 kein Strobe liefert. Der 1CLR-Eingang wird mit +5V verbunden, ansonsten würde das Flipflop immer im zurückgesetzten Zustand verbleiben. Ebenso wird der Eingang 1K und 1J mit +5V versorgt, so dass diese Eingänge immer auf 1 gesetzt sind. Laut Wahrheitstabelle für das J/K-Flipflop erfolgt ein Toggle, sobald am CLK-Eingang ein Übergang von 1 auf 0 erfolgt und J und K dabei auf 1 gesetzt sind. Mit dieser Schaltung haben wir nun also einen Ausgang Q geschaffen, der bei jedem eigehenden Strobe von PC2 den Zustand wechselt, eben so, wie wir es zuvor mit PA2 simulieren mussten.