USB-Floppy

Frage: Kann man 5¼″-Laufwerke an USB anschließen? Oder gar 8″?

Fertigprodukte

Es gibt folgendes, was die Eigenentwicklung nicht lohnt: Für 5¼″ scheint es da nichts zu geben.

Bastelei

Einen urtümlichen Floppy-Controllerchip wie WD1772 oder U8272 zu benutzen, um die seriellen MFM-Daten zu generieren oder auszulesen erscheint unsportlich. Geht das nicht mit den heutigen Rechenleistungen von 8-Bit-Controllern mit USB auch ohne?

Hier ist MFM und der Sektoraufbau erklärt, ich habe das mal in ein handliches CHM gepackt.

Diskettenlaufwerke liefern und erwarten negative Impulse pro Flusswechsel. Über die Pulsbreite konnte ich keine Info finden; wahrscheinlich so dass TTL-Schaltkreise sicher ansprechen, also deutlich kürzer als 1 µs.

Und so sollte es aussehen:

    |        0xA1 mit Sync          |       0xA1 ohne Sync          |       Daten
  0 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 | 1 Datenbits
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
 _____         _____    *    _____     _______       ___     _____     ___     
/     \_______/     \_______/     \___/       \_____/   \___/     \___/   \___/ Magnetfluss
   ___   _____   ___   _____   ___   _   _____   ___   _   _   ___   _   _   _	       __ __
\_/   \_/     \_/   \_/     \_/   \_/ \_/     \_/   \_/ \_/ \_/   \_/ \_/ \_/ \	Signal RD/WD
       1½      2     1½      2     1½  1       2     1½  1   1     1½  1   1	Zeiten
       01      01    0       00    01  1       01    0   0   0     01  1   1	Generierte Bits
 0      1       1    0        0     1  1        0    0   0   0      1  1   1	Merkbit T

Voruntersuchungen

Software

Als erstes wurde untersucht, ob der Diskettencontroller mit seiner MFM-Schreib- und Lesefunktion überhaupt in Software realisierbar ist. Dies ist für DD und HD locker möglich, und auch ED ist realisierbar. Immerhin passt ein typischer Diskettensektor in den RAM des ATmega32U4. Daher muss man die Daten nicht strömen lassen. Vorerst.

Andere Kodierungsformate wie GCR (Apple) lassen sich im Gegensatz zu einem Hardware-Diskettencontroller einfach per Software nachrüsten.

Um während des Sektorlesens den vorher gelesenen Sektor in 64-Byte-Stückelung zum USB zu schaffen, ist eine entsprechende Routine erforderlich, die maximal 16 Takte dauert. Da CALL und RET viel zu langsam sind, nur mit Sprüngen.

Der USB-Teil des ATmega32U4 ist sichtlich nicht AVR-typisch und die Dokumentation im Datenblatt unter aller Kanone: Derzeitige Quelle

Vorhandene Hardware

Es stand ein Delock-USB-Diskettenlaufwerk (3½″ HD) zur Verfügung. Dieses Diskettenlaufwerk verwendet das veraltete CBI-Protokoll (CBI = Control-Bulk-Interrupt). Das bedeutet, der SCSI-Steuerblock (6, 10 oder 12 Byte) wird über den Control-Endpoint 0 zum Gerät gesendet. Die Antwort, Zusatzdaten oder Sektordaten flutschen über den jeweiligen Bulk-Endpoint (hier i2 und o2), und am Ende gibt's eine 2-Byte-Quittung über den Interrupt-Endpoint (hier i1), bestehend aus SCSI-Fehlerkode „Sense“ und dem „Additional Sense Code“ ASC.

Ein Eigenbau-Diskettenlaufwerk mit CBI-Protokoll erfordert (zumindest unter Windows 7) eine eigene .INF-Datei zur Installation und ist damit nicht gerade benutzerfreundlich. Im Falle des o.a. Funktionsmusters findet Windows die Vendor- und Product-ID (0x3EE = Mitsumi, 0x6901 = USB-Diskettenlaufwerk) in einer vorinstallierten INF-Datei und lädt usbstor.sys. Man müsste daher bei Eigenbauten jene Vendor- und Product-ID wiederverwenden, um keine INF-Datei mitliefern zu müssen. (Auf welchem Medium? Auf Diskette — das geht nicht!)

Stellt man die Firmware auf das von Microsoft empfohlene Bulk-Only-Protokoll um, lädt Windows den Treiber usbstor.sys auf generischer Basis mit Hilfe der USB-Klasse. Daher verwenden auch die im Internet herumgeisternden Kodebeispiele zum Thema Massenspeicher allesamt das Bulk-Only-Protokoll. Hier wird der SCSI-Steuerblock mit einem 15-Byte-Rahmen versehen und über den gleichen Bulk-Out-Endpoint versendet wie auch die Schreibdaten. Sowohl die Lesedaten als auch der SCSI-Status werden über den Bulk-In-Endpoint in den PC eingelesen, wobei der Status aus einem 9-Byte-Block besteht. Bei Fehlern wird der Bulk-In-Endpoint im Stall-Modus angehalten.

Anschlüsse

Anschlussbelegung des „Pro Micro“ (18) inklusive Portadressen und Zusatzfunktionen; zum Vergleich „Arduino Micro“ (24), Teensy 2.0 (24), ATmega32U4 (26 Portpins), eHajo-Board (26)
Als erstes ist mir, wie vielen anderen Leidgeplagten auch, die Micro-USB-Buchse davongeflogen. Das Problem ist nicht die Buchse sondern die schlechte Qualität der (blauen) Leiterplatte: Die Kupferfolie klebt zu schlecht für die hohe Belastung beim Einstecken und Ausziehen. Ein Kabelschwänzchen angelötet, nun geht erst mal die Platine zu verwenden. Den hier unnützen 3,3-V-Festspannungsregler und einige C's habe ich gleich mit heruntergelötet, vielleicht brauche ich die später für ein anderes Projekt.

Die Diode am USB-Anschluss muss drauf bleiben, damit nicht das eingeschaltete Diskettenlaufwerk über dortige Pullup-Widerstände den ausgeschalteten PC versucht zu speisen. Das Laufwerk oder die Laufwerke werden selbstverständlich nicht vom USB gespeist. Hierfür ist ein eigenes Netzteil (5 V und 12 V) notwendig. Die alten Laufwerke sind viel zu stromhungrig, als dass man die Leistung einem USB-Anschluss antun sollte. Nur der Mikrocontroller wird vom PC gespeist.

Direkt angelötetes USB-Kabel
Die Anschlüsse wurden so verteilt, dass: Für die Lesedaten ist ein externer Pullup-Widerstand von bspw. 4,7 kΩ erforderlich. Der im Chip integrierte ist mit seinen rund 40 kΩ zu groß für die schnellen Impulse.
 
Adapterplatine vom „Pro Micro“ auf zwei Floppy-Buchsen
12 I/Os werden minimal für 1 Laufwerk benötigt. An das o.a. Board passen insgesamt vier Diskettenlaufwerke sowie 1 Bandlaufwerk (Streamer, hier: QIC-80) dran.

Der ATmega32U4 hat eine unintuitive Portpinverteilung. Dazu kommt das Chaos, was Arduino&Co angestiftet hat. Hier noch mal nach Ports sortiert:

Port B Port C Port D Port E Port F
BitA#R.Anschluss BitA#R.Anschluss BitA#R.Anschluss BitA#R.Anschluss BitA#R.Anschluss
PB0-A(LED D1) PC0- PD0/OC0B3AWD PE0- PF0kein Anschluss
PB115AMotor2 PC1- PD12AMotor3 PE1- PF1kein Anschluss
PB216ETK0 PC2- PD2RxDADS3 PE2kein Anschluss PF2-
PB314ASTP PC3- PD3TxDEIDX PE3- PF3-
PB48EWP PC4- PD4/ICP14ERD PE4- PF4A3AMotor0
PB59EDC PC5- PD5-A(LED D3) PE5- PF5A2ADS1
PB610ASS PC65ADS2 PD6kein Anschluss PE67AWG PF6A1ADS0
PB7kein Anschluss PC7kein Anschluss PD76ADIR PE7- PF7A0AMotor1
Wie man sieht, es überwiegen die Ausgänge.
Es ist fraglich, ob vier Laufwerke an einem Hosenträgerkabel vernünftig (d.h. ohne Reflexionen am Kabelende) laufen. 500 kBit/s sind nämlich schon recht flott. Alles „ohne Anschluss“ (also auf dem Board nicht herausgeführt) muss zur Vermeidung von verbotenen Eingangszuständen entweder als Ausgang oder als Eingang mit aktivem Pullup programmiert werden. Da in Wirklichkeit nahezu alle Laufwerkssignale invertiert sind, habe ich die Negationsstriche hier weggelassen.

Und so sieht in etwa ein Adapterboard aus. Links werden die Laufwerke mit DS2 und DS3 angeschlossen, rechts die mit DS0 und DS1. Jeweils mit einem „gedrehten“ Floppykabel. Das Bandlaufwerk kann irgendwo zusätzlich angeschlossen werden. Egal ob vor oder nach der Drehung.

 
Einseitiger Leiterplattenentwurf. Es werden nur 3 Drahtbrücken benötigt. In die Mitte kommt das „Pro Micro“ mit dem USB-Anschluss nach oben
Extra große Pads vereinfachen das Selbermachen. Die Platinenabmessungen sind 46 × 64 mm².

USB-Features aus PC-Sicht

Die Firmware könnte oder kann: Was die Firmware nicht kann: Oder vielleicht später doch noch?