In other words, finding a more creative use for the Arduino Mega than a neon clock: to be able to read and write all sorts of old data storage media and send’em over USB, blending old technology with new.
Originally inspired by the ArduinoFDC project, I have decided to try a different approach: instead of using the Arduino to talk to a floppy drive directly, why not leave the hard work on a chip that can be salvaged from an old PC?
A Seagate SCSI hard disk drive card with a DP8473V-based floppy controller.
The same controller can be found on certain Adaptec cards, too.
And I surely learned a thing or two during the process 🙂
I did originally try out ArduinoFDC on a Uno board, and it worked just fine with a 3.5″ drive, but encountered timing/CRC errors and reliability issues trying to work with older, 5 1/4″ media, especially during experiments with the IBM 5150 or PCjr – and it can be a pain trying to transfer old floppies with these old machines.
So instead of having an Arduino bit-banging the I/O pins of an old drive directly, I made a prototype board with a proper, PC-compatible FDC such as the DP8473 pictured above, wired to a Mega2560. With this setup, the Arduino board acts as an interface to the FDC – with a keyboard and display, basic disk operations and commands can be launched standalone, without needing a computer or terminal connected. Having a dedicated FDC chip with its own PLL and data discriminator, the reliability of disk transfers increased dramatically whilst the circuit is still kept simple – by itself, it is just a datasheet “typical application” of the controller, just with its address lines wired to the Arduino. In addition, custom disk geometries can be defined and stored to the EEPROM to auto-load them upon startup – up to 4 drives are supported on one controller – and I have also added some experimental 8″ filesystem support to work with SSSD CP/M disks.
PCB design by Michal Dvořáček
The LCD is a 128×64 ST7920. Originally came as a “RepRapDiscount Full Graphic Smart Controller” interface from a former 3D printer setup.
Others will work fine using Oli Kraus’ u8g2 library
Fired up the ol x-ray for a comparison: genuine NSC (left) vs counterfeit (right).
Notice the smaller outline in chip die and imprecise leads alignment.
Weight difference 2.82g vs 2.72g
Apologies for the scratch mark and the uneven contrast. First time developing a film! 🙂
With the increased RAM capabilities of the Mega compared to the Uno (8K vs 2K), multi-sector operations can be done in one go. The RAM is still not enough to load whole tracks at once, but with a 3K disk buffer I have managed to cut down time required to image a 1.44MB disk from 10 minutes (with ArduinoFDC doing single sector operations) to around 3 minutes 40 seconds.
In IMD mode with a PS/2 floppy drive and an OLED display
This circuit will work with any PC compatible FDC, as the communication protocol between the Arduino and FDC is NEC uPD765 software compatible. A DP8473V was chosen by me just because I had a couple of these chips in my spare parts collection (as I had an Adaptec ISA card with a non-functioning one, ready to be switched). In addition, these chips were found for cheap on a certain “Far Eastern” website and are most likely to be counterfeit – nevertheless, they work fine on all the 8-inch, 5 1/4 inch and 3 1/2 inch drives I have lying around 🙂
Inside the source code, or the config header to be precise, the optional accessories (display, keyboard, configuration switches etc) can be configured to use a different pinout on the Mega2560 board. The only interface whose pins can not be configured, is the FDC itself – this is because working with the address lines is time sensitive, there’s no DMA in the Arduino to handle the data transfer as soon as it is ready, and the wiring order of all 8 bits of data lines must correspond to bits of one single AVR port access, using direct port manipulation.
Schematic of the whole setup for all supported data rates using a DP8473 FDC.
Others (with 8 data and 3 address lines) can be used too, e.g. the Intel 82077AA, NSC PC8477 etc.
The 2nd pinheader for drives C: and D: is optional, in addition to the RS-232 nullmodem interface, PS/2 keyboard input, display and TG43/DENSEL jumpers, these are all optional.
Code and PCBs available on my GitHub repository.
As mentioned above, the circuit can communicate via display and keyboard, utilizing the serial interface only to send over disk images or files from the floppy, or via the serial interface exclusively, i.e. including the command prompt and setup. This can be done either through the USB port of the Mega2560, or through a simple level shifter with a null-modem serial cable: this option will not trigger a reset once the serial connection has been established.
Directory listing left: FAT-formatted disk, right: 250K 8″ CP/M floppy (FM encoding)
During boot, the controller is initialized to check if it responds to a Reset/Sense interrupt command, and after successful completion, up to 4 drives can be configured either in the “simple” mode (using predefined disk media geometries), or in the “advanced” mode, where the setup will ask for all supported parameters. Optional CP/M filesystem support is turned on if selecting an 8″ drive with a 26x128byte geometry; pin 2 of the FDD bus can be configured to act as a TG43 line, to decrease write current past this track if wished.
FAT12 filesystem support can be turned on if using 512 bytes per sector – it is on by default in all predefined geometries. As of now, simple read and write of files, and directory traversal, is possible on FAT, utilizing Elm-Chan’s FATFS library, and my own simple CP/M implementation to read and erase files off an 8″, 250K floppy.
Going through a few basic commands on a FAT-formatted floppy
The supported commands are quite “DOS-like” and self explanatory – HELP is used to invoke and give short details of each supported command. RESET can be used to reset and reconfigure settings of a particular drive – or the whole board, reinvoking setup for all.
DRIVPARM shows drive and disk media parameters of chosen drive; PERSIST makes them persistent into the EEPROM so they can be loaded upon boot-up without reconfiguring.
FORMAT and VERIFY do what they are told, according to the currently configured disk geometry. If formatting with a FAT12 or CP/M filesystem, format with verify is automatically invoked. Tracks containing bad sectors, if any, are printed out, but there is no “bad sector table” written to the disk.
IMAGE is used to create a disk image that can be sent over USB or serial link via XMODEM, or vice versa – written to the floppy using currently set disk geometry. XMODEM-1K packets are used where available, and if enabled with Yes.
During IMAGE transfer, any potential bad sectors are filled with zeros and the operation is continued whenever possible – an improvement over the original ArduinoFDC. Plus, if using the keyboard and display interface, the offending sector information is logged during the serial transfer onto the display.
Advanced setup of drive A:
Up to 4 drives can be configured, if connected.
If filesystem support is turned on, QFORMAT can be used to “quick format” – recreate the root directory in a FAT or a CP/M filesystem (the disk must be formatted before). DIR will display the contents of a specified directory, or of the current working directory. TYPE types out text contents of a file, DEL erases a file, XFER performs single-file transfer over the serial link, either read or write (as opposed to IMAGE, which works on the whole disk).
On FAT12, CD can be used to nest into subdirectories, or to show the current working directory; absolute paths in command line arguments are not supported due to memory constraints. MD and RD are equivalents of MKDIR and RMDIR. PROMPTPATH is used to either display drive letter only in the prompt (for small displays), or the whole path by default. Finally, TYPEINTO creates a simple text file from the keyboard input.
Making the first prototype board
Even though there’s multi drive support, and certain commands can work with differently configured drives (e.g. RESET B:, DRIVPARM C:, FORMAT D: etc), due to tight memory constraints of an Arduino, all of the file commands work in the current drive/current working directory only, and there are no advanced commands such as COPY, MOVE, DELTREE, or support for wildcards in names. As an example, to copy a file from A:\DOS\AUTOEXEC.BAT to drive B:, the XFER AUTOEXEC.BAT command is invoked first to transfer the file over serial link, then the drive is switched to B: and XFER AUTOEXEC.BAT is called again, this time to receive and write it to disk. Gimme more than 8K of RAM and I’ll do stuff. 🙂
It wouldn’t be a prototype if there was not some kind of patching involved
And that’s about the size of it – a portable floppy controller in a box, with some basic and some advanced functionality that allow you to pop a 3, 5 or 8 inch drive through USB and have both read and write support on a today’s machine. Yes, it’s not one thing fits all and there are limitations, just as with anything in life. 🙂
The following disk drives, media and geometries were tested to work with this setup, read and write:
8″, FM, 250K (77x26x128B), single sided, CP/M 2.2 filesystem; 250K data rate, 500K transfer rate;
the following 8 inchers are hangovers from 8FORMAT experiments 🙂
8″, MFM, 77x9x512B, one and two sides, FAT12;
8″, MFM, 1.2M (77x16x512B), FAT12;
5.25″, 160K, 180K (8spt, 9spt single sided), 320K, 360K (8spt, 9spt double sided), 1.2M, FAT12 each,
5.25″ double-density media in a high density drive (300K data rate),
3.5″ 720K and 1.44MB (9 and 18spt double sided),
3.5″ 2.88MB (36spt double sided, extended density) PS/2 drives work too!
Four floppy drives in use, from left to right: 8″, 5.25″ DD, 5.25 HD, 3.5″ HD
Here’s an example of some known, non-standard geometries that can be used with MegaFDC – applied by pressing Esc during drive type setting. You can use the PERSIST command to store these configurations into the EEPROM:
5.25″ 410K DD (in a DD drive): double-stepping No, disk-change signal No, 41 tracks, 2 heads, 10 sectors, 512B each, 07 sector gap, 0E format gap, F6 format fill byte, MFM data, 250kbps rate, no perpendicular recording, use FAT12 Yes, media descriptor FD, 112 rootdir entries, 1024B clusters.
This configuration can be used for known good double-density disks to squeeze 50K more on them. If in an HD drive, use 300kbps rate and Yes when asked for double-stepping.
3.5″ 820K DD: double-stepping No, disk-change signal Yes, 82 tracks, 2 heads, 10 sectors, 512B each, 07 sector gap, 0E format gap, F6 format fill byte, MFM data, 250kbps rate, no perpendicular recording, use FAT12 Yes, media descriptor F9, 112 root directory entries, 1024B clusters.
3.5″ 1.68MB HD: double-stepping No, disk-change signal Yes, 80 tracks, 2 heads, 21 sectors, 512B each, 07 sector gap, 0D format gap, F6 format fill byte, MFM data, 500kbps rate, no perpendicular recording, use FAT12 Yes, media descriptor F0, 224 root directory entries, 512B clusters.
3.5″ 1.72MB HD: Same as 1.68MB, just with 82 tracks.
DMF (Windows Distributed Media Format): Same as 1.68MB, just with 16 root directory entries and a 1024B cluster size (DMF 1024).
3.5″ 3.12MB ED: double-stepping No, disk-change signal Yes, 82 tracks, 2 heads, 39 sectors, 512B each, 10 sector gap, 28 format gap, F6 format fill byte, MFM data, 1Mbps rate, perpendicular recording Yes, use FAT12 Yes, media descriptor F0, 240 root directory entries, 1024B clusters.
In conjunction with a PS/2 2.88MB drive setup, this geometry can be used to extend the ED floppy to over 3 megabytes. As an experiment, MegaFDC will also format a known-good regular 1.44MB HD floppy to this capacity.
Example interface with 8″, 5.25″ and 3.5″ drives with serial data transfer
could this be interfaced to a Z80 bus, as a full fdc , for 8 bit computers ?!
Why would you do that? If you have hardware knowledge of your platform and know how to code, you can already program the FDC chip with your Z80 directly (with some TTL glue logic involved). Of course you could use the source code of MegaFDC as an inspiration to see how the communication between the CPU and the FDC is done.
But to answer your question, yes, it can be done. Experiment!
Hello!
It would be nice to add support for reading and writing TR-DOS disks for the ZX Spectrum.
The source code repository is public, feel free to experiment!
Unfortunately, I’m a lousy programmer. 🙂