Эх сурвалжийг харах

ipf: Handle weak data regions

Keir Fraser 4 жил өмнө
parent
commit
c76f4d3921

+ 14 - 11
scripts/greaseweazle/image/ipf.py

@@ -175,21 +175,20 @@ class IPF:
         trackbuf.frombytes(bytes(carray))
         trackbuf = trackbuf[:ti.tracklen]
 
-        # Write splice is at trackbuf[ti.overlap]. Index is at trackbuf[0].
         #for i in range(ti.sectorcnt):
         #    si = CapsSectorInfo()
         #    res = self.lib.CAPSGetInfo(ct.byref(si), self.iid,
         #                               cyl, head, 1, i)
         #    error.check(res == 0, "Couldn't get sector info")
-        #    # Data is at trackbuf[si.datastart:si.datastart + si.datasize]
-        #for i in range(ti.weakcnt):
-        #    wi = CapsDataInfo()
-        #    res = self.lib.CAPSGetInfo(ct.byref(wi), self.iid,
-        #                               cyl, head, 2, i)
-        #    error.check(res == 0, "Couldn't get weak data info")
-        #    # Weak data at trackbuf[wi.start:wi.start + wi.size]
+        #    range.append((si.datastart, si.datasize))
 
-        error.check(ti.weakcnt == 0, "Can't yet handle weak data")
+        weak = []
+        for i in range(ti.weakcnt):
+            wi = CapsDataInfo()
+            res = self.lib.CAPSGetInfo(ct.byref(wi), self.iid,
+                                       cyl, head, 2, i)
+            error.check(res == 0, "Couldn't get weak data info")
+            weak.append((wi.start, wi.size))
 
         timebuf = None
         if ti.timebuf:
@@ -211,8 +210,12 @@ class IPF:
         # So we assume a rotation rate of 300 RPM (5 rev/sec).
         rpm = 300
                 
-        track = MasterTrack(trackbuf, 60/rpm)
-        track.bit_ticks, track.splice = timebuf, ti.overlap
+        track = MasterTrack(
+            bits = trackbuf,
+            time_per_rev = 60/rpm,
+            bit_ticks = timebuf,
+            splice = ti.overlap,
+            weak = weak)
         return track
 
 

+ 41 - 7
scripts/greaseweazle/track.py

@@ -14,26 +14,32 @@ class MasterTrack:
 
     @property
     def bitrate(self):
-        return len(self.bitarray) / self.time_per_rev
+        return len(self.bits) / self.time_per_rev
 
     # bits: Track bitcell data (bitarray)
     # time_per_rev: Time per revolution, in seconds (float)
     # bit_ticks: Per-bitcell time values, in unitless 'ticks'
     # splice: Location of the track splice, in bitcells, after the index.
-    def __init__(self, bits, time_per_rev):
+    # weak: List of (start, length) weak ranges
+    def __init__(self, bits, time_per_rev, bit_ticks=None, splice=0, weak=[]):
         self.bits = bits
         self.time_per_rev = time_per_rev
-        self.bit_ticks = None
-        self.splice = 0
+        self.bit_ticks = bit_ticks
+        self.splice = splice
+        self.weak = weak
 
     def __str__(self):
-        s = "\nMaster Track:\n"
+        s = "\nMaster Track: splice at %d\n" % self.splice
         s += (" %d bits, %.1f kbit/s"
               % (len(self.bits), self.bitrate))
         if self.bit_ticks:
             s += " (variable)"
-        s += ("\n Total Time = %.1f ms (%.1f rpm)\n "
+        s += ("\n %.1f ms / rev (%.1f rpm)"
               % (self.time_per_rev * 1000, 60 / self.time_per_rev))
+        if len(self.weak) > 0:
+            s += "\n %d weak range" % len(self.weak)
+            if len(self.weak) > 1: s += "s"
+            s += ": " + ", ".join(str(n) for _,n in self.weak) + " bits"
         #s += str(binascii.hexlify(self.bits.tobytes()))
         return s
 
@@ -48,6 +54,34 @@ class MasterTrack:
         bit_ticks = self.bit_ticks.copy() if self.bit_ticks else [1] * bitlen
         ticks_to_index = sum(bit_ticks)
 
+        # Weak regions need special processing for correct flux representation.
+        for s,n in self.weak:
+            e = s + n
+            assert s+n <= bitlen
+            if n < 2:
+                continue
+            if n < 400:
+                # Short weak regions are written with no flux transitions.
+                bits[s:e] = bitarray([0]) * n
+            else:
+                # Long weak regions we present a fuzzy clock bit in an
+                # otherwise normal byte (16 bits MFM). The byte may be
+                # interpreted as
+                # MFM 0001001010100101 = 12A5 = byte 0x43, or
+                # MFM 0001001010010101 = 1295 = byte 0x47
+                pattern = bitarray(endian="big")
+                pattern.frombytes(b"\x12\xA5")
+                bits[s:e] = (pattern * (n//16+1))[:n]
+                for i in range(0, n-10, 16):
+                    x, y = bit_ticks[s+i+10], bit_ticks[s+i+11]
+                    bit_ticks[s+i+10], bit_ticks[s+i+11] = x+y*0.5, y*0.5
+            # To prevent corrupting a preceding sync word by effectively
+            # starting the weak region early, we start with a 1 if we just
+            # clocked out a 0.
+            bits[s] = not (bits[-1] if s == 0 else bits[s-1])
+            # Similarly modify the last bit of the weak region.
+            bits[e-1] = not(bits[e-2] or bits[e%bitlen])
+        
         splice_at_index = self.splice < 4 or bitlen - self.splice < 4
 
         if splice_at_index:
@@ -94,7 +128,7 @@ class MasterTrack:
 
         # Package up the flux for return.
         flux = Flux([ticks_to_index], flux_list,
-                    self.time_per_rev / ticks_to_index)
+                    ticks_to_index / self.time_per_rev)
         flux.terminate_at_index = splice_at_index
         return flux