| 
					
				 | 
			
			
				@@ -185,9 +185,9 @@ class Unit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return flux[:-1] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ## encode_flux: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ## _encode_flux: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ## Convert the given flux timings into an encoded data stream. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def encode_flux(self, flux): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def _encode_flux(self, flux): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         dat = bytearray() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         for val in flux: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if val == 0: 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -209,9 +209,9 @@ class Unit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return dat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ## read_track: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ## Read and decode flux and index timings for the current track. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def read_track(self, nr_revs): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ## _read_track: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ## Private helper which issues command requests to Greaseweazle. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def _read_track(self, nr_revs): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         # Request and read all flux timings for this track. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         dat = bytearray() 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -222,12 +222,29 @@ class Unit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if dat[-1] == 0: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Check flux status. We bail if there was an error. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self._send_cmd(struct.pack("2B", Cmd.GetFluxStatus, 2)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        except CmdError as error: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            del dat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return error.code, None 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # Check flux status. An exception is raised if there was an error. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        self._send_cmd(struct.pack("2B", Cmd.GetFluxStatus, 2)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return dat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ## read_track: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ## Read and decode flux and index timings for the current track. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def read_track(self, nr_revs, nr_retries=5): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        retry = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        while True: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                dat = self._read_track(nr_revs) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            except CmdError as error: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                # An error occurred. We may retry on transient overflows. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if error.code == Ack.FluxOverflow and retry < nr_retries: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    retry += 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    raise error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                # Success! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         # Decode the flux list and read the index-times list. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         flux_list = self._decode_flux(dat) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -247,20 +264,33 @@ class Unit: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         index_list = index_list[1:] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         # Success: Return the requested full index-to-index revolutions. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return Ack.Okay, Flux(index_list, flux_list, self.sample_freq) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return Flux(index_list, flux_list, self.sample_freq) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ## write_track: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ## Write the given data stream to the current track via Greaseweazle. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def write_track(self, dat): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self._send_cmd(struct.pack("<2BIB", Cmd.WriteFlux, 7, 0, 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.ser.write(dat) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.ser.read(1) # Sync with Greaseweazle 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self._send_cmd(struct.pack("2B", Cmd.GetFluxStatus, 2)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        except CmdError as error: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return error.code 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return Ack.Okay 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    ## Write the given flux stream to the current track via Greaseweazle. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    def write_track(self, flux_list, nr_retries=5): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        # Create encoded data stream. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        dat = self._encode_flux(flux_list) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+         
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        retry = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        while True: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                # Write the flux stream to the track via Greaseweazle. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self._send_cmd(struct.pack("<2BIB", Cmd.WriteFlux, 7, 0, 1)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.ser.write(dat) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self.ser.read(1) # Sync with Greaseweazle 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                self._send_cmd(struct.pack("2B", Cmd.GetFluxStatus, 2)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            except CmdError as error: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                # An error occurred. We may retry on transient underflows. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if error.code == Ack.FluxUnderflow and retry < nr_retries: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    retry += 1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    raise error 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                # Success! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                break 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     ## 
			 |