read.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. # greaseweazle/tools/read.py
  2. #
  3. # Greaseweazle control script: Read Disk to Image.
  4. #
  5. # Written & released by Keir Fraser <keir.xen@gmail.com>
  6. #
  7. # This is free and unencumbered software released into the public domain.
  8. # See the file COPYING for more details, or visit <http://unlicense.org>.
  9. description = "Read a disk to the specified image file."
  10. import sys
  11. from greaseweazle.tools import util
  12. from greaseweazle import error
  13. from greaseweazle import usb as USB
  14. from greaseweazle.flux import Flux
  15. def open_image(args):
  16. image_class = util.get_image_class(args.file)
  17. error.check(hasattr(image_class, 'to_file'),
  18. "%s: Cannot create %s image files"
  19. % (args.file, image_class.__name__))
  20. image = image_class.to_file(args.scyl, args.nr_sides)
  21. if args.rate is not None:
  22. image.bitrate = args.rate
  23. return image
  24. # normalise_to_rpm:
  25. # Adjust all revolutions in Flux object to have specified rotation speed.
  26. def normalise_rpm(flux, rpm):
  27. index_list, freq = flux.index_list, flux.sample_freq
  28. norm_to_index = 60/rpm * flux.sample_freq
  29. norm_flux = []
  30. to_index, index_list = index_list[0], index_list[1:]
  31. factor = norm_to_index / to_index
  32. for x in flux.list:
  33. to_index -= x
  34. if to_index >= 0:
  35. norm_flux.append(x*factor)
  36. continue
  37. if not index_list:
  38. break
  39. n_to_index, index_list = index_list[0], index_list[1:]
  40. n_factor = norm_to_index / n_to_index
  41. norm_flux.append((x+to_index)*factor - to_index*n_factor)
  42. to_index, factor = n_to_index, n_factor
  43. return Flux([norm_to_index]*len(flux.index_list), norm_flux, freq)
  44. # read_to_image:
  45. # Reads a floppy disk and dumps it into a new image file.
  46. def read_to_image(usb, args, image):
  47. for cyl in range(args.scyl, args.ecyl+1):
  48. for side in range(0, args.nr_sides):
  49. print("\rReading Track %u.%u..." % (cyl, side), end="")
  50. usb.seek((cyl, cyl*2)[args.double_step], side)
  51. flux = usb.read_track(args.revs)
  52. if args.rpm is not None:
  53. flux = normalise_rpm(flux, args.rpm)
  54. image.append_track(flux)
  55. print()
  56. # Write the image file.
  57. with open(args.file, "wb") as f:
  58. f.write(image.get_image())
  59. def main(argv):
  60. parser = util.ArgumentParser()
  61. parser.add_argument("--drive", type=util.drive_letter, default='A',
  62. help="drive to read (A,B,0,1,2)")
  63. parser.add_argument("--revs", type=int, default=3,
  64. help="number of revolutions to read per track")
  65. parser.add_argument("--scyl", type=int, default=0,
  66. help="first cylinder to read")
  67. parser.add_argument("--ecyl", type=int, default=81,
  68. help="last cylinder to read")
  69. parser.add_argument("--single-sided", action="store_true",
  70. help="single-sided read")
  71. parser.add_argument("--double-step", action="store_true",
  72. help="double-step drive heads")
  73. parser.add_argument("--rate", type=int, nargs="?",
  74. help="data rate (kbit/s)")
  75. parser.add_argument("--rpm", type=int, nargs="?",
  76. help="normalise to RPM")
  77. parser.add_argument("file", help="output filename")
  78. parser.add_argument("device", nargs="?", help="serial device")
  79. parser.description = description
  80. parser.prog += ' ' + argv[1]
  81. args = parser.parse_args(argv[2:])
  82. args.nr_sides = 1 if args.single_sided else 2
  83. try:
  84. usb = util.usb_open(args.device)
  85. image = open_image(args)
  86. util.with_drive_selected(read_to_image, usb, args, image)
  87. except USB.CmdError as error:
  88. print("Command Failed: %s" % error)
  89. if __name__ == "__main__":
  90. main(sys.argv)
  91. # Local variables:
  92. # python-indent: 4
  93. # End: