|  | @@ -8,228 +8,22 @@
 | 
	
		
			
				|  |  |  # See the file COPYING for more details, or visit <http://unlicense.org>.
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  import crcmod.predefined
 | 
	
		
			
				|  |  | -import sys, struct, argparse, serial, collections
 | 
	
		
			
				|  |  | +import sys, struct, argparse, serial
 | 
	
		
			
				|  |  |  from timeit import default_timer as timer
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -from greaseweazle import version
 | 
	
		
			
				|  |  | +from greaseweazle import version, USB
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  # 40MHz
 | 
	
		
			
				|  |  |  scp_freq = 40000000
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -BAUD_CLEAR_COMMS    = 10000
 | 
	
		
			
				|  |  | -BAUD_NORMAL         = 9600
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -CMD_GET_INFO        =  0
 | 
	
		
			
				|  |  | -CMD_SEEK            =  1
 | 
	
		
			
				|  |  | -CMD_SIDE            =  2
 | 
	
		
			
				|  |  | -CMD_SET_PARAMS      =  3
 | 
	
		
			
				|  |  | -CMD_GET_PARAMS      =  4
 | 
	
		
			
				|  |  | -CMD_MOTOR           =  5
 | 
	
		
			
				|  |  | -CMD_READ_FLUX       =  6
 | 
	
		
			
				|  |  | -CMD_WRITE_FLUX      =  7
 | 
	
		
			
				|  |  | -CMD_GET_FLUX_STATUS =  8
 | 
	
		
			
				|  |  | -CMD_GET_INDEX_TIMES =  9
 | 
	
		
			
				|  |  | -CMD_SELECT          = 10
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -# Bootloader-specific:
 | 
	
		
			
				|  |  | -CMD_UPDATE          = 1
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ACK_OKAY            = 0
 | 
	
		
			
				|  |  | -ACK_BAD_COMMAND     = 1
 | 
	
		
			
				|  |  | -ACK_NO_INDEX        = 2
 | 
	
		
			
				|  |  | -ACK_NO_TRK0         = 3
 | 
	
		
			
				|  |  | -ACK_FLUX_OVERFLOW   = 4
 | 
	
		
			
				|  |  | -ACK_FLUX_UNDERFLOW  = 5
 | 
	
		
			
				|  |  | -ACK_WRPROT          = 6
 | 
	
		
			
				|  |  | -ACK_MAX             = 6
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -# CMD_{GET,SET}_PARAMS:
 | 
	
		
			
				|  |  | -PARAMS_DELAYS       = 0
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -ack_str = [
 | 
	
		
			
				|  |  | -  "Okay", "Bad Command", "No Index", "Track 0 not found",
 | 
	
		
			
				|  |  | -  "Flux Overflow", "Flux Underflow", "Disk is Write Protected" ]
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -class CmdError(Exception):
 | 
	
		
			
				|  |  | -  def __init__(self, cmd, code):
 | 
	
		
			
				|  |  | -    self.cmd = cmd
 | 
	
		
			
				|  |  | -    self.code = code
 | 
	
		
			
				|  |  | -  def __str__(self):
 | 
	
		
			
				|  |  | -    if self.code <= ACK_MAX:
 | 
	
		
			
				|  |  | -      return ack_str[self.code]
 | 
	
		
			
				|  |  | -    return "Unknown Error (%u)" % self.code
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def send_cmd(cmd):
 | 
	
		
			
				|  |  | -  ser.write(cmd)
 | 
	
		
			
				|  |  | -  (c,r) = struct.unpack("2B", ser.read(2))
 | 
	
		
			
				|  |  | -  assert c == cmd[0]
 | 
	
		
			
				|  |  | -  if r != 0:
 | 
	
		
			
				|  |  | -    raise CmdError(c,r)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def get_fw_info():
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("4B", CMD_GET_INFO, 4, 0, 8))
 | 
	
		
			
				|  |  | -  return struct.unpack("<4BI", ser.read(8))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def print_fw_info(info):
 | 
	
		
			
				|  |  | -  (major, minor, max_index, max_cmd, freq) = info
 | 
	
		
			
				|  |  | -  print("Greaseweazle v%u.%u" % (major, minor))
 | 
	
		
			
				|  |  | -  print("Max index timings %u" % (max_index))
 | 
	
		
			
				|  |  | -  print("Max cmd %u" % (max_cmd))
 | 
	
		
			
				|  |  | -  print("Sample frequency: %.2f MHz" % (freq / 1000000))
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -def seek(cyl, side):
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("3B", CMD_SEEK, 3, cyl))
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("3B", CMD_SIDE, 3, side))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def get_delays():
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("4B", CMD_GET_PARAMS, 4, PARAMS_DELAYS, 5*2))
 | 
	
		
			
				|  |  | -  return struct.unpack("<5H", ser.read(5*2))
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -def print_delays(x):
 | 
	
		
			
				|  |  | -  (select_delay, step_delay, seek_settle, motor_delay, auto_off) = x
 | 
	
		
			
				|  |  | -  print("Select Delay: %uus" % select_delay)
 | 
	
		
			
				|  |  | -  print("Step Delay: %uus" % step_delay)
 | 
	
		
			
				|  |  | -  print("Settle Time: %ums" % seek_settle)
 | 
	
		
			
				|  |  | -  print("Motor Delay: %ums" % motor_delay)
 | 
	
		
			
				|  |  | -  print("Auto Off: %ums" % auto_off)
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def set_delays(seek_delay = None, step_delay = None, seek_settle = None,
 | 
	
		
			
				|  |  | -               motor_delay = None, auto_off = None):
 | 
	
		
			
				|  |  | -  (_seek_delay, _step_delay, _seek_settle,
 | 
	
		
			
				|  |  | -   _motor_delay, _auto_off) = get_delays()
 | 
	
		
			
				|  |  | -  if not seek_delay: seek_delay = _seek_delay
 | 
	
		
			
				|  |  | -  if not step_delay: step_delay = _step_delay
 | 
	
		
			
				|  |  | -  if not seek_settle: seek_settle = _seek_settle
 | 
	
		
			
				|  |  | -  if not motor_delay: motor_delay = _motor_delay
 | 
	
		
			
				|  |  | -  if not auto_off: auto_off = _auto_off
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("<3B5H", CMD_SET_PARAMS, 3+5*2, PARAMS_DELAYS,
 | 
	
		
			
				|  |  | -                       seek_delay, step_delay, seek_settle,
 | 
	
		
			
				|  |  | -                       motor_delay, auto_off))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def drive_select(state):
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("3B", CMD_SELECT, 3, int(state)))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def drive_motor(state):
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("3B", CMD_MOTOR, 3, int(state)))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def get_index_times(nr):
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("4B", CMD_GET_INDEX_TIMES, 4, 0, nr))
 | 
	
		
			
				|  |  | -  x = struct.unpack("<%dI" % nr, ser.read(4*nr))
 | 
	
		
			
				|  |  | -  return x
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -def print_index_times(index_times):
 | 
	
		
			
				|  |  | -  for ticks in index_times:
 | 
	
		
			
				|  |  | -    print("%u ticks" % (ticks))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -# write_flux:
 | 
	
		
			
				|  |  | -# Write the current track via Greaseweazle with the specified flux timings.
 | 
	
		
			
				|  |  | -def write_flux(flux):
 | 
	
		
			
				|  |  | -  start = timer()
 | 
	
		
			
				|  |  | -  x = bytearray()
 | 
	
		
			
				|  |  | -  for val in flux:
 | 
	
		
			
				|  |  | -    if val == 0:
 | 
	
		
			
				|  |  | -      pass
 | 
	
		
			
				|  |  | -    elif val < 250:
 | 
	
		
			
				|  |  | -      x.append(val)
 | 
	
		
			
				|  |  | -    else:
 | 
	
		
			
				|  |  | -      high = val // 250
 | 
	
		
			
				|  |  | -      if high <= 5:
 | 
	
		
			
				|  |  | -        x.append(249+high)
 | 
	
		
			
				|  |  | -        x.append(1 + val%250)
 | 
	
		
			
				|  |  | -      else:
 | 
	
		
			
				|  |  | -        x.append(255)
 | 
	
		
			
				|  |  | -        x.append(1 | (val<<1) & 255)
 | 
	
		
			
				|  |  | -        x.append(1 | (val>>6) & 255)
 | 
	
		
			
				|  |  | -        x.append(1 | (val>>13) & 255)
 | 
	
		
			
				|  |  | -        x.append(1 | (val>>20) & 255)
 | 
	
		
			
				|  |  | -  x.append(0) # End of Stream
 | 
	
		
			
				|  |  | -  end = timer()
 | 
	
		
			
				|  |  | -  #print("%u flux -> %u bytes in %f seconds" % (len(flux), len(x), end-start))
 | 
	
		
			
				|  |  | -  retry = 0
 | 
	
		
			
				|  |  | -  while True:
 | 
	
		
			
				|  |  | -    start = timer()
 | 
	
		
			
				|  |  | -    send_cmd(struct.pack("<2BIB", CMD_WRITE_FLUX, 7, 0, 1))
 | 
	
		
			
				|  |  | -    ser.write(x)
 | 
	
		
			
				|  |  | -    ser.read(1) # Sync with Greaseweazle
 | 
	
		
			
				|  |  | -    try:
 | 
	
		
			
				|  |  | -      send_cmd(struct.pack("2B", CMD_GET_FLUX_STATUS, 2))
 | 
	
		
			
				|  |  | -    except CmdError as error:
 | 
	
		
			
				|  |  | -      if error.code == ACK_FLUX_UNDERFLOW and retry < 5:
 | 
	
		
			
				|  |  | -        retry += 1
 | 
	
		
			
				|  |  | -        print("Retry #%u..." % retry)
 | 
	
		
			
				|  |  | -        continue;
 | 
	
		
			
				|  |  | -      raise
 | 
	
		
			
				|  |  | -    end = timer()
 | 
	
		
			
				|  |  | -    #print("Track written in %f seconds" % (end-start))
 | 
	
		
			
				|  |  | -    break
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -# read_flux:
 | 
	
		
			
				|  |  | -# Read flux timings from Greaseweazle for the current track.
 | 
	
		
			
				|  |  | -def read_flux(nr_idx):
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  # Read the encoded flux stream, retrying if necessary.
 | 
	
		
			
				|  |  | -  retry = 0
 | 
	
		
			
				|  |  | -  while True:
 | 
	
		
			
				|  |  | -    start = timer()
 | 
	
		
			
				|  |  | -    x = collections.deque()
 | 
	
		
			
				|  |  | -    send_cmd(struct.pack("3B", CMD_READ_FLUX, 3, nr_idx))
 | 
	
		
			
				|  |  | -    nr = 0
 | 
	
		
			
				|  |  | -    while True:
 | 
	
		
			
				|  |  | -      x += ser.read(1)
 | 
	
		
			
				|  |  | -      x += ser.read(ser.in_waiting)
 | 
	
		
			
				|  |  | -      nr += 1;
 | 
	
		
			
				|  |  | -      if x[-1] == 0:
 | 
	
		
			
				|  |  | -        break
 | 
	
		
			
				|  |  | -    try:
 | 
	
		
			
				|  |  | -      send_cmd(struct.pack("2B", CMD_GET_FLUX_STATUS, 2))
 | 
	
		
			
				|  |  | -    except CmdError as error:
 | 
	
		
			
				|  |  | -      if error.code == ACK_FLUX_OVERFLOW and retry < 5:
 | 
	
		
			
				|  |  | -        retry += 1
 | 
	
		
			
				|  |  | -        print("Retry #%u..." % retry)
 | 
	
		
			
				|  |  | -        del x
 | 
	
		
			
				|  |  | -        continue;
 | 
	
		
			
				|  |  | -      raise
 | 
	
		
			
				|  |  | -    end = timer()
 | 
	
		
			
				|  |  | -    break
 | 
	
		
			
				|  |  | -    
 | 
	
		
			
				|  |  | -  #print("Read %u bytes in %u batches in %f seconds" % (len(x), nr, end-start))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  # Decode the flux stream into a list of flux samples.
 | 
	
		
			
				|  |  | -  start = timer()
 | 
	
		
			
				|  |  | -  y = []
 | 
	
		
			
				|  |  | -  while x:
 | 
	
		
			
				|  |  | -    i = x.popleft()
 | 
	
		
			
				|  |  | -    if i < 250:
 | 
	
		
			
				|  |  | -      y.append(i)
 | 
	
		
			
				|  |  | -    elif i == 255:
 | 
	
		
			
				|  |  | -      val =  (x.popleft() & 254) >>  1
 | 
	
		
			
				|  |  | -      val += (x.popleft() & 254) <<  6
 | 
	
		
			
				|  |  | -      val += (x.popleft() & 254) << 13
 | 
	
		
			
				|  |  | -      val += (x.popleft() & 254) << 20
 | 
	
		
			
				|  |  | -      y.append(val)
 | 
	
		
			
				|  |  | -    else:
 | 
	
		
			
				|  |  | -      val = (i - 249) * 250
 | 
	
		
			
				|  |  | -      val += x.popleft() - 1
 | 
	
		
			
				|  |  | -      y.append(val)
 | 
	
		
			
				|  |  | -  assert y[-1] == 0
 | 
	
		
			
				|  |  | -  y = y[:-1]
 | 
	
		
			
				|  |  | -  end = timer()
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  #print("Processed %u flux values in %f seconds" % (len(y), end-start))
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -  return y
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  # flux_to_scp:
 | 
	
		
			
				|  |  |  # Converts Greaseweazle flux samples into a Supercard Pro Track.
 | 
	
		
			
				|  |  |  # Returns the Track Data Header (TDH) and the SCP "bitcell" array.
 | 
	
		
			
				|  |  |  def flux_to_scp(flux, track, nr_revs):
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  factor = scp_freq / sample_freq
 | 
	
		
			
				|  |  | +  factor = scp_freq / usb.sample_freq
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  index_times = get_index_times(nr_revs+1)
 | 
	
		
			
				|  |  | +  index_times = usb.get_index_times(nr_revs+1)
 | 
	
		
			
				|  |  |    tdh = struct.pack("<3sB", b"TRK", track)
 | 
	
		
			
				|  |  |    dat = bytearray()
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -306,8 +100,16 @@ def read_to_scp(args):
 | 
	
		
			
				|  |  |      side = track & (nr_sides - 1)
 | 
	
		
			
				|  |  |      print("\rReading Track %u.%u..." % (cyl, side), end="")
 | 
	
		
			
				|  |  |      trk_offs.append(len(trk_dat))
 | 
	
		
			
				|  |  | -    seek(cyl, side)
 | 
	
		
			
				|  |  | -    flux = read_flux(args.revs+1)
 | 
	
		
			
				|  |  | +    usb.seek(cyl, side)
 | 
	
		
			
				|  |  | +    for retry in range(1, 5):
 | 
	
		
			
				|  |  | +      (ack, enc_flux) = usb.read_track(args.revs+1)
 | 
	
		
			
				|  |  | +      if ack == USB.Ack.Okay:
 | 
	
		
			
				|  |  | +        break
 | 
	
		
			
				|  |  | +      elif ack == USB.Ack.FluxOverflow and retry < 5:
 | 
	
		
			
				|  |  | +        print("Retry #%u..." % (retry))
 | 
	
		
			
				|  |  | +      else:
 | 
	
		
			
				|  |  | +        raise CmdError(ack)
 | 
	
		
			
				|  |  | +    flux = usb.decode_flux(enc_flux)
 | 
	
		
			
				|  |  |      (tdh, dat) = flux_to_scp(flux, track, args.revs)
 | 
	
		
			
				|  |  |      trk_dat += tdh
 | 
	
		
			
				|  |  |      trk_dat += dat
 | 
	
	
		
			
				|  | @@ -345,7 +147,7 @@ def read_to_scp(args):
 | 
	
		
			
				|  |  |  # write_from_scp:
 | 
	
		
			
				|  |  |  # Writes the specified Supercard Pro image file to floppy disk.
 | 
	
		
			
				|  |  |  def write_from_scp(args):
 | 
	
		
			
				|  |  | -  factor = sample_freq / scp_freq
 | 
	
		
			
				|  |  | +  factor = usb.sample_freq / scp_freq
 | 
	
		
			
				|  |  |    with open(args.file, "rb") as f:
 | 
	
		
			
				|  |  |      dat = f.read()
 | 
	
		
			
				|  |  |    header = struct.unpack("<3s9BI", dat[0:16])
 | 
	
	
		
			
				|  | @@ -363,7 +165,7 @@ def write_from_scp(args):
 | 
	
		
			
				|  |  |      print("\rWriting Track %u.%u..." % (cyl, side), end="")
 | 
	
		
			
				|  |  |      if trk_offs[i] == 0:
 | 
	
		
			
				|  |  |        continue
 | 
	
		
			
				|  |  | -    seek(cyl, side)
 | 
	
		
			
				|  |  | +    usb.seek(cyl, side)
 | 
	
		
			
				|  |  |      thdr = struct.unpack("<3sBIII", dat[trk_offs[i]:trk_offs[i]+16])
 | 
	
		
			
				|  |  |      (sig,_,_,samples,off) = thdr
 | 
	
		
			
				|  |  |      assert sig == b"TRK"
 | 
	
	
		
			
				|  | @@ -379,7 +181,15 @@ def write_from_scp(args):
 | 
	
		
			
				|  |  |        val = int(round(y))
 | 
	
		
			
				|  |  |        rem = y - val
 | 
	
		
			
				|  |  |        flux.append(val)
 | 
	
		
			
				|  |  | -    write_flux(flux)
 | 
	
		
			
				|  |  | +    enc_flux = usb.encode_flux(flux)
 | 
	
		
			
				|  |  | +    for retry in range(1, 5):
 | 
	
		
			
				|  |  | +      ack = usb.write_track(enc_flux)
 | 
	
		
			
				|  |  | +      if ack == USB.Ack.Okay:
 | 
	
		
			
				|  |  | +        break
 | 
	
		
			
				|  |  | +      elif ack == USB.Ack.FluxUnderflow and retry < 5:
 | 
	
		
			
				|  |  | +        print("Retry #%u..." % (retry))
 | 
	
		
			
				|  |  | +      else:
 | 
	
		
			
				|  |  | +        raise CmdError(ack)
 | 
	
		
			
				|  |  |    print()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -397,9 +207,7 @@ def update_firmware(args):
 | 
	
		
			
				|  |  |    if crc16.crcValue != 0:
 | 
	
		
			
				|  |  |      print("%s: Bad CRC" % (args.file))
 | 
	
		
			
				|  |  |    print("Updating to v%u.%u..." % (maj, min))
 | 
	
		
			
				|  |  | -  send_cmd(struct.pack("<2BI", CMD_UPDATE, 6, len(dat)))
 | 
	
		
			
				|  |  | -  ser.write(dat)
 | 
	
		
			
				|  |  | -  (ack,) = struct.unpack("B", ser.read(1))
 | 
	
		
			
				|  |  | +  ack = usb.update_firmware(dat)
 | 
	
		
			
				|  |  |    if ack != 0:
 | 
	
		
			
				|  |  |      print("** UPDATE FAILED: Please retry!")
 | 
	
		
			
				|  |  |      return
 | 
	
	
		
			
				|  | @@ -437,24 +245,19 @@ def _main(argv):
 | 
	
		
			
				|  |  |      print(", ".join(str(key) for key in actions.keys()))
 | 
	
		
			
				|  |  |      return
 | 
	
		
			
				|  |  |    
 | 
	
		
			
				|  |  | -  global ser
 | 
	
		
			
				|  |  | -  ser = serial.Serial(args.device)
 | 
	
		
			
				|  |  | -  ser.baudrate = BAUD_CLEAR_COMMS
 | 
	
		
			
				|  |  | -  ser.baudrate = BAUD_NORMAL
 | 
	
		
			
				|  |  | -  ser.reset_input_buffer()
 | 
	
		
			
				|  |  | +  global usb
 | 
	
		
			
				|  |  | +  usb = USB.Unit(serial.Serial(args.device))
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  global sample_freq
 | 
	
		
			
				|  |  | -  info = get_fw_info()
 | 
	
		
			
				|  |  | -  sample_freq = info[4]
 | 
	
		
			
				|  |  | -  update_mode = (info[2] == 0)
 | 
	
		
			
				|  |  | +  update_mode = (usb.max_index == 0)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    print("** %s v%u.%u, Host Tools v%u.%u"
 | 
	
		
			
				|  |  | -        % (("Greaseweazle","Bootloader")[update_mode], info[0], info[1],
 | 
	
		
			
				|  |  | +        % (("Greaseweazle","Bootloader")[update_mode],
 | 
	
		
			
				|  |  | +           usb.major, usb.minor,
 | 
	
		
			
				|  |  |             version.major, version.minor))
 | 
	
		
			
				|  |  |    
 | 
	
		
			
				|  |  |    if (not update_mode
 | 
	
		
			
				|  |  | -      and (version.major > info[0]
 | 
	
		
			
				|  |  | -           or (version.major == info[0] and version.minor > info[1]))):
 | 
	
		
			
				|  |  | +      and (version.major > usb.major
 | 
	
		
			
				|  |  | +           or (version.major == usb.major and version.minor > usb.minor))):
 | 
	
		
			
				|  |  |      print("Firmware is out of date: Require >= v%u.%u"
 | 
	
		
			
				|  |  |            % (version.major, version.minor))
 | 
	
		
			
				|  |  |      print("Install the Update Jumper and \"update <update_file>\"")
 | 
	
	
		
			
				|  | @@ -463,7 +266,7 @@ def _main(argv):
 | 
	
		
			
				|  |  |    if update_mode and args.action != "update":
 | 
	
		
			
				|  |  |      print("Greaseweazle is in Firmware Update Mode:")
 | 
	
		
			
				|  |  |      print(" The only available action is \"update <update_file>\"")
 | 
	
		
			
				|  |  | -    if info[4] & 1:
 | 
	
		
			
				|  |  | +    if usb.sample_freq & 1:
 | 
	
		
			
				|  |  |        print(" Remove the Update Jumper for normal operation")
 | 
	
		
			
				|  |  |      else:
 | 
	
		
			
				|  |  |        print(" Main firmware is erased: You *must* perform an update!")
 | 
	
	
		
			
				|  | @@ -473,35 +276,34 @@ def _main(argv):
 | 
	
		
			
				|  |  |      print("Greaseweazle is in Normal Mode:")
 | 
	
		
			
				|  |  |      print(" To \"update\" you must install the Update Jumper")
 | 
	
		
			
				|  |  |      return
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | -  set_delays(step_delay=5000)
 | 
	
		
			
				|  |  | -  print_delays(get_delays())
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if not update_mode:
 | 
	
		
			
				|  |  | -    drive_select(True)
 | 
	
		
			
				|  |  | -    drive_motor(True)
 | 
	
		
			
				|  |  | -  
 | 
	
		
			
				|  |  | +  usb.step_delay = 5000
 | 
	
		
			
				|  |  | +  print("Select Delay: %uus" % usb.select_delay)
 | 
	
		
			
				|  |  | +  print("Step Delay: %uus" % usb.step_delay)
 | 
	
		
			
				|  |  | +  print("Settle Time: %ums" % usb.seek_settle_delay)
 | 
	
		
			
				|  |  | +  print("Motor Delay: %ums" % usb.motor_delay)
 | 
	
		
			
				|  |  | +  print("Auto Off: %ums" % usb.auto_off_delay)
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |    try:
 | 
	
		
			
				|  |  | -    actions[args.action](args)
 | 
	
		
			
				|  |  | -  except:
 | 
	
		
			
				|  |  |      if not update_mode:
 | 
	
		
			
				|  |  | -      ser.reset_output_buffer()
 | 
	
		
			
				|  |  | -      ser.baudrate = BAUD_CLEAR_COMMS
 | 
	
		
			
				|  |  | -      ser.baudrate = BAUD_NORMAL
 | 
	
		
			
				|  |  | -      ser.reset_input_buffer()
 | 
	
		
			
				|  |  | -      drive_motor(False)
 | 
	
		
			
				|  |  | -      drive_select(False)
 | 
	
		
			
				|  |  | -    raise
 | 
	
		
			
				|  |  | -  else:
 | 
	
		
			
				|  |  | +      usb.drive_select(True)
 | 
	
		
			
				|  |  | +      usb.drive_motor(True)
 | 
	
		
			
				|  |  | +    actions[args.action](args)
 | 
	
		
			
				|  |  | +  except KeyboardInterrupt:
 | 
	
		
			
				|  |  | +    print()
 | 
	
		
			
				|  |  | +    usb.reset()
 | 
	
		
			
				|  |  | +    usb.ser.close()
 | 
	
		
			
				|  |  | +    usb.ser.open()
 | 
	
		
			
				|  |  | +  finally:
 | 
	
		
			
				|  |  |      if not update_mode:
 | 
	
		
			
				|  |  | -      drive_motor(False)
 | 
	
		
			
				|  |  | -      drive_select(False)
 | 
	
		
			
				|  |  | +      usb.drive_motor(False)
 | 
	
		
			
				|  |  | +      usb.drive_select(False)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  def main(argv):
 | 
	
		
			
				|  |  |    try:
 | 
	
		
			
				|  |  |      _main(argv)
 | 
	
		
			
				|  |  | -  except CmdError as error:
 | 
	
		
			
				|  |  | +  except USB.CmdError as error:
 | 
	
		
			
				|  |  |      print("Command Failed: %s" % error)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 |