So you’ve built the hardware! What now?
Connecting it up
In order to do anything useful, you have to plug it in to a floppy disk drive (or two).
Plug the motherboard end of your floppy disk cable into the FluxEngine.
The red stripe goes on the right. The lower set of holes connect to the board. (Pin 2 of the connector needs to connect to pin 2.7 on the board.)
If you’re using header pins, the upper row of holes in the connector should overhang the edge of the board. If you’re using a floppy drive motherboard connector, you’re golden, of course (unless you have one of those annoying unkeyed cables, or have accidentally soldered the connector on in the wrong place — don’t laugh, I’ve done it.)
Plug the drive end of your floppy disk cable into the drive (or drives).
Floppy disk cables typically have two pairs of floppy disk drive connectors with a twist between them. (Each pair has one connector for a 3.5” drive and a different one for a 5.25” drive.) (Some cables are cheap and just have the 3.5” connectors. Some are very cheap and have a single 3.5” connector, after the twist.)
FluxEngine uses, sadly, non-standard disk numbering (there are reasons). Drive 0 is the one nearest the motherboard; that is, before the twist. Drive 1 is the one at the end of the cable; that is, after the twist. Drive 0 is the default. If you only have one drive, remember to plug the drive into the connector before the twist. (Or use
-s :d=1to select drive 1 when working with disks.)
Important. Make sure that no disk you care about is in the drive. (Because if your wiring is wrong and a disk is inserted, you’ll corrupt it.)
Connect the floppy drive to power. Nothing should happen. If you’ve connected something in backwards, you’ll see the drive light up, the motor start, and if you didn’t take the disk out, one track has just been wiped. If this happens, check your wiring.
Connect the FluxEngine to your PC via USB — using the little socket on the board, not the big programmer plug.
Insert a scratch disk and do
fluxengine rpmfrom the shell. The motor should work and it’ll tell you that the disk is spinning at about 300 rpm for a 3.5” disk, or 360 rpm for a 5.25” disk. If it doesn’t, please get in touch.
fluxengine testbulktransportfrom the shell. It’ll measure your USB bandwidth. Ideally you should be getting above 900kB/s. FluxEngine needs about 850kB/s, so if you’re getting less than this, try a different USB port.
Insert a standard PC formatted floppy disk into the drive (probably a good idea to remove the old disk first). Then do
fluxengine read ibm. It should read the disk, emitting copious diagnostics, and spit out an
ibm.imgfile containing the decoded disk image (either 1440kB or 720kB depending).
I’m sorry to say that the client program is very badly documented — it’s
moving too quickly for the documentation to keep up. It does respond to
help depending on context. There are some common properties,
Source and destination specifiers
When reading from or writing to a disk (or a file pretending to be a disk),
-d) options to tell FluxEngine
which bits of the disk you want to access. These use a common syntax:
fluxengine read ibm -s fakedisk.flux:t=0-79:s=0
To access a real disk, leave out the filename (so
To access only some tracks, use the
t=modifier. To access only some sides, use the
s=modifier. To change drives, use
Inside a modifier, you can use a comma separated list of ranges. So
When specifying a range, you can also specify the step. For example,
:t=0-79x2would be used when accessing a 40-track disk with double stepping.
To read from drive 1 instead of drive 0, use
To read from a set of KryoFlux stream files, specify the path to the directory containing the files with a trailing slash; so
some/files/:t=0-10. There must be a files for a single disk only in the directory.
Source and destination specifiers work entirely in physical units. FluxEngine is intended to be connected to an 80 (or 82) track double sided drive, and these are the units used. If the format you’re trying to access lays out its tracks differently, then you’ll need a specifier which tells FluxEngine how to find those tracks. See the 40-track disk example above.
If you don’t specify a modifier, you’ll get the default, which should be sensible for the command you’re using.
Important note: FluxEngine always uses zero-based units (even if the *disk format says otherwise).
High density disks
High density disks use a different magnetic medium to low and double density
disks, and have different magnetic properties. 3.5” drives can usually
autodetect what kind of medium is inserted into the drive based on the hole
in the disk casing, but 5.25” drives can’t. As a result, you need to
explicitly tell FluxEngine on the command line whether you’re using a high
density disk or not with the
If you don’t do this, your disks may not read correctly and will certainly
fail to write correctly.
You can distinguish high density 5.25” floppies from the presence of a traction ring around the hole in the middle of the disk; if the ring is not present, the disk is probably high density. However, this isn’t always the case, and reading the disk label is much more reliable.
The FluxEngine client software is a largely undocumented set of small tools.
You’ll have to play with them. They all support
--help. They’re not
installed anywhere and after building you’ll find them in the
fluxengine erase: wipes (all or part of) a disk — erases it without writing a pulsetrain.
fluxengine inspect: dumps the raw pulsetrain / bitstream to stdout. Mainly useful for debugging.
fluxengine read*: reads various formats of disk. See the per-format documentation linked from the table above. These all take an optional
--write-fluxoption which will cause the raw flux to be written to the specified file.
fluxengine write*: writes various formats of disk. Again, see the per-format documentation above.
fluxengine writeflux: writes raw flux files. This is much less useful than you might think: you can’t write flux files read from a disk to another disk. (See the FAQ for more information.) It’s mainly useful for flux files synthesised by the other
fluxengine writetestpattern: writes regular pulses (at a configurable interval) to the disk. Useful for testing drive jitter, erasing disks in a more secure fashion, or simply debugging. Goes well with
fluxengine rpm: measures the RPM of the drive (requires a disk in the drive). Mainly useful for testing.
fluxengine seek: moves the head. Mainly useful for finding out whether your drive can seek to track 82. (Mine can’t.)
fluxengine testbulktransport: measures your USB throughput. You need about 600kB/s for FluxEngine to work. You don’t need a disk in the drive for this one.
fluxengine upgradefluxfile: occasionally I need to upgrade the flux file format in a non-backwards-compatible way; this tool will upgrade flux files to the new format.
Commands which normally take
--dest get a sensible default if
fluxengine read ibm on its own will read drive 0 and
Supplied with FluxEngine, but not part of FluxEngine, are some little tools I wrote to do useful things. These are built alongside FluxEngine.
brother120tool: extracts files from a 120kB Brother filesystem image.
cwftoflux: converts (one flavour of) CatWeasel flux file into a FluxEngine flux file.
The recommended workflow
So you’ve just received, say, a huge pile of old Brother word processor disks containing valuable historical data, and you want to read them.
Typically I do this:
$ fluxengine read brother -s :d=0 -o brother.img --write-flux=brother.flux
This will read the disk in drive 0 and write out a filesystem image. It’ll also copy the flux to brother.flux. If I then need to tweak the settings, I can rerun the decode without having to physically touch the disk like this:
$ fluxengine read brother -s brother.flux -o brother.img
Apart from being drastically faster, this avoids touching the (potentially physically fragile) disk.
If the disk is particularly dodgy, you can force FluxEngine not to retry
failed reads with
--retries=0. This reduces head movement. This is not
recommended. Floppy disks are inherently unreliable, and the occasional bit
error is perfectly normal; FluxEngine will retry and the sector will read
fine next time. If you prevent retries, then not only do you get bad sectors
in the resulting image, but the flux file itself contains the bad read, so
attempting a decode of it will just reproduce the same bad data.
See also the troubleshooting page for more information about reading dubious disks.