Schlagwort: amiga

Erster Release

So nun ist es soweit, ich entlasse die erste einigermaßen brauchbare Version meines Amiga Disketten Lese und Schreib Programms „ADF-Copy“ in die Wildnis unter der GNU Public License v3. D.h. jeder darfs benutzen, weiter entwickeln und kopieren solange die Copyright Informationen erhalten bleiben und darauf hingewiesen wird das eine Weiterentwicklung auf meinem Werk beruht. Ebenso müssen Weiterentwicklungen daraus auch unter der GPLv3 lizensiert werden.

Hier der Download:

ADF-Copy_v0.8

Ist alles noch recht Beta und hat kaum Fehlerabfragen, wenn ihr also eurer Superseltenes Retro Game überschreibt weil ihr den Writeprotect Nupsi vergessen habt und das falsche klickt, nicht mein Fehler McFly! ;)

Zur Hardware

Das ganze lässt sich auf einem Steckbrett mit ein paar Strippen aufbauen. Ansonsten kann man auch anhand der Pin Definitionen im Sourcecode des Arduino Sketches arbeiten.

 

Pinout_small

Als Bauteile werden benötigt:

  • Teensy 3.2 – ganz wichtig das es die 3.2 Version ist, denn nur diese ist 5V tolerant!
  • ein Micro USB Kabel, denn beim Teensy wird keines mitgeliefert.
  • ein Steckbrett, das kleine aus dem Conrad Weihnachtskalender reicht vollkommen aus.
  • 14 Steckbrettkabel mittlerer Länge mit Male/Female, es reicht wenn ein Masse Pin der Floppy mit dem Teensy verbunden ist. Im Layout sind alle verbunden weil man das eben so macht. :)
  • von einem alten Netzteil ein Kabel mit Floppy Stromstecker, man muss nur Masse an Schwarz und 5V an Rot anlegen, die gelbe 12V Strippe wird nicht benötigt.
  • ein 5V Netzteil für die Stromversorgung der Floppy was mindestens 1A liefert, wenn der Steppermotor loslegt zieht der kurz 0,7A und wenn die Spannung zusammenbricht kommt die Floppy durcheinander und Steppt in die falsche Richtung (Schon erlebt und Stunden nach dem Fehler gesucht)

Über USB reicht der Strom leider nicht für die Floppy, naja, man kann nicht alles haben.

Über Feedback würde ich mich freuen und ansonsten: Have fun and keep the Amiga alive!

kleines Update

Da der Schreibmodus nun funktioniert habe ich nun auch Verify eingebaut, nach dem Schreiben eines Track wird dieser gelesen und mit den zu schreibenden Daten verglichen, bei Unterschieden oder schlimmeren wird der Track nochmal geschrieben und geprüft, maximal 10 Mal, falls es dann immer noch nicht geklappt hat bricht der Schreibvorgang ab. So eine Diskette sollte man besser entsorgen.

Das Frontend hab ich grafisch auch überholt und etwas hübscher und kompakter gestaltet, aber seht selbst.

frontend02

Funzt :)

Da der Schreibmodus mittlerweile funktioniert und auf dem trockenen schwimmen keinen Spass macht hab ich mal meinen Amiga 4000 aufgebaut, einige Disketten geschrieben und am lebenden Objekt getestet. Da ich ja auch ein Diagnoseprogramm brauchte hab ich mit dem Amiga Emulator (WinUAE) ein ADF erstellt und dort das Programm DiskSalv4 von Dave Haynie aufgespielt, dann mit meinem ADF Writer auf eine Disk geschrieben und in den Amiga geworfen.

Die Diskette hat der Amiga mit seinem 20 Jahre alten Laufwerk ohne murren gelesen :)

Mit Hilfe von Disksalv hab ich dann einige andere Disketten die ich geschrieben hatte überprüft, lies sich alles ohne Probleme lesen, kein einziger Retry bei einem Track, ich bin zufrieden.

Einzig HD Disketten die ich als DD beschrieben hatte waren teilweise unlesbar, ich hatte natürlich das HD Loch abgeklebt. Ich hab dann mal so eine Diskette mit zugeklebten Loch mit meinem ADF Writer beschrieben, und siehe da, einwandfrei lesbar. Scheinbar verhält sich das Floppy Laufwerk unterschiedlich wenn das HD Loch zu oder offen ist, aber wenn man das weiß kann man darauf achten.

Jetzt gehts daran das Frontend auf dem PC etwas aufzuhübschen und Nutzerfreundlicher zu machen, und vielleicht Verify einzubauen :)

Spannung ist spannend…

Gestern lief alles und heute geht nichts mehr. Beim Lesen und Schreiben fing der Schreib/Lese Kopf einfach mittendrin an in die falsche Richtung zu wandern, d.h. wenn er einen Track richtung Innen fahren sollte fuhr er einen Schritt richtung Außen, oder bewegte sich mehrere Schritte anstatt einem, wtf?

Nach stundenlanger Suche nach Timing Problemen bei der Ansteuerung des Schrittmotors, oder ob mir irgendwas in die Serielle Kommunikation spuckt fiel mir ein das ich das Netzteil für die Floppy über Nacht angelassen hatte und kontrollierte mal die Spannung. Ich hatte es auf 5V eingestellt, nun zeigte es 4,96V an, sollte eigentlich kein Problem sein… oder? Die Spannung wird über ein Poti eingestellt, ist halt ein billiges Labornetzteil, wird wohl das Poti über Nacht etwas gedriftet sein wegen Wärme, Wetter oder einer Fischschwarmwanderung im Pazifik. Hab es dann auf 5,01V gestellt und hossa, keine Probleme mehr!

Das Laufwerk scheint eine echte Diva zu sein das 0,05V soviel ausmachen. Meine Vermutung mittlerweile ist das das billige Labornetzteil kurz in der Spannung einknickt wenn der Schrittmotor einen Step macht, laut Datasheet eines Samsung Laufwerks zieht sowas 0,7A, und das es mit den 0,05V Unterschied dann genau unterhalb der zulässigen Grenze sinkt. Nun steht es auf 5,2V, das sollte genug Luft sein.

 

Frontend für den PC

 

Nachdem es nun eine Wochen ruhig waren hier ein weiteres Update, ich war ja nicht untätig, nur zu faul zum bloggen ;)frontend01

Da ich mich irgendwie mit keiner IDE für C++ anfreunden konnte und ich unter Windows eigentlich noch nie was mit C++ und GUI gemacht habe hab ich zu Processing 3.0 gegriffen, damit hatte ich schon mal ein Frontend für ein Projekt geschrieben und Erfahrungen gesammelt. Processing ist ein Java Dialekt mit kompletter IDE, vielen Grafikbefehlen und einer großen Library Base. Ich bin zwar kein JAVA Spezialist, aber passt schon, Google ist mein Freund, und während meines Studiums hatte ich viel mit Modula zu tun und irgendwie sind sich ja alle Imperativen Programmiersprachen sehr ähnlich :)

Das Interface brauch noch ein bischen Liebe, aber für erste Ergebnisse reichts.

  • „getName“ liest den Volumename der Diskette
  • „Save As“ öffnet einen Requester um den Speicherort und Namen festzulegen
  • „Dump“ liest von Start Track bis End Track eine Amigadisk ein und speichert sie als .adf
  • „Abort“ bricht den Lesevorgang ab.
  • „Read“ liest einen Track und zeigt im Infofenster an wieviel Sektoren gefunden wurden, ist noch zu Debugzwecken drinne
  • Im Infofenster wird angezeigt bei welchem Track gerade gelesen wird, Fehler usw.

Unten wird die Häufung der Transitionen angezeigt, je heller desto mehr, hier kann man sehen das die Transitionen in der Regel etwas kürzer sind, bzw. die alte Flinte ganz schön streut. Ob ich da irgendwo einen Rechenfehler gemacht habe, sodaß die Transitionen oft kürzer als die Norm sind, keine Ahnung, vielleicht kümmer ich mich später nochmal darum. Man sieht hier auch viele Streubits, ich vermute das das Murks aus dem Trackgap ist.

Die Einstufung der Transitionen mache ich momentan wie folgt:

  • unter 1,5µs wird verworfen
  • 1,51µs bis 4,83µs ist eine ’10‘
  • 4,84µs bis 6,70µs ist eine ‚100‘
  • 6,71µs bis 8,58µs ist eine ‚1000‘
  • alles darüber wird verworfen

Die magenta Linien im Graph zeigen an das mehrere Leseversuche nötig waren um den Track zu lesen, ich prüfe ob ein Track 11 Sektoren enthält, dann ob die beiden Checksummen stimmen. Wenn etwas davon nicht stimmt wird der Track nochmal gelesen. Maximal macht der Mikrocontroller bisher 10 Versuche einen Track zu lesen, wenn der 10te auch fehlschlägt wird der Track so übertragen wie er ist und dem Frontend gemeldet in welchen Sektoren welche Checksummen nicht stimmen.

Wie man sieht ist diese Diskette ziemlich an der Grenze und besitzt schon einige Weak Tracks, wurde aber noch „korrekt“ ausgelesen. Da die Checksummen aus den MFM Daten per XOR generiert werden können sich hier natürlich Fehler einschleichen die nicht erkannt werden, von daher ist das „korrekt“ mit Vorsicht zu geniessen. Auf DOS Ebene gibt es noch mehr Checksummen, aber viele Spiele benutzen gar keine Filesystemfunktionen sondern benutzen das Trackdisk.device direkt. Damals gab es Kopierschutzverfahren die die Checksummen absichtlich falsch geschrieben haben, in den ungenutzten 16 Bytes im Header Informationen speicherten oder sonstwie am Header manipuliert haben, ein normales Copytool oder die Workbench konnte so eine Disk nicht kopieren. Ebenso gab es Spiele die ein andere Syncword benutzten, Sachen in die Trackgap schrieben, in GCR codiert waren, Laserlock benutzten, Track 80-82 benutzten usw., es gab ne Menge was sie machen konnten um die Piraten auf Abstand zu halten. Irgendwann wurde alles irgendwie geknackt, aber nicht jeder Normalo konnte mal eben ein Spiel im Laden kaufen und zig Kopien an seine Freunde auf dem Schulhof verteilen.

Aber ich will eh kein Kopierprogramm für geschützte Software schreiben sondern nur für Disketten die ohne Kopierschutz daher kommen, selbst nach 20 Jahren könnte das Eis dünn sein auf dem man sich da bewegt da es in Deutschland ja mittlerweile Strafbar ist einen Kopierschutz zu umgehen. Das war die subtile Maßnahme unserer Regierung das Recht auf Privatkopie im Urhebergesetz  § 53 Absatz 1 Satz 1 auszuhebeln ohne es anzufassen. Sie haben einfach ein neues geschaffen was die Umgehung technischer Schutzmaßnahmen §§ 95a ff. UrhG (DE) unter Strafe stellt. Allerdings lässt sich über die Formulierung „Wirksame technische Maßnahmen“ streiten :) Naja, sie treiben die Kohle ja eh über GEMA und ZPÜ ein, darüber kann man sich aber auch den Mund fusselig reden wenn man für die Digicam eine SD-Karte kauft und ZPÜ abdrücken muss weil man damit ja Urheberrechtlich geschütztes Material kopieren könnte, auf wiedersehen Unschuldsverdacht. :P

Spielkrams

Mittlerweile hab ich in mein Programm noch ein paar Features eingebaut, unter anderem eine Analyse des Timings der Transitionen auf dem gerade gelesenen Track, so etwas sieht dann in der Ascii Ausgabe so aus:

Transitions: 47166 Real Bits: 110011
0.25:0-146+
1.83:38-1
2.33:50-1
3.58:80-3
3.63:81-11
3.67:82-75
3.71:83-1134++++++++
3.75:84-5063+++++++++++++++++++++++++++++++++++++++
3.79:85-8495++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3.83:86-8020++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3.88:87-5470++++++++++++++++++++++++++++++++++++++++++
3.92:88-2809+++++++++++++++++++++
3.96:89-1693+++++++++++++
4.00:90-749+++++
4.04:91-360++
4.08:92-60
4.13:93-4
5.38:123-3
5.42:124-18
5.46:125-105
5.50:126-288++
5.54:127-638++++
5.58:128-1097++++++++
5.63:129-1500+++++++++++
5.67:130-1788+++++++++++++
5.71:131-1662++++++++++++
5.75:132-1343++++++++++
5.79:133-1066++++++++
5.83:134-624++++
5.88:135-389+++
5.92:136-179+
5.96:137-52
6.00:138-7
6.04:139-2
7.38:171-3
7.42:172-20
7.46:173-65
7.50:174-102
7.54:175-211+
7.58:176-271++
7.63:177-395+++
7.67:178-413+++
7.71:179-326++
7.75:180-260++
7.79:181-202+
7.83:182-118
7.88:183-61
7.92:184-11
7.96:185-1
8.42:196-1
OK

Wo die 146 Transitionen mit einer länge von 0,25µs herkommen hab ich keine Ahnung, kommen vielleicht aus dem Trackgap weil da in der Regel nur Müll steht bzw. die Diskette dort nicht formatiert ist, soll mir aber egal sein, ich werte nur Transitionen aus die länger als 1,5µs sind ;)
Da der Controller des Amiga mit maximal 500kbit/s arbeitet besitzt er eh nur eine Auflösung von 2µs, würde sowas also überhaupt nicht mitbekommen, bzw. falls er auch Filter vorgeschaltet hat sowas als Leitungsrauschen wegfiltern.

 

Erste Versuche mit dem Teensy 3.2

adf_01
Versuchsaufbau

So sieht der Versuchsaufbau mit dem Teensy aus, ich konnte die Floppy direkt mit einem Steckbrett und ein paar Dingsdakabeln verdrahten, keine lästigen Spannungsteiler oder Levelshifter da der Teensy 3.2 direkt TTL Pegel auf den Eingängen frisst.

#define _redwc 2     //2 density select IN 
#define _index 3     //8 index OUT
#define _drivesel 4  //12 drive select 1 IN
#define _motor 5     //16 motor1 on IN
#define _dir 6       //18 direction IN
#define _step 7      //20 step IN
#define _writedata 8 //22 write data IN
#define _writeen 9   //24 write enable IN
#define _track0 10   //26 track 0 OUT
#define _wprot 11    //28 write protect OUT
#define _readdata 22 //30 read data OUT (FTM0)
#define _side 14     //32 head select IN
#define _ready 15    //34 ready / disk change OUT

Die ganzen Floppy Pins gehen von oben nach unten an die Pins vom Teensy, bis auf die Read Data Leitung, die habe ich nach Studium des Datenblatt an GPIO 22 gelegt, dieser GPIO lässt sich nämlich als Input Capture Trigger für das FlexTimer Module 0 benutzen.

Der FTM0 ist ein 16 Bit Timer der mit maximal Bus Clock läuft, Bus Clock ist beim Teensy der halbe Coreclock, da ich auf 96 MHz takte sind das 48 MHz. Über den Prescaler halbiere ich den Takt nochmal auf 24 MHz, d.h. alle 41,6 Nanosekunden zählt der Timer einen Schritt hoch. Für den Eingang habe ich noch einen Filter im Timer eingestellt sodaß das Signal am Input Trigger für mindestens 12 Taktzyklen Busclock (250ns) stabil sein muss damit es erkannt wird. Wird nun über den GPIO 22, welches der Input Capture Trigger für FlexTimer Modul 0 ist, ein Flankenwechsel (in meinem Falle Falling Edge) detektiert findet folgendes statt:

  • der Inhalt des Counters (FTM0_CNT) wird in ein extra Register (FTM0_C0V) kopiert
  • der Interrupt Vector (ftm0_isr) des FTM0 wird angesprungen
  • die von mir geschriebene Interruptroutine setzt den Counter auf Null
  • der Inhalt des Registers FTM0_C0V wird ausgewertet wie lang die Transition dauerte, 4,6 oder 8 µs
  • entsprechende schreibe ich in eine Puffervariable eine ’10‘, ‚100‘ oder ‚1000‘, ich benutze dafür ein Longword (32bit) in dem ich die Bits sammel und wenn ich 8 Bit oder mehr komplett habe schreibe ich sie in den Steambuffer.
  • On the Fly prüfe ich ob das Longword den Inhalt 0xA4489448 enthält, das ist nämlich der Anfang des Syncwords eine Amiga Sektors und kann ensprechend dem Stream entsprechend ausrichten das genau ein Byte anfängt. Ebenso vermerke ich in einer Tabelle einen Pointer auf den Sektoranfang im Speicher, das macht das decodieren später einfacher.
  • wenn der Streambuffer voll ist oder ich 11 Sektoren gefunden habe schalte ich die Interrupt Generierung aus.
  • der Interrupt benötigt etwa 0,9 µs pro Transition, d.h. sie ist lange fertig bevor die nächste Transition kommt (4µs oder länger)

Währenddessen wartet meine Hauptroutine nur darauf das der Lesevorgang beendet ist und startet danach die decodierung des Tracks.

Der ganze Spass läuft mittlerweile recht zuverlässig, hat zwar bisher kaum Fehlerüberprüfungen aber spuckt erste brauchbare Ergebnisse aus:

Reading Track 0
Sectors start at: 172, 2067, 3155, 4243, 5331, 6419, 7507, 8595, 9683, 10771, 11859
Decode took 1631
Sectors found: 11 Errors found: 0
OK
Format Type: 255 Track: 0 Sector: 0 NumSec2Gap: 3 Data Chk: 4410155 Header Chk: 0
44 4F 53 00 C0 20 0F 19 00 00 03 70 43 FA 00 18 4E AE FF A0 4A 80 67 0A 20 40 20 68 00 16 70 00 DOS.. .....pC...N...J.g. @ h..p.
4E 75 70 FF 60 FA 64 6F 73 2E 6C 69 62 72 61 72 79 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 Nup.`.dos.library...............
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................................

Oben sieht man den Bootsektor einer Amiga Diskette, in den ersten vier Bytes steht „DOS“,0 für eine normale Diskette, dann folgt eine kurze Assemblerroutine die über die dos.library den Boot der Disk startet.

Lesegerät für Amiga Floppies

Da ich letztens mal wieder meinen Amiga aktiviert habe kam mir die Idee mal ein paar Daten vom meine Amiga Disketten zu retten. Ich hatte damals ein paar Sachen programmiert, Unterlagen aus meiner Studienzeit und so weiter. Prinzipiell gibts da ja verschiedene Möglichkeiten, aber ich fand es interessant mit einem Handelsüblichen PC Laufwerk und einem Mikrocontroller Amiga Disketten zu lesen, und später vielleicht auch zu schreiben.

Es gibt halb kommerzielle Produkte dafür zu kaufen, z.B. das KryoFlux, das kost so um die 100€, aber irgendwie macht das selber bauen mehr Spass. Und wenn ich sehe wie voll die Platine des KryoFlux ist, denke ich mir das geht einfacher mit modernen Microcontrollern, man muss nur den richtigen finden.

Im Netz findet man einige Informationen zum Interface von Floppy Laufwerken, dem Shugart Bus, der Bus arbeitet mit TTL Pegeln, also 0-5V. Da ich aber Sachen besser begreife wenn ich sie „sehe“ hab ich mal meinen Logikanalysator an den Floppy Port des Amiga gehangen und eine Diskette formatiert:

logik01

In der Grafik hab ich leider die Signale WD (Write Data) und WE (Write Enable) verkehrt bezeichnet. Hier sieht man schön wie die Signale zusammenspielen. Mit einem kurzen Impuls auf /STEP wird zur nächsten Spur gesprungen. Quasi gleichzeitig wird die Seite der Floppy eingestellt auf der gearbeitet werden soll, das wird vom Ready Signal jeweils kurz quittiert. Nach einer gewissen Zeit wird dann wd (WE) auf low gezogen um einen schreibzugriff einzuleiten. Daraufhin wird eine Seite geschrieben we (WD), dann die Seite (SIDE) gewechselt und diese dann geschrieben. Später werden dann beide Seiten eingelesen und verglichen ob der Schreibzugriff fehlerfrei war.

Gut, das Schreiben ist mir erstmal egal, wichtig ist die Grundlagen wie MFM codierung und die Ansteuerung des Laufwerks zu programmieren.

 

Da die Informationen auf einer Floppy und anderen Magnetischen Medien durch eine änderung der Magnetisierungsrichtung gespeichert werden kann man da nicht einfach Nullen und Einsen raufschreiben. Der Floppy Controller würde irgendwann den Takt verlieren wenn zuviele Nullen oder Einsen hintereinander kommen. Deshalb wird die Information durch unterschiedliche Abstände zwischen der änderung der Magnetisierung gespeichert.logik02 Hier sieht man drei Unterschiedliche lange Abstände: 8 µs, 6 µs und 4 µs. Bei einer HD Floppy mit 1,440MB wären das 2,3,4 µs Abstände. Da der Amiga aber in der Regel nur DD Floppylaufwerke verbaut hatte interessiert mich nur DD Disketten zu lesen.