Skip to content

Commit

Permalink
floppsy works! properly serves a 1.44MB disk image to a Pentium III c…
Browse files Browse the repository at this point in the history
…ompaq
  • Loading branch information
jepler committed Nov 12, 2024
1 parent bfeea43 commit c7ce752
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 30 deletions.
108 changes: 78 additions & 30 deletions examples/mfm_emu/mfm_emu.ino
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#define READY_PIN 14 // IDC 34
#elif defined(ARDUINO_ADAFRUIT_FLOPPSY_RP2040)
// Yay built in pin definitions!
#define NEOPIXEL_PIN PIN_NEOPIXEL
#else
#error "Please set up pin definitions!"
#endif
Expand All @@ -61,7 +62,14 @@
#define NEOPIXEL_FORMAT NEO_GRB + NEO_KHZ800
#endif

Adafruit_NeoPixel strip(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip(NEOPIXEL_COUNT, NEOPIXEL_PIN, NEOPIXEL_FORMAT);

#define STATUS_RGB(r,g,b) do { \
strip.fill(strip.Color(r,g,b)); \
strip.show(); \
} while(0)
#else
#define STATUS_RGB(r,g,b) do {} while(0)
#endif

#include "drive.pio.h"
Expand Down Expand Up @@ -176,11 +184,11 @@ struct floppy_format_info_t {
};

const struct floppy_format_info_t format_info[] = {
{40, 9, 2000, 100000}, // 5.25" 360kB, 300RPM
{80, 15, 1000, 167000}, // 5.25" 1200kB, 360RPM

{80, 9, 2000, 100000}, // 3.5" 720kB, 300RPM
{80, 18, 1000, 200000}, // 3.5" 1440kB, 300RPM
{80, 9, 2000, 100000}, // 3.5" 720kB, 300RPM

{80, 15, 1000, 167000}, // 5.25" 1200kB, 360RPM
{40, 9, 2000, 100000}, // 5.25" 360kB, 300RPM
};

const floppy_format_info_t *cur_format = &format_info[0];
Expand Down Expand Up @@ -239,13 +247,24 @@ void openNextImage() {
#endif

void setup() {
#if defined(FLOPPY_DIRECTION_PIN)
pinMode(FLOPPY_DIRECTION_PIN, OUTPUT);
digitalWrite(FLOPPY_DIRECTION_PIN, LOW); // we are emulating a floppy
#endif
#if defined(FLOPPY_ENABLE_PIN)
pinMode(FLOPPY_ENABLE_PIN, OUTPUT);
digitalWrite(FLOPPY_ENABLE_PIN, LOW); // do second after setting direction
#endif

// index pin direction is set in setup1
pinMode(DIR_PIN, INPUT_PULLUP);
pinMode(STEP_PIN, INPUT_PULLUP);
pinMode(SIDE_PIN, INPUT_PULLUP);
pinMode(MOTOR_PIN, INPUT_PULLUP);
pinMode(SELECT_PIN, INPUT_PULLUP);
pinMode(TRK0_PIN, OUTPUT);
pinMode(READY_PIN, OUTPUT);
digitalWrite(READY_PIN, HIGH); // active low
#if defined(PROT_PIN)
pinMode(PROT_PIN, OUTPUT);
digitalWrite(PROT_PIN, LOW); // always write-protected, no write support
Expand All @@ -254,33 +273,32 @@ void setup() {
pinMode(DISKCHANGE_PIN, INPUT_PULLUP);
#endif

#if defined(FLOPPY_DIRECTION_PIN)
pinMode(FLOPPY_DIRECTION_PIN, OUTPUT);
digitalWrite(FLOPPY_DIRECTION_PIN, LOW); // we are emulating a floppy
#endif
#if defined(FLOPPY_ENABLE_PIN)
pinMode(FLOPPY_ENABLE_PIN, OUTPUT);
digitalWrite(FLOPPY_ENABLE_PIN, LOW); // do second after setting direction
Serial.begin(115200);
#define WAIT_SERIAL
#if defined(WAIT_SERIAL)
while(!Serial) {}
Serial.println("Serial connected");
#endif

Serial.begin(115200);
attachInterrupt(digitalPinToInterrupt(STEP_PIN), onStep, FALLING);

#if defined(NEOPIXEL_PIN)
strip.begin();
#endif

#if USE_SDFAT
if (!SD.begin(PIN_CARD_CS)) {
Serial.println("SD card initialization failed");
return;
}

if (!dir.open("/")) {
STATUS_RGB(255,0,0);
delay(2000);
} else if (!dir.open("/")) {
Serial.println("SD card directory could not be read");
return;
STATUS_RGB(255,255,0);
delay(2000);
} else {
STATUS_RGB(0,0,255);
openNextImage();
}
openNextImage();
#endif

#if defined(NEOPIXEL_PIN)
strip.begin();
#endif
}

Expand Down Expand Up @@ -308,14 +326,38 @@ static void encode_track_mfm(uint8_t head, uint8_t cylinder,
size_t pos = encode_track_mfm(&io);
}

// As an easter egg, the dummy disk image embeds the boot sector Tetris implementation
// from https://github.com/daniel-e/tetros (source available under MIT license)
const uint8_t tetros[] = {
#include "tetros.h"
};

static void make_dummy_data(uint8_t head, uint8_t cylinder, size_t n_bytes) {
uint8_t dummy_byte = head * 2 + cylinder;
std::fill(track_data, track_data + n_bytes, dummy_byte);
if(head == 0 && cylinder == 0 && n_bytes >= 512) {
Serial.println("Injecting tetros in boot sector");
std::copy(tetros, std::end(tetros), track_data);
}
}

void loop() {
static int cached_trackno = -1;
auto new_trackno = trackno;
int motor_pin = !digitalRead(MOTOR_PIN);
int select_pin = !digitalRead(SELECT_PIN);
int side = !digitalRead(SIDE_PIN);
auto enabled = motor_pin && select_pin;
static bool old_enabled = false;
static bool old_enabled = false, old_select_pin=false, old_motor_pin=false;

if(motor_pin != old_motor_pin) {
Serial.printf("motor_pin -> %s\n", motor_pin ? "true" : "false");
old_motor_pin = motor_pin;
}
if(select_pin != old_select_pin) {
Serial.printf("select_pin -> %s\n", select_pin ? "true" : "false");
old_select_pin = select_pin;
}

if(enabled != old_enabled) {
Serial.printf("enabled -> %s\n", enabled ? "true" : "false");
Expand All @@ -337,6 +379,7 @@ void loop() {
#endif

if (cur_format && new_trackno != cached_trackno) {
STATUS_RGB(0,255,255);
fluxout = -1;
Serial.printf("Preparing MFM data for track %d\n", new_trackno);
int sector_count = cur_format->sectors;
Expand All @@ -348,29 +391,34 @@ void loop() {
int n = file.read(track_data, count);
if (n != count) {
Serial.println("Read failed -- using dummy data");
std::fill(track_data, track_data + count, dummy_byte);
make_dummy_data(0, new_trackno, count);
}
encode_track_mfm(0, new_trackno, sector_count);
n = file.read(track_data, count);
if (n != count) {
Serial.println("Read failed -- using dummy data");
std::fill(track_data, track_data + count, dummy_byte + 1);
make_dummy_data(1, new_trackno, count);
}
encode_track_mfm(1, new_trackno, sector_count);
#else
Serial.println("No filesystem - using dummy data");
std::fill(track_data, track_data + count, dummy_byte);
make_dummy_data(0, new_trackno, count);
encode_track_mfm(0, new_trackno, sector_count);
std::fill(track_data, track_data + count, dummy_byte + 1);
make_dummy_data(1, new_trackno, count);
encode_track_mfm(1, new_trackno, sector_count);
#endif

Serial.println("MFM data prepared");
cached_trackno = new_trackno;
}
fluxout =
(cur_format != NULL && enabled && cached_trackno == trackno) ? side : -1;
#if defined(NEOPIXEL_PIN)
strip.fill(motor_pin ? 0xffffffff : 0);
strip.show();
if(fluxout >= 0) { STATUS_RGB(0,255,0); } else { STATUS_RGB(0,0,0); }
#endif

// this is not correct handling of the ready/disk change flag. on my test
// computer, just leaving the pin HIGH works, while immediately reporting LOW on the
// "ready / disk change
// digitalWrite(READY_PIN, !motor_pin);
}
2 changes: 2 additions & 0 deletions examples/mfm_emu/tetros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
49, 192, 142, 216, 49, 192, 205, 16, 180, 1, 185, 7, 38, 205, 16, 182, 3, 185, 18, 0, 81, 254, 198, 178, 13, 185, 14, 0, 187, 120, 0, 232, 182, 0, 128, 254, 21, 116, 9, 66, 185, 12, 0, 49, 219, 232, 168, 0, 89, 226, 225, 198, 6, 0, 127, 100, 180, 2, 205, 26, 160, 2, 127, 49, 208, 179, 31, 247, 227, 64, 162, 2, 127, 49, 210, 187, 7, 0, 247, 243, 192, 226, 3, 146, 186, 18, 4, 232, 229, 0, 117, 254, 232, 210, 0, 49, 201, 138, 14, 0, 127, 81, 96, 49, 201, 186, 184, 11, 180, 134, 205, 21, 97, 80, 180, 1, 205, 22, 137, 193, 88, 116, 69, 232, 175, 0, 128, 253, 75, 116, 17, 128, 253, 72, 116, 30, 128, 253, 77, 116, 16, 198, 6, 0, 127, 10, 235, 35, 74, 232, 167, 0, 116, 29, 66, 235, 26, 66, 232, 158, 0, 116, 20, 74, 235, 17, 136, 195, 64, 64, 168, 7, 117, 2, 44, 8, 232, 140, 0, 116, 2, 136, 216, 232, 119, 0, 80, 48, 228, 205, 22, 88, 89, 226, 162, 232, 103, 0, 254, 198, 232, 116, 0, 116, 138, 254, 206, 232, 95, 0, 232, 22, 0, 233, 91, 255, 180, 2, 205, 16, 184, 32, 9, 205, 16, 195, 180, 2, 205, 16, 180, 8, 205, 16, 195, 96, 182, 21, 254, 206, 116, 57, 49, 219, 185, 12, 0, 178, 14, 232, 230, 255, 192, 236, 4, 116, 2, 67, 66, 226, 244, 128, 251, 12, 117, 228, 96, 178, 14, 185, 12, 0, 81, 254, 206, 232, 204, 255, 254, 198, 136, 227, 177, 1, 232, 185, 255, 66, 89, 226, 237, 97, 254, 206, 117, 226, 232, 192, 255, 97, 195, 49, 219, 235, 9, 136, 195, 192, 235, 3, 67, 192, 227, 4, 67, 137, 223, 235, 3, 191, 0, 0, 96, 49, 219, 136, 195, 139, 135, 134, 125, 49, 219, 185, 4, 0, 81, 177, 4, 246, 196, 128, 116, 29, 80, 9, 255, 116, 14, 96, 137, 251, 48, 192, 185, 1, 0, 232, 112, 255, 97, 235, 9, 232, 116, 255, 192, 236, 4, 116, 1, 67, 88, 209, 224, 66, 226, 217, 128, 234, 4, 254, 198, 89, 226, 206, 8, 219, 97, 195, 68, 68, 0, 240, 68, 68, 0, 240, 96, 34, 0, 226, 64, 100, 0, 142, 96, 68, 0, 46, 32, 98, 0, 232, 0, 102, 0, 102, 0, 102, 0, 102, 0, 198, 64, 38, 0, 198, 64, 38, 0, 78, 64, 76, 0, 228, 128, 140, 0, 108, 64, 140, 0, 108, 64, 140, 128, 0, 1, 0, 23, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 85, 170

0 comments on commit c7ce752

Please sign in to comment.