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;
127 virtual bool side(
int head) = 0;
142 virtual int track(
void) = 0;
180 uint8_t *sector_validity,
const uint8_t *pulses,
181 size_t n_pulses,
float nominal_bit_time_us,
182 bool clear_validity =
false,
183 uint8_t *logical_track =
nullptr,
184 int expected_track = -1);
187 uint8_t *pulses,
size_t max_pulses,
188 float nominal_bit_time_us, uint8_t logical_track);
190 size_t capture_track(
volatile uint8_t *pulses,
size_t max_pulses,
191 int32_t *falling_index_offset,
192 bool store_greaseweazle =
false, uint32_t capture_ms = 0,
193 uint32_t index_wait_ms = 250)
194 __attribute__((optimize(
"O3")));
197 bool store_greaseweazle =
false,
bool use_index =
true)
198 __attribute__((optimize(
"O3")));
201 void print_pulse_bins(uint8_t *pulses,
size_t n_pulses, uint8_t max_bins = 64,
202 bool is_gw_format =
false, uint32_t min_bin_size = 100);
204 bool is_gw_format =
false);
207 #if defined(LED_BUILTIN) 231 #if defined(__SAMD51__) 232 void deinit_capture(
void);
233 void enable_capture(
void);
235 bool init_generate(
void);
236 void deinit_generate(
void);
237 void enable_generate(
void);
238 void disable_generate(
void);
241 bool start_polled_capture(
void);
242 void disable_capture(
void);
244 bool init_capture(
void);
245 void enable_background_capture(
void);
246 void wait_for_index_pulse_low(
void);
248 int8_t _indexpin, _wrdatapin, _wrgatepin, _rddatapin;
251 #ifdef BUSIO_USE_FAST_PINIO 252 BusIO_PortReg *indexPort;
253 BusIO_PortMask indexMask;
254 uint32_t dummyPort = 1;
266 int8_t motorpin, int8_t directionpin, int8_t steppin,
267 int8_t wrdatapin, int8_t wrgatepin, int8_t track0pin,
268 int8_t protectpin, int8_t rddatapin, int8_t sidepin,
273 void select(
bool selected)
override;
276 bool side(
int head)
override;
277 int track(
void)
override;
279 void step(
bool dir, uint8_t times);
287 int8_t _densitypin, _selectpin, _motorpin, _directionpin, _steppin,
288 _track0pin, _protectpin, _sidepin, _readypin;
290 int _track = -1, _side = -1;
312 int8_t phase2pin, int8_t phase3pin, int8_t phase4pin,
313 int8_t wrdatapin, int8_t wrgatepin, int8_t protectpin,
318 void select(
bool selected)
override;
321 bool side(
int head)
override;
322 int track(
void)
override;
329 bool goto_quartertrack(
int);
335 int _step_multiplier()
const;
337 int8_t _selectpin, _phase1pin, _phase2pin, _phase3pin, _phase4pin,
339 int _quartertrack = -1;
340 StepMode _step_mode = STEP_MODE_HALF;
341 void _step(
int dir,
int times);
354 adafruit_floppy_disk_t format = AUTODETECT);
359 uint32_t size(
void)
const;
360 int32_t readTrack(
int track,
bool head);
371 bool dirty()
const {
return _dirty; }
380 bool inserted(adafruit_floppy_disk_t format);
383 virtual bool isBusy();
384 virtual uint32_t sectorCount();
385 virtual bool syncDevice();
387 virtual bool readSector(uint32_t block, uint8_t *dst);
388 virtual bool readSectors(uint32_t block, uint8_t *dst,
size_t ns);
389 virtual bool writeSector(uint32_t block,
const uint8_t *src);
390 virtual bool writeSectors(uint32_t block,
const uint8_t *src,
size_t ns);
393 uint8_t track_data[MFM_IBMPC1440K_SECTORS_PER_TRACK * MFM_BYTES_PER_SECTOR];
396 uint8_t track_validity[MFM_IBMPC1440K_SECTORS_PER_TRACK];
400 #if defined(PICO_BOARD) || defined(__RP2040__) || defined(ARDUINO_ARCH_RP2040) 403 static constexpr uint8_t NO_TRACK = UINT8_MAX;
404 uint8_t _sectors_per_track = 0;
405 uint8_t _tracks_per_side = 0;
406 uint8_t _last_track_read = NO_TRACK;
407 uint16_t _bit_time_ns;
408 bool _high_density =
true;
409 bool _dirty =
false, _track_has_errors =
false;
410 bool _double_step =
false;
412 adafruit_floppy_disk_t _format = AUTODETECT;
415 uint8_t _flux[125000];
static const uint32_t MAX_ERASE_US
Maximum erase time, in us.
Definition: Adafruit_Floppy.h:199
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 flux transitions for one revolution or a bounded duration.
Definition: Adafruit_Floppy.cpp:657
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:829
bool motor_is_spinning(void)
Is the drive motor spinning based on interal caching.
Definition: Adafruit_Floppy.h:102
bool erase_track(uint32_t duration_us)
Erase the selected track without waiting for INDEX.
Definition: Adafruit_Floppy.cpp:947
uint8_t sectors_per_track(void) const
The expected number of sectors per track in this format.
Definition: Adafruit_Floppy.h:364
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:1003
bool is_index_seen
cached index pulses seen state
Definition: Adafruit_Floppy.h:227
StepMode
Constants for use with the step_mode method.
Definition: Adafruit_Floppy.h:305
bool is_index_missing
configured INDEX timed out during motor startup
Definition: Adafruit_Floppy.h:228
uint8_t tracks_per_side(void) const
The expected number of tracks per side in this format.
Definition: Adafruit_Floppy.h:367
bool get_ready_sense() override
Check whether the ready output is active.
Definition: Adafruit_Floppy.h:326
bool read_index()
Poll the status of the index pulse.
Definition: Adafruit_Floppy.cpp:229
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:332
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, int expected_track=-1)
Decode one track of previously captured MFM data.
Definition: Adafruit_Floppy.cpp:554
virtual bool spin_motor(bool motor_on)=0
Turn the motor on or off. Starting waits for settling and INDEX, or just settling when indexpin=-1...
uint16_t watchdog_delay_ms
quiescent time until drives reset (msecs)
Definition: Adafruit_Floppy.h:217
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:371
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:219
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:594
int8_t led_pin
Debug LED output for tracing.
Definition: Adafruit_Floppy.h:210
uint16_t select_delay_us
delay after drive select (usecs)
Definition: Adafruit_Floppy.h:213
bool is_motor_spinning
cached motor spinning state
Definition: Adafruit_Floppy.h:226
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:214
bool index_pulses_missing(void) const
Whether startup timed out waiting for a configured INDEX input.
Definition: Adafruit_Floppy.cpp:263
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:1037
virtual bool get_ready_sense()=0
Check whether the ready output is active.
Definition: Adafruit_Floppy.h:351
A helper class for chattin with PC & Shugart floppy drives.
Definition: Adafruit_Floppy.h:263
virtual bool side(int head)=0
Which head/side to read from.
bool is_drive_selected
cached drive select state
Definition: Adafruit_Floppy.h:225
uint32_t getSampleFrequency(void)
Get the sample rate that we read and emit pulses at, platform and implementation-dependant.
Definition: Adafruit_Floppy.cpp:624
uint16_t motor_delay_ms
delay after motor on (msecs)
Definition: Adafruit_Floppy.h:216
Stream * debug_serial
optional debug stream for serial output
Definition: Adafruit_Floppy.h:221
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:168
A helper class for chattin with Apple 2 floppy drives.
Definition: Adafruit_Floppy.h:298
uint16_t settle_delay_ms
settle delay after seek (msecs)
Definition: Adafruit_Floppy.h:215
bool begin(void)
Initializes the GPIO pins but do not start the motor or anything.
Definition: Adafruit_Floppy.cpp:98
bool has_index(void) const
Whether a physical INDEX input was configured.
Definition: Adafruit_Floppy.cpp:249