@@ -50,7 +50,7 @@ def _sleep_ms(interval):
5050 _sleep_deadline_ms (ticks_add (ticks_ms (), interval ))
5151
5252
53- class MFMFloppy : # pylint: disable=too-many-instance-attributes
53+ class Floppy : # pylint: disable=too-many-instance-attributes
5454 """Interface with floppy disk drive hardware"""
5555
5656 _track : typing .Optional [int ]
@@ -71,6 +71,7 @@ def __init__(
7171 readypin : microcontroller .Pin ,
7272 wrdatapin : typing .Optional [microcontroller .Pin ] = None ,
7373 wrgatepin : typing .Optional [microcontroller .Pin ] = None ,
74+ floppydirectionpin : typing .Optional [microcontroller .Pin ] = None ,
7475 ) -> None :
7576 self ._density = DigitalInOut (densitypin )
7677 self ._density .pull = Pull .UP
@@ -97,6 +98,10 @@ def __init__(
9798 self ._ready = DigitalInOut (readypin )
9899 self ._ready .pull = Pull .UP
99100
101+ self ._floppydirection = _optionaldigitalinout (floppydirectionpin )
102+ if self ._floppydirection :
103+ self ._floppydirection .switch_to_output (True )
104+
100105 self ._track = None
101106
102107 def _do_step (self , direction , count ):
@@ -122,6 +127,7 @@ def find_track0(self):
122127 for _ in range (250 ):
123128 if not self ._track0 .value :
124129 self ._track = 0
130+ self ._check_inpos ()
125131 return
126132 self ._do_step (_STEP_OUT , 1 )
127133 raise RuntimeError ("Could not reach track 0" )
@@ -131,7 +137,7 @@ def _check_inpos(self) -> None:
131137 drive_says_track0 = not self ._track0 .value
132138 we_think_track0 = track == 0
133139 if drive_says_track0 != we_think_track0 :
134- raise RuntimeError ("Drive lost position" )
140+ raise RuntimeError (f "Drive lost position (target= { track } , track0 sensor { drive_says_track0 } ) " )
135141
136142 @property
137143 def track (self ) -> typing .Optional [int ]:
@@ -150,7 +156,7 @@ def track(self, track: int) -> None:
150156 delta = track - self .track
151157 if delta < 0 :
152158 self ._do_step (_STEP_OUT , - delta )
153- else :
159+ elif delta > 0 :
154160 self ._do_step (_STEP_IN , delta )
155161
156162 self ._track = track
@@ -210,24 +216,6 @@ def flux_readinto(self, buf: "circuitpython_typing.WritableBuffer") -> int:
210216 :return: The actual number of bytes of read"""
211217 return floppyio .flux_readinto (buf , self ._rddata , self ._index )
212218
213- def mfm_readinto (self , buf : "circuitpython_typing.WriteableBuffer" ) -> int :
214- """Read mfm blocks into the buffer.
215-
216- The track is assumed to consist of 512-byte sectors.
217-
218- The function returns when all sectors have been successfully read, or
219- a number of index pulses have occurred. Due to technical limitations, this
220- process may not be interruptible by KeyboardInterrupt.
221-
222- :param buf: Read data into this buffer. Must be a multiple of 512.
223- :return: The actual number of sectors read
224- """
225- return floppyio .mfm_readinto (
226- buf ,
227- self ._rddata ,
228- self ._index ,
229- )
230-
231219
232220class FloppyBlockDevice :
233221 """Wrap an MFMFloppy object into a block device suitable for `storage.VfsFat`
@@ -243,37 +231,46 @@ class FloppyBlockDevice:
243231 import storage
244232 import adafruit_floppy
245233
246- floppy = adafruit_floppy.MFMFloppy (...)
234+ floppy = adafruit_floppy.Floppy (...)
247235 block_device = adafruit_floppy.FloppyBlockDevice(floppy)
248236 vfs = storage.VfsFat(f)
249237 storage.mount(vfs, '/floppy')
250238 print(os.listdir("/floppy"))
251239 """
252240
253- def __init__ (self , floppy , heads = 2 , sectors = 18 , tracks = 80 ):
241+ def __init__ (self , floppy , heads = 2 , sectors = 18 , tracks = 80 , flux_buffer = None , t1_nom_ns : float = 1000 ):
254242 self .floppy = floppy
255243 self .heads = heads
256244 self .sectors = sectors
257245 self .tracks = tracks
246+ self .flux_buffer = flux_buffer or buffer (sectors * 12 * 512 )
258247 self .track0side0_cache = memoryview (bytearray (sectors * 512 ))
248+ self .track0side0_validity = bytearray (sectors )
249+ self .track_cache = memoryview (bytearray (sectors * 512 ))
250+ self .track_validity = bytearray (sectors )
259251
260- self .floppy .track = 0
261- self .floppy .head = 0
262- floppyio .mfm_readinto (self .track0side0_cache , floppy ._rddata , floppy ._index )
252+ self ._t2_5_max = round (2.5 * t1_nom_ns * floppyio .samplerate * 1e-9 )
253+ self ._t3_5_max = round (3.5 * t1_nom_ns * floppyio .samplerate * 1e-9 )
254+
255+ self ._track_read (self .track0side0_cache , self .track0side0_validity , 0 , 0 )
263256
264- self .track_cache = memoryview (bytearray (sectors * 512 ))
265257 self .cached_track = - 1
266258 self .cached_side = - 1
267259
260+
268261 def deinit (self ):
269- """Deinitialize this object (does nothing)"""
262+ """Deinitialize this object"""
263+ self .floppy .deinit ()
264+ del self .flux_buffer
265+ del self .track0side0_cache
266+ del self .track_validity
270267
271268 def sync (self ):
272269 """Write out any pending data to disk (does nothing)"""
273270
274271 def writeblocks (self , start , buf ): # pylint: disable=no-self-use
275272 """Write to the floppy (always raises an exception)"""
276- raise IOError ("Read-only filesystem" )
273+ raise OSError ("Read-only filesystem" )
277274
278275 def count (self ):
279276 """Return the floppy capacity in 512-byte units"""
@@ -287,27 +284,37 @@ def readblocks(self, start_block, buf):
287284
288285 def _readblock (self , block , buf ):
289286 if block > self .count ():
290- raise IOError ("Read past end of media" )
287+ raise OSError ("Read past end of media" )
291288 track = block // (self .heads * self .sectors )
292289 block %= self .heads * self .sectors
293290 side = block // (self .sectors )
294291 block %= self .sectors
295- trackdata = self ._get_track_data (track , side )
292+ trackdata , validity = self ._get_track_data (track , side )
293+ if not validity [block ]:
294+ raise OSError (f"Failed to read sector { track } /{ side } /{ block } " )
296295 buf [:] = trackdata [block * 512 : (block + 1 ) * 512 ]
297296
298297 def _get_track_data (self , track , side ):
299298 if track == 0 and side == 0 :
300- return self .track0side0_cache
299+ return self .track0side0_cache , self . track0side0_validity
301300 if track != self .cached_track or side != self .cached_side :
302- self .floppy .selected = True
303- self .floppy .spin = True
304- self .floppy .track = track
305- self .floppy .side = side
306- self .floppy .mfm_readinto (
307- self .track_cache ,
308- )
309- self .floppy .spin = False
310- self .floppy .selected = False
311- self .cached_track = track
312- self .cached_side = side
313- return self .track_cache
301+ self ._track_read (self .track_cache , self .track_validity , track , side )
302+ return self .track_cache , self .track_validity
303+
304+ def _track_read (self , track_data , validity , track , side ):
305+ self .floppy .selected = True
306+ self .floppy .spin = True
307+ self .floppy .track = track
308+ self .floppy .side = side
309+ self ._mfm_readinto (track_data , validity )
310+ self .floppy .spin = False
311+ self .floppy .selected = False
312+ self .cached_track = track
313+ self .cached_side = side
314+
315+ def _mfm_readinto (self , track_data , validity ):
316+ for i in range (5 ):
317+ self .floppy .flux_readinto (self .flux_buffer )
318+ print ("timing bins" , self ._t2_5_max , self ._t3_5_max )
319+ n = floppyio .mfm_readinto (track_data , self .flux_buffer , self ._t2_5_max , self ._t3_5_max , validity , i == 0 )
320+ if n == self .sectors : break
0 commit comments