Adafruit has an Arduino library & example code ready to go with this FeatherWing. The library is optimized for the Adafruit Feather RP2040 microcontroller board.

This library needs to be installed using the Arduino Library Manager. From the Arduino “Sketch” menu, select “Include Library” then “Manage Libraries…”.

Type “floppy” in the search field to quickly find the library — Adafruit_Floppy:

If prompted to install additional libraries, say "yes"; Adafruit_Floppy relies on Adafruit BusIO and SdFat - Adafruit Fork.

You have to make specific selections in the Tools menu:

  • Board: "Adafruit Feather RP2040"
  • CPU Speed: "200 MHz (Overclock)"
  • Optimize: "Optimize Even More (-O3)"
  • USB Stack: "Adafruit TinyUSB"

After restarting the Arduino software, you should see a new example folder called Adafruit_Floppy, and inside, an example called floppy_capture_track_test. Upload the sketch to your Arduino and open the serial monitor. Place a disk in your floppy drive, and reset the board. Your floppy should "spin up" and you should see information about the flux data on your floppy's "track zero". For a formatted floppy, the "flux bins" (a histogram of times between adacent flux transitions) should cluster preferentially into 3 to 4 different groups of values with large gaps between them. For example, here's the frequency information from an MFM-formatted (DOS) floppy. The peaks correspond to 4, 6, and 8µs, or 96, 144, and 192 counts at 24MHz:

[12:22:39] its time for a nice floppy transfer!
[12:22:39] Sample freqency 24.00MHz
[12:22:40] Waiting for index pulse...Found!
[12:22:40] Seeking track...Going to track 0
[12:22:40] Going to track 0
[12:22:40] done!           
[12:22:40] Captured 45282 flux transitions
[12:22:40] -------
[12:22:40] 93: 130
[12:22:40] 94: 1460
[12:22:40] 95: 6257
[12:22:40] 96: 13469
[12:22:40] 97: 10962
[12:22:40] 98: 3345
[12:22:40] 99: 836
[12:22:40] 100: 302
[12:22:40] -------
[12:22:40] 139: 122
[12:22:40] 140: 273
[12:22:40] 141: 464
[12:22:40] 142: 848
[12:22:40] 143: 1083
[12:22:40] 144: 1258
[12:22:40] 145: 1265
[12:22:40] 146: 1098
[12:22:40] 147: 700
[12:22:40] 148: 296
[12:22:40] -------
[12:22:40] 192: 115
[12:22:40] 193: 122
[12:22:40] 194: 142
[12:22:40] 195: 111
[12:22:40] 196: 111
[12:22:40] Ready? No
[12:22:40] Write Protected? Yes
[12:22:40] Track 0? Yes

Because the floppy is inherently an analog device, the exact counts in each flux bin will vary slightly from run to run.

MFM (DOS/Windows) Floppy Decoding

There are a lot of floppy formats, but one ubiquitous one at the end of the floppy era was the IBM PC compatible MFM floppy. The example "mfm_test" will decode the content of such a floppy disk and display it on the serial monitor in hex and ASCII.

Seeking track 8 head 1
Going to track 8

Captured 9 sectors
Validity: VVVVVVVVV
00000000 65 76 65 72 61 6c 20 6c 6f 77 65 72 20 63 6f 75 | everal lower cou
00000010 72 74 20 6f 70 69 6e 69 6f 6e 73 2c 20 69 6e 63 | rt opinions, inc
00000020 6c 75 64 69 6e 67 20 0d 0a 74 68 65 20 6f 70 69 | luding   the opi
00000030 6e 69 6f 6e 73 20 69 6e 20 41 6d 65 72 61 64 61 | nions in Amerada
00000040 20 48 65 73 73 20 61 6e 64 20 4c 54 56 20 53 65 |  Hess and LTV Se
00000050 63 75 72 69 74 69 65 73 20 74 68 61 74 20 61 72 | curities that ar
00000060 65 20 73 6f 20 0d 0a 66 72 65 71 75 65 6e 74 6c | e so   frequentl
00000070 79 20 63 69 74 65 64 20 69 6e 20 73 75 70 70 6f | y cited in suppo
00000080 72 74 20 6f 66 20 74 68 65 20 62 72 6f 61 64 65 | rt of the broade
00000090 72 20 73 63 6f 70 65 20 66 6f 72 20 74 68 65 20 | r scope for the
000000a0 0d 0a 70 72 69 76 69 6c 65 67 65 2e 18 11 31 31 |   privilege.  11
000000b0 32 18 20 20 54 68 65 72 65 20 69 73 20 6e 6f 20 | 2   There is no
000000c0 63 61 75 74 69 6f 6e 20 74 68 61 74 20 74 68 65 | caution that the
000000d0 20 6c 61 6e 67 75 61 67 65 20 71 75 6f 74 65 64 |  language quoted
000000e0 20 66 72 6f 6d 20 0d 0a 41 6d 65 72 61 64 61 20 |  from   Amerada
000000f0 48 65 73 73 20 6d 61 79 20 62 65 20 6e 6f 20 6d | Hess may be no m

For full details of the Adafruit Floppy library, see the API documentation. Here are some key details, though:

Pins & Construction

There are a lot of pins, so we put a standard definition block at the top of the examples for you to cut & paste into your code:

// these are for Adafruit Feather RP2040
#define DENSITY_PIN A1 // IDC 2
#define INDEX_PIN 25   // IDC 8
#define SELECT_PIN A0  // IDC 12
#define MOTOR_PIN A2   // IDC 16
#define DIR_PIN A3     // IDC 18
#define STEP_PIN 24    // IDC 20
#define WRDATA_PIN 13  // IDC 22
#define WRGATE_PIN 12  // IDC 24
#define TRK0_PIN 10    // IDC 26
#define PROT_PIN 11    // IDC 28
#define READ_PIN 9     // IDC 30
#define SIDE_PIN 8     // IDC 32
#define READY_PIN 7    // IDC 34

Adafruit_Floppy floppy(DENSITY_PIN, INDEX_PIN, SELECT_PIN,
                       MOTOR_PIN, DIR_PIN, STEP_PIN,
                       WRDATA_PIN, WRGATE_PIN, TRK0_PIN,
                       PROT_PIN, READ_PIN, SIDE_PIN, READY_PIN);

Usually, you'll start with the sequence: begin, select, spin_motor, and goto_track:

if (!floppy.begin()) {
    Serial.println("Failed to initialize floppy interface");
    while (1) yield();
  }

  floppy.select(true);
  if (! floppy.spin_motor(true)) {
    Serial.println("Failed to spin up motor & find index pulse");
    while (1) yield();
  }

  Serial.print("Seeking track...");
  if (! floppy.goto_track(0)) {
    Serial.println("Failed to seek to track");
    while (1) yield();
  }

Grabbing raw flux data

You can capture flux data to an array:

// outside any function
// WARNING! there are 150K max flux pulses per track!
uint8_t flux_transitions[MAX_FLUX_PULSE_PER_TRACK];

// inside loop() or other function
int32_t index_pulse_offset;
uint32_t captured_flux = floppy.capture_track(flux_transitions, sizeof(flux_transitions), &index_pulse_offset, true);

Decoding MFM flux data

Or use an Adafruit_MFM_Floppy object to get block-level access to a MFM-formatted floppy disk:

// outside any function, after defining floppy object
Adafruit_Floppy floppy(DENSITY_PIN, INDEX_PIN, SELECT_PIN,
                       MOTOR_PIN, DIR_PIN, STEP_PIN,
                       WRDATA_PIN, WRGATE_PIN, TRK0_PIN,
                       PROT_PIN, READ_PIN, SIDE_PIN, READY_PIN);

// You can select IBMPC1440K or IBMPC360K (check adafruit_floppy_disk_t options!)
Adafruit_MFM_Floppy mfm_floppy(&floppy, IBMPC360K);

// in loop() or other function
int32_t captured_sectors = mfm_floppy.readTrack(track, head);
// then access mfm_floppy.track_validity, mfm_floppy.track_data, and other fields

This guide was first published on Feb 28, 2023. It was last updated on May 19, 2024.

This page (Using Arduino adafruit_floppy) was last updated on Mar 08, 2024.

Text editor powered by tinymce.