Browse Source

gw: TrackSet has an iterator. Also allow side-cyl offsets to be specified.

Keir Fraser 4 years ago
parent
commit
03b7a3413e

+ 5 - 5
scripts/greaseweazle/tools/erase.py

@@ -22,11 +22,11 @@ def erase(usb, args):
     drive_ticks = (flux.index_list[0] + flux.index_list[1]) / 2
     del flux
 
-    for cyl in range(args.tracks.cyl[0], args.tracks.cyl[1]+1):
-        for side in range(args.tracks.side[0], args.tracks.side[1]+1):
-            print("\rErasing Track %u.%u..." % (cyl, side), end="")
-            usb.seek((cyl, cyl*2)[args.tracks.double_step], side)
-            usb.erase_track(drive_ticks * 1.1)
+    for t in args.tracks:
+        cyl, side = t.cyl, t.side
+        print("\rErasing Track %u.%u..." % (cyl, side), end="")
+        usb.seek(t.physical_cyl, side)
+        usb.erase_track(drive_ticks * 1.1)
 
     print()
 

+ 7 - 7
scripts/greaseweazle/tools/read.py

@@ -106,13 +106,13 @@ def read_to_image(usb, args, image, decoder=None):
 
     summary = [[],[]]
 
-    for cyl in range(args.tracks.cyl[0], args.tracks.cyl[1]+1):
-        for side in range(args.tracks.side[0], args.tracks.side[1]+1):
-            usb.seek((cyl, cyl*2)[args.tracks.double_step], side)
-            dat = read_with_retry(usb, args, cyl, side, decoder)
-            print("T%u.%u: %s" % (cyl, side, dat.summary_string()))
-            summary[side].append(dat)
-            image.emit_track(cyl, side, dat)
+    for t in args.tracks:
+        cyl, side = t.cyl, t.side
+        usb.seek(t.physical_cyl, side)
+        dat = read_with_retry(usb, args, cyl, side, decoder)
+        print("T%u.%u: %s" % (cyl, side, dat.summary_string()))
+        summary[side].append(dat)
+        image.emit_track(cyl, side, dat)
 
     if decoder is not None:
         print_summary(args, summary)

+ 47 - 17
scripts/greaseweazle/tools/util.py

@@ -51,23 +51,50 @@ def range_str(s, e):
     if s != e: str += "-%d" % e
     return str
 
+class TrackSet:
+
+    class TrackIter:
+        def __init__(self, ts):
+            l = []
+            for c in range(ts.cyl[0], ts.cyl[1]+1):
+                for s in range(ts.side[0], ts.side[1]+1):
+                    pc = (c, c*2)[ts.double_step]
+                    pc += ts.side_off[0] if s == ts.side[0] else ts.side_off[1]
+                    l.append((pc, s, c))
+            l.sort()
+            self.l = iter(l)
+        def __next__(self):
+            self.physical_cyl, self.side, self.cyl = next(self.l)
+            return self
+    
+    def __init__(self):
+        self.cyl = (0,79)
+        self.side = (0,1)
+        self.double_step = False
+
+    def __str__(self):
+        a, b = self.cyl
+        s = 'c=%d' % a
+        if a != b: s += '-%d' % b
+        if self.double_step: s += 'x2'
+        a, c = self.side
+        b, d = self.side_off
+        s += ':s=%d' % a
+        if b != 0: s += '[%s%d]' % ('+' if b >= 0 else '', b)
+        if a != c:
+            s += '-%d' % c
+            if d != 0: s += '[%s%d]' % ('+' if d >= 0 else '', d)
+        return s
+
+    def __iter__(self):
+        return self.TrackIter(self)
+
 def trackset(tracks):
-    class TrackSet:
-        def __init__(self):
-            self.cyl = (0,79)
-            self.side = (0,1)
-            self.double_step = False
-        def __str__(self):
-            s = 'c=%s' % range_str(self.cyl[0], self.cyl[1])
-            if self.double_step:
-                s += 'x2'
-            s += ':s=%s' % range_str(self.side[0], self.side[1])
-            return s
     ts = TrackSet()
     for x in tracks.split(':'):
         k,v = x.split('=')
         if k == 'c':
-            m = re.match('(\d+)(-(\d+))?(x2)?', v)
+            m = re.match('(\d+)(-(\d+))?(x2)?$', v)
             if m is None: raise ValueError()
             if m.group(3) is None:
                 ts.cyl = int(m.group(1)), int(m.group(1))
@@ -76,12 +103,15 @@ def trackset(tracks):
             if m.group(4) is not None:
                 ts.double_step = True
         elif k == 's':
-            m = re.match('(\d+)(-(\d+))?', v)
+            m = re.match('(?P<s>\d+)(\[(?P<s_off>[-+]\d)\])?'
+                         '(-(?P<e>\d+)(\[(?P<e_off>[-+]\d)\])?)?$', v)
             if m is None: raise ValueError()
-            if m.group(3) is None:
-                ts.side = int(m.group(1)), int(m.group(1))
-            else:
-                ts.side = int(m.group(1)), int(m.group(3))
+            s, e = m.group('s'), m.group('e')
+            ts.side = int(s), int(e if e is not None else s)
+            s, e = m.group('s_off'), m.group('e_off')
+            s = int(s) if s is not None else 0
+            e = int(e) if e is not None else 0
+            ts.side_off = s,e
     return ts
 
 

+ 50 - 49
scripts/greaseweazle/tools/write.py

@@ -44,60 +44,61 @@ def write_from_image(usb, args, image):
 
     verified_count, not_verified_count = 0, 0
 
-    for cyl in range(args.tracks.cyl[0], args.tracks.cyl[1]+1):
-        for side in range(args.tracks.side[0], args.tracks.side[1]+1):
+    for t in args.tracks:
 
-            track = image.get_track(cyl, side)
-            if track is None and not args.erase_empty:
-                continue
+        cyl, side = t.cyl, t.side
 
-            print("\r%sing Track %u.%u..." %
-                  ("Writ" if track is not None else "Eras", cyl, side),
-                  end="", flush=True)
-            usb.seek((cyl, cyl*2)[args.tracks.double_step], side)
+        track = image.get_track(cyl, side)
+        if track is None and not args.erase_empty:
+            continue
+
+        print("\r%sing Track %u.%u..." %
+              ("Writ" if track is not None else "Eras", cyl, side),
+              end="", flush=True)
+        usb.seek(t.physical_cyl, side)
             
-            if track is None:
-                usb.erase_track(drive_ticks * 1.1)
-                continue
+        if track is None:
+            usb.erase_track(drive_ticks * 1.1)
+            continue
 
-            flux = track.flux_for_writeout()
+        flux = track.flux_for_writeout()
             
-            # @factor adjusts flux times for speed variations between the
-            # read-in and write-out drives.
-            factor = drive_ticks / flux.index_list[0]
-
-            # Convert the flux samples to Greaseweazle sample frequency.
-            rem = 0.0
-            flux_list = []
-            for x in flux.list:
-                y = x * factor + rem
-                val = round(y)
-                rem = y - val
-                flux_list.append(val)
-
-            # Encode the flux times for Greaseweazle, and write them out.
-            formatter = Formatter()
-            verified = False
-            for retry in range(3):
-                usb.write_track(flux_list, flux.terminate_at_index)
-                try:
-                    no_verify = args.no_verify or track.verify is None
-                except AttributeError: # track.verify undefined
-                    no_verify = True
-                if no_verify:
-                    not_verified_count += 1
-                    verified = True
-                    break
-                v_revs = 1 if track.splice == 0 else 2
-                v_flux = usb.read_track(v_revs)
-                v_flux.scale(flux.mean_index_time / v_flux.mean_index_time)
-                verified = track.verify.verify_track(v_flux)
-                if verified:
-                    verified_count += 1
-                    break
-                formatter.print(" Retry %d" % (retry + 1))
-            formatter.erase()
-            error.check(verified, "Failed to write Track %u.%u" % (cyl, side))
+        # @factor adjusts flux times for speed variations between the
+        # read-in and write-out drives.
+        factor = drive_ticks / flux.index_list[0]
+
+        # Convert the flux samples to Greaseweazle sample frequency.
+        rem = 0.0
+        flux_list = []
+        for x in flux.list:
+            y = x * factor + rem
+            val = round(y)
+            rem = y - val
+            flux_list.append(val)
+
+        # Encode the flux times for Greaseweazle, and write them out.
+        formatter = Formatter()
+        verified = False
+        for retry in range(3):
+            usb.write_track(flux_list, flux.terminate_at_index)
+            try:
+                no_verify = args.no_verify or track.verify is None
+            except AttributeError: # track.verify undefined
+                no_verify = True
+            if no_verify:
+                not_verified_count += 1
+                verified = True
+                break
+            v_revs = 1 if track.splice == 0 else 2
+            v_flux = usb.read_track(v_revs)
+            v_flux.scale(flux.mean_index_time / v_flux.mean_index_time)
+            verified = track.verify.verify_track(v_flux)
+            if verified:
+                verified_count += 1
+                break
+            formatter.print(" Retry %d" % (retry + 1))
+        formatter.erase()
+        error.check(verified, "Failed to write Track %u.%u" % (cyl, side))
 
     print()
     if not_verified_count == 0: