Giter Club home page Giter Club logo

arduinofdc's Introduction

ArduinoFDC

ArduinoFDC Setup

ArduinoFDC is a sketch that implements a floppy disk controller. It works with Arduino Uno, Leonardo, Nano, Pro Mini, Micro and Mega.

ArduinoFDC consists of three parts:

  1. A library providing low-level functions to allow reading and writing disks at the sector level as well as low-level formatting disks.
  2. Integration of ChaN's brilliant FatFS library to provide file-level functions for reading and writing files and directories in a FAT (MS-DOS) file system and a high-level format function to initialize a FAT file system.
  3. An example sketch implementing ArduDOS, a (very) small DOS environment for browsing a FAT file system as well as a low-level disk monitor to access sector data on the disk, including the ability to transfer whole disks or single files via the XModem protocol.

ArduinoFDC works with double density (DD) as well as high density (HD) disk drives. It can read, write and format 5.25" DD (360KB), 5.25" HD (1.2MB), 3.5" DD (720KB) and 3.5" HD (1.44MB) disks.

Wiring:

The table below shows how to wire the Arduino pins to the 34-pin IDC connector on the floppy drive cable.

The pin numbers are defined at the top of the ArduinoFDC.cpp file. Some of them can easily be changed whereas others are hard-coded in the controller code. Refer to the comments at the top of the ArduinoFDC.cpp file if you want to use different pin assignments.

Floppy Cable Uno/Mini/Nano Leonardo/Micro Mega Notes Function
2 13 13/16 42 3,4,5 Density select
8 7 8 47 Index
10 4 5 51 1,3 Motor Enable A
12 A1 A1 40 1,3,4 Drive Select B
14 5 6 50 1,3 Drive Select A
16 A0 A0 41 1,3,4 Motor Enable B
18 3 3 52 3 Head Step Direction
20 2 2 53 3 Head Step Pulse
22 9 9 46 Write Data
24 10 10 45 Write Gate
26 11 11/14 44 3 Track 0
28 12 12/15 43 3,4 Write Protect
30 8 4 48 2 Read Data
32 6 7 49 3 Side Select
1,3,5,...,31,33 GND GND GND 6 Signal Ground

Note 1: The pin numbers for the SELECT/MOTOR signals assume you are wiring to the controller end of a floppy drive cable. If you are wiring directly to the floppy drive, the A/B pins will be reversed (search the web for "Floppy drive twist" for more information).

Note 2: It is highly recommended (but not entirely necessary) to add a 1k pull-up resistor to +5V to this signal. The Arduino's built-in pull-up resistors are very weak (20-50k) and may not pull the signal up quickly enough. Without the resistor you may encounter read errors (bad CRC, header not found), especially when reading HD disks. Whether it works without the resistor will depend on your specific drive, drive cable, connections and Arduino.

Note 3: This signal can easily be moved to a different pin on the Arduino by changing the corresponding #define PIN_XXX ... statement at the top of ArduinoFDC.cpp

Note 4: This signal is not essential for the functionality of the controller. The corresponding pin can be freed by commenting out the #define PIN_XXX ... statement at the top of ArduinoFDC.cpp

Note 5: See section "DENSITY control signal" below.

Note 6: You should be able to just pick one of the GND pins. However, some cables/drives do not actually connect all of these to ground. If your setup does not work it may be worth trying a different GND pin.

Supported disk/drive types

To properly read/write data, the library must be configured for the drive/disk combination that is being used. The drive type can be passed into the begin functions or set afterwards by calling the setDriveType function. Supported types are:

  • ArduinoFDC::DT_5_DD: Double-density disk in a 5.25" double-density drive
  • ArduinoFDC::DT_5_DDonHD: Double-density disk in a 5.25" high-density drive
  • ArduinoFDC::DT_5_HD: High-density disk in a 5.25" high-density drive
  • ArduinoFDC::DT_3_DD: Double-density disk in a 3.5" double- or high-density drive
  • ArduinoFDC::DT_3_HD: High-density disk in a 3.5" high-density drive

DENSITY control signal

The function of the DENSITY control signal line between the controller and the floppy drive is not well defined and varies between drives. Furthermore most drives can be configured by jumpers (also called "straps"). You may want to consult the documentation for your drive for details.

In their default configuration most 3.5" drives do not use this signal. The drive itself determines the type of disk (DD or HD) by the presence of a hole in the disk (on the opposite edge from the "write protect" hole). The controller must be configured separately for the correct type (DD or HD), otherwise reading/writing will fail.

For 5.25" HD drives this signal is generally an input from the controller to the drive. If the signal is LOW then low density mode is selected, otherwise high density is used. However, for some drives the opposite is true. Many drives can be configured via jumpers to select the expected levals.

The controller can be configured what to do with this signal by calling the "setDensityPinMode" function. The following modes are supported:

  • ArduinoFDC::DP_DISCONNECT: This configures the DENSITY pin as INPUT. It does not actually read the pin.
  • ArduinoFDC::DP_OUTPUT_LOW_FOR_HD: This configures the DENSITY pin as an OUTPUT and sets it LOW if the disk type is HD.
  • ArduinoFDC::DP_OUTPUT_LOW_FOR_DD: This configures the DENSITY pin as an OUTPUT and sets it LOW if the disk type is DD.

By default, the mode is set to DP_DISCONNECT for 3.5" drives and DP_OUTPUT_LOW_FOR_DD for 5.25" drives.

Another way to handle the DENSITY signal is to comment out the #define PIN_DENSITY line at the top of ArduinoFDC.cpp and hard-wire the DENSITY signal from the disk drive cable to the proper level (or leave it disconnected).

Library functions:

To use the low-level disk access library functions (listed below), copy ArduinoFDC.h and ArduinoFDC.cpp into your Arduino sketch directory and add #include "ArduinoFDC.h" to your sketch.

To use the FAT file system functions, additionally copy ff.h, ff.c, ffconf.h, diskio.h and diskio.cpp. Then add #include "ff.h" and #include "ArduinoFDC.h" to your sketch. For documentation of the FatFS functions refer to the FatFS documentation.

void ArduinoFDC.begin(driveAtype, driveBtype)

Initializes the Arduino pins used by the controller. For possible drive types see the "Supported disk/drive types" section above. If left out both types default to ArduinoFDC::DT_3_HD.

void ArduinoFDC.end()

Releases the pins initialized by ArduinoFDC.begin()

bool ArduinoFDC.selectDrive(byte drive)

Selects drive A (0) or B (1) to be used for subsequent calls to readSector/writeSector/formatDisk. Calling begin() selects drive A. Returns 'false' if trying to select drive 1 when the corresponding control pins are commented out in ArduinoFDC.cpp

byte ArduinoFDC.selectedDrive()

Returns which drive is currently selected, A (0) or B (1).

void ArduinoFDC.setDriveType(driveType)

Sets the disk/drive type for the currently selected drive. For possible drive types see the "Supported disk/drive types" section above.

byte ArduinoFDC.getDriveType(driveType)

Returns the drive type of the currently selected drive.

void ArduinoFDC.setDensityPinMode(mode)

Sets the function of the DENSITY pin for the currently selected drive. See section "Density control signal" above.

byte ArduinoFDC.numTracks()

Returns the number of tracks for the drive type of the currently selected drive.

byte ArduinoFDC.numSectors()

Returns the number of sectors per track for the drive type of the currently selected drive.

bool ArduinoFDC.haveDisk()

Returns true if a disk is in the drive. This is done by looking for the index hole. If the drive motor is not currently running this haveDisk() will temporarily turn it on.

bool ArduinoFDC.isWriteProtected()

Returns true if the disk is write protected. If no disk is in the drive then the result may be either true or false. If the WRITE PROTECT signal is not connected then the result is always false.

void ArduinoFDC.motorOn()

Turns the disk drive motor on.

The readSector/writeSector/formatDisk functions will turn the motor on and back off automatically if it is not already running. Note that turning on the motor also includes a one second delay to allow it to spin up. If you are reading/writing multiple sectors you may want to use the motorOn and motorOff functions to manually turn the motor on and off.

void ArduinoFDC.motorOff()

Turns the disk drive motor off.

bool ArduinoFDC.motorRunning()

Returns true if the disk drive motor is currently running and false if not.

byte ArduinoFDC.readSector(byte track, byte side, byte sector, byte *buffer)

Reads data from a sector from the flopy disk. Always reads a full sector (512 bytes).

  • The "track" parameter must be in range 0..(numTracks()-1)
  • The "side" parameter must either be 0 or 1
  • The "sector" paramter must be in range 1..numSectors()
  • The "buffer" parameter must be a pointer to a byte array of size (at least) 516 bytes.

The function returns 0 if reading succeeded. Otherwise an error code is returned (see Troubleshooting section below)

IMPORTANT: On successful return, the sector data that was read will be in buffer[1..512] (NOT buffer[0..511])

byte ArduinoFDC.writeSector(byte track, byte side, byte sector, byte *buffer, bool verify)

Writes data to a sector on the floppy disk. Always writes a full sector (512 bytes).

  • The "track" parameter must be in range 0..(numTracks()-1)
  • The "side" parameter must either be 0 or 1
  • The "sector" paramter must be in range 1..numSectors()
  • The "buffer" parameter must be a pointer to a byte array of size (at least) 516 bytes.
  • If the "verify" parameter is true, the data written will be read back and compared to what was written. If a difference is detected then the function will return false. If the "verify" parameter is false then no verification is done. The function may still return false if the proper sector location on disk can not be found before writing.

The function returns 0 if writing succeeded. Otherwise an error code is returned (see Troubleshooting section below)

IMPORTANT: The sector data to be written must be in buffer[1..512] (NOT buffer[0..511])

bool ArduinoFDC.formatDisk(byte *buffer, byte from_track=0, byte to_track=255)

Formats a floppy disk according to the format specified by the "setDriveType()" function. A subset of tracks can be formatted by specifying the from_track and to_track parameters.

A buffer of size at least 144 bytes is needed to store temporary data during formatting. The buffer is passed in as an argument to allow re-using other buffers in your sketch. If you do not have a buffer to be re-used, just declare byte buffer[144] before calling formatDisk().

This function does not set up any file system on the disk. It only sets up the low-level sector structure that allows reading and writing of sectors (and fills all sector data with 0xF6 bytes).

The function returns 0 if formatting succeeded. Otherwise an error code is returned (see Troubleshooting section below). Note that no verification of the formatted disk is performed. The only possible error conditions are missing track 0 or index hole signals. You can use the readSectorfunction to verify that data can be read properly after formatting.

ArduDOS

ArduDOS is a minimal DOS that allows the user to browse the file system on the disk and read/write files. The basic functionality is modeled on MS-DOS with some exceptions:

  1. All commands operate only on the currently selected drive. If two drives are connected then use "b:" or "a:" to switch drives.
  2. The working directory is always the top-level directory of the disk. No "cd" command is available to change the directory. Therefore, all paths given as arguments to commands must be relative to the top-level directory.
  3. Disk changes are not automatically detected. After changing a disk, re-select the current drive (e.g. "a:") to notify ArduDOS of the change.

ArduDOS is easy to access from either Arduio's serial monitor or any other serial terminal. Set the monitor or terminal's baud rate to 115200 before connecting. The following commands are available:

  • dir [directory]
    Show the listing of the specified directory (default is root directory).
  • type filename
    Type out the specified file to the screen (best for text files).
  • dump filename
    Dump the specified file to the screen in hexadecimal notation (best for binary files).
  • write filename
    Receive text line-by-line from the user and write it to the specified file. Enter an empty line to finish.
  • del filename
    Delete the specified file.
  • mkdir dirname
    Create the specified directory.
  • rmdir dirname
    Remove the specified directory.
  • disktype 0/1/2/3/4
    Set the drive type of the current drive, where 0/1/2/3/4 stands for the drive type as listed (in the same order) in section "Supported disk/drive types" above.
  • format [/q]
    Low-level format a disk and initialize a FAT file system. If /q argument is given, performs a quick format, i.e. only resets the file system without low-level format.
  • monitor
    Enter the low-level disk monitor (see the "Low-level disk monitor" section below).
  • send filename (only available if #define USE_XMODEM is enabled at the top of ArduinoFDC.ino)
    Send the specified file via XModem protocol. See the "XModem" section below for more details.
  • receive filename (only available if #define USE_XMODEM is enabled at the top of ArduinoFDC.ino)
    Receive the specified file via XModem protocol. See the "XModem" section below for more details.

ArduDOS session

Low-level disk monitor

Like ArduDOS, the low-level monitor is easy to use with the Arduino serial monitor. When using ArduDOS (i.e. #define USE_ARDUDOS is enabled at the top of ArduinoFDC.ino), use the "monitor" command to enter the low-level monitor.

If ArduDOS is not enabled then the sketch drops directly into the disk monitor mode. Set Arduino's serial monitor to 115200 baud to connect.

When running, the monitor will show a command prompt. Enter your command in the serial monitor's input line and press Enter to execute the command.

The following commands are supported:

  • r track, sector[,side]
    Read the sector specified by track/sector/side, copy its contents to an internal buffer and show the buffer content. If the side parameter is left out it defaults to zero.
  • w track, sector[,side]
    Write the current buffer contents to the sector specified by track/sector/side and verify the data after writing. Shows "Ok" or "Error" status after execution. If the side parameter is left out it defaults to zero.
  • f
    Low-level format the disk. No file system is initialized, all sectors are filled with 0xF6. To format and/or add a file system use the "format" command in ArduDOS (see ArduDOS section above).
  • b
    Show the current buffer content
  • B [n]
    Fill the buffer with value n. If n is left out then fill the buffer with bytes 0,1,2,...255,0,1,2,...255.
  • m [0/1]
    Turn the motor of the currently selected drive off/on. If the 0/1 parameter is left out then the current motor status is shown.
  • r
    Read ALL sectors on the disk and show status Ok/Error for each one.
  • w [0/1]
    Write the current buffer content to ALL sectors on the disk. If the 0/1 parameter is 1 then verify every sector after writing it (significantly slower). If the 0/1 parameter is left out it defaults to 0.
  • s [0/1]
    Select drive A (0) or B (1). If the 0/1 parameter is left out then the currently selected drive is shown.
  • t 0/1/2/3/4
    Set the drive type of the current drive, where 0/1/2/3/4 stands for the drive type as listed (in the same order) in section "Supported disk/drive types" above.
  • S (only available if #define USE_XMODEM is enabled at the top of ArduinoFDC.ino)
    Read all sectors of the current disk and transmit them via XModem protocol. See the "XModem" section below for more details.
  • R (only available if #define USE_XMODEM is enabled at the top of ArduinoFDC.ino)
    Receive a disk image via XModem and write it to the current disk. See the "XModem" section below for more details.
  • x (only if the monitor is entered from ArduDOS via the "monitor" command)
    Exit the monitor and return to ArduDOS.

XModem

Both ArduDOS and the low-level monitor can transmit and receive data via the XModem protocol. If you want to use this functionality, first un-comment the #define USE_XMODEM setting at the top of file ArduinoFDC.ino and re-upload the sketch.

Use a terminal program that supports XModem to send/receive the data. I recommend TeraTerm. First start the transfer on the controller then initiate the XModem send/receive function in the terminal program.

Note that no error messages can be displayed during the XModem transfers since the transfer takes place over the same serial connection as the terminal. If the transfer stops prematurely and nothing is shown in the terminal, pressing ENTER will get the command prompt back.

Troubleshooting

The following table lists the error codes returned by the readSector, writeSector and formatDisk functions including possible causes for each error. Pin numbers refer to pins on the Arduino UNO.

# Code Meaning Possible causes
0 S_OK No error, the operation succeeded
1 S_NOTINIT The ArduinoFDC.begin() function has not been called
2 S_NOTREADY No data at all is received from the disk drive - no disk in drive
- drive does not have power
- pins MOTOR (4/12), SELECT (5/13), READ (8), INDEX (7) or GND not properly connected
3 S_NOSYNC Data is received but no sync mark can be found - disk not formatted or not formatted for the correct density
- GND pin not properly connected
4 S_NOHEADER Sync marks are found but either no sector header or no header with the expected track/side/sector markings - pins STEP (2), STEPDIR (3), SIDE (6) or GND not properly connected
- bad disk or unknown format
- misaligned disk drive
- invalid track, sector or head number given
5 S_INVALIDID The data record was not started by a 0xFB byte as expected - bad disk or unknown format
6 S_CRC The sector data checksum is incorrect - bad disk or unknown format
- pullup resistors too weak (see note 2 in wiring section)
7 S_NOTRACK0 When trying to move the read head to track 0, the TRACK0 signal was not seen, even after stepping more than 80 tracks. - pins STEP (2), STEPDIR (3), SELECT (5/13), TRACK0 (11) or GND not properly connected
- drive does not have power
8 S_VERIFY When reading back data that was just written, the data did not match - pins WRITEGATE (10) or WRITEDATA (9) not properly connected
- disk is write protected and WRITEPROTECT (12) pin is not connected
- bad disk
9 S_READONLY Attempting to write to a write-protected disk - disk is write protected

Acknowledgements

The ArduDOS functionality would not have been possible without ChaN's brilliant FatFS library.

The XModem communication uses the arduino-xmodem code available at https://code.google.com/archive/p/arduino-xmodem.

arduinofdc's People

Contributors

dhansel avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.