1 #ifndef ADAFRUIT_FLOPPY_H 2 #define ADAFRUIT_FLOPPY_H 19 #include <Adafruit_SPIDevice.h> 22 #include "SdFatConfig.h" 24 #define FLOPPY_IBMPC_HD_TRACKS 80 25 #define FLOPPY_IBMPC_DD_TRACKS 40 26 #define FLOPPY_HEADS 2 28 #define MFM_IBMPC1200K_SECTORS_PER_TRACK 15 29 #define MFM_IBMPC1440K_SECTORS_PER_TRACK 18 30 #define MFM_IBMPC360K_SECTORS_PER_TRACK 9 31 #define MFM_IBMPC720K_SECTORS_PER_TRACK 9 32 #define MFM_BYTES_PER_SECTOR 512UL 36 #define MAX_FLUX_PULSE_PER_TRACK \ 37 (uint32_t)(500000UL / 5 * \ 38 1.5) // 500khz / 5 hz per track rotation, 1.5 rotations 40 #define BUSTYPE_IBMPC 1 41 #define BUSTYPE_SHUGART 2 51 } adafruit_floppy_disk_t;
61 bool is_apple2 =
false);
75 virtual void select(
bool selected) = 0;
101 virtual bool side(
int head) = 0;
116 virtual int track(
void) = 0;
154 uint8_t *sector_validity,
const uint8_t *pulses,
155 size_t n_pulses,
float nominal_bit_time_us,
156 bool clear_validity =
false,
157 uint8_t *logical_track =
nullptr);
160 uint8_t *pulses,
size_t max_pulses,
161 float nominal_bit_time_us, uint8_t logical_track);
163 size_t capture_track(
volatile uint8_t *pulses,
size_t max_pulses,
164 int32_t *falling_index_offset,
165 bool store_greaseweazle =
false, uint32_t capture_ms = 0,
166 uint32_t index_wait_ms = 250)
167 __attribute__((optimize(
"O3")));
170 bool store_greaseweazle =
false,
bool use_index =
true)
171 __attribute__((optimize(
"O3")));
172 void print_pulse_bins(uint8_t *pulses,
size_t n_pulses, uint8_t max_bins = 64,
173 bool is_gw_format =
false, uint32_t min_bin_size = 100);
175 bool is_gw_format =
false);
178 #if defined(LED_BUILTIN) 198 #if defined(__SAMD51__) 199 void deinit_capture(
void);
200 void enable_capture(
void);
202 bool init_generate(
void);
203 void deinit_generate(
void);
204 void enable_generate(
void);
205 void disable_generate(
void);
208 bool start_polled_capture(
void);
209 void disable_capture(
void);
211 bool init_capture(
void);
212 void enable_background_capture(
void);
213 void wait_for_index_pulse_low(
void);
215 int8_t _indexpin, _wrdatapin, _wrgatepin, _rddatapin;
218 #ifdef BUSIO_USE_FAST_PINIO 219 BusIO_PortReg *indexPort;
220 BusIO_PortMask indexMask;
221 uint32_t dummyPort = 0;
233 int8_t motorpin, int8_t directionpin, int8_t steppin,
234 int8_t wrdatapin, int8_t wrgatepin, int8_t track0pin,
235 int8_t protectpin, int8_t rddatapin, int8_t sidepin,
240 void select(
bool selected)
override;
243 bool side(
int head)
override;
244 int track(
void)
override;
246 void step(
bool dir, uint8_t times);
254 int8_t _densitypin, _selectpin, _motorpin, _directionpin, _steppin,
255 _track0pin, _protectpin, _sidepin, _readypin;
257 int _track = -1, _side = -1;
279 int8_t phase2pin, int8_t phase3pin, int8_t phase4pin,
280 int8_t wrdatapin, int8_t wrgatepin, int8_t protectpin,
285 void select(
bool selected)
override;
288 bool side(
int head)
override;
289 int track(
void)
override;
296 bool goto_quartertrack(
int);
302 int _step_multiplier()
const;
304 int8_t _selectpin, _phase1pin, _phase2pin, _phase3pin, _phase4pin,
306 int _quartertrack = -1;
307 StepMode _step_mode = STEP_MODE_HALF;
308 void _step(
int dir,
int times);
321 adafruit_floppy_disk_t format = AUTODETECT);
326 uint32_t size(
void)
const;
327 int32_t readTrack(
int track,
bool head);
338 bool dirty()
const {
return _dirty; }
347 bool inserted(adafruit_floppy_disk_t format);
350 virtual bool isBusy();
351 virtual uint32_t sectorCount();
352 virtual bool syncDevice();
354 virtual bool readSector(uint32_t block, uint8_t *dst);
355 virtual bool readSectors(uint32_t block, uint8_t *dst,
size_t ns);
356 virtual bool writeSector(uint32_t block,
const uint8_t *src);
357 virtual bool writeSectors(uint32_t block,
const uint8_t *src,
size_t ns);
360 uint8_t track_data[MFM_IBMPC1440K_SECTORS_PER_TRACK * MFM_BYTES_PER_SECTOR];
363 uint8_t track_validity[MFM_IBMPC1440K_SECTORS_PER_TRACK];
367 #if defined(PICO_BOARD) || defined(__RP2040__) || defined(ARDUINO_ARCH_RP2040) 370 static constexpr uint8_t NO_TRACK = UINT8_MAX;
371 uint8_t _sectors_per_track = 0;
372 uint8_t _tracks_per_side = 0;
373 uint8_t _last_track_read = NO_TRACK;
374 uint16_t _bit_time_ns;
375 bool _high_density =
true;
376 bool _dirty =
false, _track_has_errors =
false;
377 bool _double_step =
false;
379 adafruit_floppy_disk_t _format = AUTODETECT;
382 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:578
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:724
uint8_t sectors_per_track(void) const
The expected number of sectors per track in this format.
Definition: Adafruit_Floppy.h:331
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:855
StepMode
Constants for use with the step_mode method.
Definition: Adafruit_Floppy.h:272
uint8_t tracks_per_side(void) const
The expected number of tracks per side in this format.
Definition: Adafruit_Floppy.h:334
bool get_ready_sense() override
Check whether the ready output is active.
Definition: Adafruit_Floppy.h:293
bool read_index()
Poll the status of the index pulse.
Definition: Adafruit_Floppy.cpp:216
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:299
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:188
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:58
bool dirty() const
Check if there is data to be written to the current track.
Definition: Adafruit_Floppy.h:338
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:190
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:521
int8_t led_pin
Debug LED output for tracing.
Definition: Adafruit_Floppy.h:181
uint16_t select_delay_us
delay after drive select (usecs)
Definition: Adafruit_Floppy.h:184
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:185
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:484
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:889
virtual bool get_ready_sense()=0
Check whether the ready output is active.
Definition: Adafruit_Floppy.h:318
A helper class for chattin with PC & Shugart floppy drives.
Definition: Adafruit_Floppy.h:230
virtual bool side(int head)=0
Which head/side to read from.
uint32_t getSampleFrequency(void)
Get the sample rate that we read and emit pulses at, platform and implementation-dependant.
Definition: Adafruit_Floppy.cpp:550
uint16_t motor_delay_ms
delay after motor on (msecs)
Definition: Adafruit_Floppy.h:187
Stream * debug_serial
optional debug stream for serial output
Definition: Adafruit_Floppy.h:192
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:159
A helper class for chattin with Apple 2 floppy drives.
Definition: Adafruit_Floppy.h:265
uint16_t settle_delay_ms
settle delay after seek (msecs)
Definition: Adafruit_Floppy.h:186
bool begin(void)
Initializes the GPIO pins but do not start the motor or anything.
Definition: Adafruit_Floppy.cpp:98