1 #ifndef ADAFRUIT_FLOPPY_H 2 #define ADAFRUIT_FLOPPY_H 19 #include <Adafruit_SPIDevice.h> 22 #define DISABLE_FS_H_WARNING 24 #include "SdFatConfig.h" 26 #define FLOPPY_IBMPC_HD_TRACKS 80 27 #define FLOPPY_IBMPC_DD_TRACKS 40 28 #define FLOPPY_HEADS 2 30 #define MFM_IBMPC1200K_SECTORS_PER_TRACK 15 31 #define MFM_IBMPC1440K_SECTORS_PER_TRACK 18 32 #define MFM_IBMPC360K_SECTORS_PER_TRACK 9 33 #define MFM_IBMPC720K_SECTORS_PER_TRACK 9 34 #define MFM_BYTES_PER_SECTOR 512UL 38 #define MAX_FLUX_PULSE_PER_TRACK \ 39 (uint32_t)(500000UL / 5 * \ 40 1.5) // 500khz / 5 hz per track rotation, 1.5 rotations 42 #define BUSTYPE_IBMPC 1 43 #define BUSTYPE_SHUGART 2 53 } adafruit_floppy_disk_t;
63 bool is_apple2 =
false);
77 virtual void select(
bool selected) = 0;
125 virtual bool side(
int head) = 0;
140 virtual int track(
void) = 0;
178 uint8_t *sector_validity,
const uint8_t *pulses,
179 size_t n_pulses,
float nominal_bit_time_us,
180 bool clear_validity =
false,
181 uint8_t *logical_track =
nullptr);
184 uint8_t *pulses,
size_t max_pulses,
185 float nominal_bit_time_us, uint8_t logical_track);
187 size_t capture_track(
volatile uint8_t *pulses,
size_t max_pulses,
188 int32_t *falling_index_offset,
189 bool store_greaseweazle =
false, uint32_t capture_ms = 0,
190 uint32_t index_wait_ms = 250)
191 __attribute__((optimize(
"O3")));
194 bool store_greaseweazle =
false,
bool use_index =
true)
195 __attribute__((optimize(
"O3")));
196 void print_pulse_bins(uint8_t *pulses,
size_t n_pulses, uint8_t max_bins = 64,
197 bool is_gw_format =
false, uint32_t min_bin_size = 100);
199 bool is_gw_format =
false);
202 #if defined(LED_BUILTIN) 225 #if defined(__SAMD51__) 226 void deinit_capture(
void);
227 void enable_capture(
void);
229 bool init_generate(
void);
230 void deinit_generate(
void);
231 void enable_generate(
void);
232 void disable_generate(
void);
235 bool start_polled_capture(
void);
236 void disable_capture(
void);
238 bool init_capture(
void);
239 void enable_background_capture(
void);
240 void wait_for_index_pulse_low(
void);
242 int8_t _indexpin, _wrdatapin, _wrgatepin, _rddatapin;
245 #ifdef BUSIO_USE_FAST_PINIO 246 BusIO_PortReg *indexPort;
247 BusIO_PortMask indexMask;
248 uint32_t dummyPort = 0;
260 int8_t motorpin, int8_t directionpin, int8_t steppin,
261 int8_t wrdatapin, int8_t wrgatepin, int8_t track0pin,
262 int8_t protectpin, int8_t rddatapin, int8_t sidepin,
267 void select(
bool selected)
override;
270 bool side(
int head)
override;
271 int track(
void)
override;
273 void step(
bool dir, uint8_t times);
281 int8_t _densitypin, _selectpin, _motorpin, _directionpin, _steppin,
282 _track0pin, _protectpin, _sidepin, _readypin;
284 int _track = -1, _side = -1;
306 int8_t phase2pin, int8_t phase3pin, int8_t phase4pin,
307 int8_t wrdatapin, int8_t wrgatepin, int8_t protectpin,
312 void select(
bool selected)
override;
315 bool side(
int head)
override;
316 int track(
void)
override;
323 bool goto_quartertrack(
int);
329 int _step_multiplier()
const;
331 int8_t _selectpin, _phase1pin, _phase2pin, _phase3pin, _phase4pin,
333 int _quartertrack = -1;
334 StepMode _step_mode = STEP_MODE_HALF;
335 void _step(
int dir,
int times);
348 adafruit_floppy_disk_t format = AUTODETECT);
353 uint32_t size(
void)
const;
354 int32_t readTrack(
int track,
bool head);
365 bool dirty()
const {
return _dirty; }
374 bool inserted(adafruit_floppy_disk_t format);
377 virtual bool isBusy();
378 virtual uint32_t sectorCount();
379 virtual bool syncDevice();
381 virtual bool readSector(uint32_t block, uint8_t *dst);
382 virtual bool readSectors(uint32_t block, uint8_t *dst,
size_t ns);
383 virtual bool writeSector(uint32_t block,
const uint8_t *src);
384 virtual bool writeSectors(uint32_t block,
const uint8_t *src,
size_t ns);
387 uint8_t track_data[MFM_IBMPC1440K_SECTORS_PER_TRACK * MFM_BYTES_PER_SECTOR];
390 uint8_t track_validity[MFM_IBMPC1440K_SECTORS_PER_TRACK];
394 #if defined(PICO_BOARD) || defined(__RP2040__) || defined(ARDUINO_ARCH_RP2040) 397 static constexpr uint8_t NO_TRACK = UINT8_MAX;
398 uint8_t _sectors_per_track = 0;
399 uint8_t _tracks_per_side = 0;
400 uint8_t _last_track_read = NO_TRACK;
401 uint16_t _bit_time_ns;
402 bool _high_density =
true;
403 bool _dirty =
false, _track_has_errors =
false;
404 bool _double_step =
false;
406 adafruit_floppy_disk_t _format = AUTODETECT;
409 uint8_t _flux[125000];
size_t capture_track(volatile uint8_t *pulses, size_t max_pulses, int32_t *falling_index_offset, bool store_greaseweazle=false, uint32_t capture_ms=0, uint32_t index_wait_ms=250) __attribute__((optimize("O3")))
Capture one track's worth of flux transitions, between two falling index pulses.
Definition: Adafruit_Floppy.cpp:598
bool drive_is_selected(void)
Is the drive selected based on interal caching.
Definition: Adafruit_Floppy.h:84
bool write_track(uint8_t *pulses, size_t n_pulses, bool store_greaseweazle=false, bool use_index=true) __attribute__((optimize("O3")))
Write one track of flux pulse data, starting at the index pulse.
Definition: Adafruit_Floppy.cpp:744
bool motor_is_spinning(void)
Is the drive motor spinning based on interal caching.
Definition: Adafruit_Floppy.h:102
uint8_t sectors_per_track(void) const
The expected number of sectors per track in this format.
Definition: Adafruit_Floppy.h:358
void print_pulses(uint8_t *pulses, size_t n_pulses, bool is_gw_format=false)
Pretty print the counts in a list of flux transitions.
Definition: Adafruit_Floppy.cpp:875
bool is_index_seen
cached index pulses seen state
Definition: Adafruit_Floppy.h:222
StepMode
Constants for use with the step_mode method.
Definition: Adafruit_Floppy.h:299
uint8_t tracks_per_side(void) const
The expected number of tracks per side in this format.
Definition: Adafruit_Floppy.h:361
bool get_ready_sense() override
Check whether the ready output is active.
Definition: Adafruit_Floppy.h:320
bool read_index()
Poll the status of the index pulse.
Definition: Adafruit_Floppy.cpp:223
virtual bool goto_track(int track_num)=0
Seek to the desired track, requires the motor to be spun up!
int get_side() override
Current head in use, based on internal caching.
Definition: Adafruit_Floppy.h:326
virtual bool spin_motor(bool motor_on)=0
Turn on or off the floppy motor, if on we wait till we get an index pulse!
uint16_t watchdog_delay_ms
quiescent time until drives reset (msecs)
Definition: Adafruit_Floppy.h:212
virtual int track(void)=0
The current track location, based on internal caching.
An abstract base class for chattin with floppy drives.
Definition: Adafruit_Floppy.h:60
bool dirty() const
Check if there is data to be written to the current track.
Definition: Adafruit_Floppy.h:365
virtual bool set_density(bool high_density)=0
Set the density for flux reading and writing.
virtual void soft_reset(void)
Initializes the GPIO pins but do not start the motor or anything.
Definition: Adafruit_Floppy.cpp:118
uint8_t bus_type
what kind of floppy drive we're using
Definition: Adafruit_Floppy.h:214
virtual bool get_write_protect()=0
Check whether the floppy in the drive is write protected.
size_t encode_track_mfm(const uint8_t *sectors, size_t n_sectors, uint8_t *pulses, size_t max_pulses, float nominal_bit_time_us, uint8_t logical_track)
Encode one track of previously captured MFM data.
Definition: Adafruit_Floppy.cpp:541
int8_t led_pin
Debug LED output for tracing.
Definition: Adafruit_Floppy.h:205
uint16_t select_delay_us
delay after drive select (usecs)
Definition: Adafruit_Floppy.h:208
bool is_motor_spinning
cached motor spinning state
Definition: Adafruit_Floppy.h:221
virtual bool get_track0_sense()=0
Check whether the track0 sensor is active.
virtual void select(bool selected)=0
Whether to select this drive.
uint16_t step_delay_us
delay between head steps (usecs)
Definition: Adafruit_Floppy.h:209
size_t decode_track_mfm(uint8_t *sectors, size_t n_sectors, uint8_t *sector_validity, const uint8_t *pulses, size_t n_pulses, float nominal_bit_time_us, bool clear_validity=false, uint8_t *logical_track=nullptr)
Decode one track of previously captured MFM data.
Definition: Adafruit_Floppy.cpp:504
Adafruit_FloppyBase(int indexpin, int wrdatapin, int wrgatepin, int rddatapin, bool is_apple2=false)
Create a hardware interface to a floppy drive.
Definition: Adafruit_Floppy.cpp:47
void print_pulse_bins(uint8_t *pulses, size_t n_pulses, uint8_t max_bins=64, bool is_gw_format=false, uint32_t min_bin_size=100)
Pretty print a simple histogram of flux transitions.
Definition: Adafruit_Floppy.cpp:909
virtual bool get_ready_sense()=0
Check whether the ready output is active.
Definition: Adafruit_Floppy.h:345
A helper class for chattin with PC & Shugart floppy drives.
Definition: Adafruit_Floppy.h:257
virtual bool side(int head)=0
Which head/side to read from.
bool is_drive_selected
cached drive select state
Definition: Adafruit_Floppy.h:220
uint32_t getSampleFrequency(void)
Get the sample rate that we read and emit pulses at, platform and implementation-dependant.
Definition: Adafruit_Floppy.cpp:570
uint16_t motor_delay_ms
delay after motor on (msecs)
Definition: Adafruit_Floppy.h:211
Stream * debug_serial
optional debug stream for serial output
Definition: Adafruit_Floppy.h:216
bool index_pulses_seen(void)
Are index pulses being seen?
Definition: Adafruit_Floppy.h:109
virtual int get_side()=0
Current head in use, based on internal caching.
virtual void end()
Disables floppy communication, allowing pins to be used for general input and output.
Definition: Adafruit_Floppy.cpp:163
A helper class for chattin with Apple 2 floppy drives.
Definition: Adafruit_Floppy.h:292
uint16_t settle_delay_ms
settle delay after seek (msecs)
Definition: Adafruit_Floppy.h:210
bool begin(void)
Initializes the GPIO pins but do not start the motor or anything.
Definition: Adafruit_Floppy.cpp:98