flux.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. # greaseweazle/flux.py
  2. #
  3. # Written & released by Keir Fraser <keir.xen@gmail.com>
  4. #
  5. # This is free and unencumbered software released into the public domain.
  6. # See the file COPYING for more details, or visit <http://unlicense.org>.
  7. from greaseweazle import error
  8. class Flux:
  9. def __init__(self, index_list, flux_list, sample_freq, index_cued=True):
  10. self.index_list = index_list
  11. self.list = flux_list
  12. self.sample_freq = sample_freq
  13. self.splice = 0
  14. self.index_cued = index_cued
  15. def __str__(self):
  16. s = "\nFlux: %.2f MHz" % (self.sample_freq*1e-6)
  17. s += ("\n Total: %u samples, %.2fms\n"
  18. % (len(self.list), sum(self.list)*1000/self.sample_freq))
  19. rev = 0
  20. for t in self.index_list:
  21. s += " Revolution %u: %.2fms\n" % (rev, t*1000/self.sample_freq)
  22. rev += 1
  23. return s[:-1]
  24. def summary_string(self):
  25. return ("Raw Flux (%u flux in %.2fms)"
  26. % (len(self.list), sum(self.list)*1000/self.sample_freq))
  27. def cue_at_index(self):
  28. if self.index_cued:
  29. return
  30. # Clip the initial partial revolution.
  31. to_index = self.index_list[0]
  32. for i in range(len(self.list)):
  33. to_index -= self.list[i]
  34. if to_index < 0:
  35. break
  36. if to_index < 0:
  37. self.list = [-to_index] + self.list[i+1:]
  38. else: # we ran out of flux
  39. self.list = []
  40. self.index_list = self.index_list[1:]
  41. self.index_cued = True
  42. def flux_for_writeout(self):
  43. error.check(self.splice == 0 or len(self.index_list) > 1,
  44. "Cannot write single-revolution unaligned raw flux")
  45. splice_at_index = (self.splice == 0)
  46. # Copy the required amount of flux to a fresh list.
  47. flux_list = []
  48. to_index = self.index_list[0]
  49. remain = to_index + self.splice
  50. for f in self.list:
  51. if f > remain:
  52. break
  53. flux_list.append(f)
  54. remain -= f
  55. if splice_at_index:
  56. # Extend with "safe" 4us sample values, to avoid unformatted area
  57. # at end of track if drive motor is a little slow.
  58. four_us = max(self.sample_freq * 4e-6, 1)
  59. if remain > four_us:
  60. flux_list.append(remain)
  61. for i in range(round(to_index/(10*four_us))):
  62. flux_list.append(four_us)
  63. elif remain > 0:
  64. # End the write exactly where specified.
  65. flux_list.append(remain)
  66. return WriteoutFlux(to_index, flux_list, self.sample_freq,
  67. index_cued = True,
  68. terminate_at_index = (self.splice == 0))
  69. def flux(self):
  70. return self
  71. def scale(self, factor):
  72. """Scale up all flux and index timings by specified factor."""
  73. self.sample_freq /= factor
  74. @property
  75. def ticks_per_rev(self):
  76. """Mean time between index pulses, in sample ticks"""
  77. index_list = self.index_list
  78. if not self.index_cued:
  79. index_list = index_list[1:]
  80. return sum(index_list) / len(index_list)
  81. @property
  82. def time_per_rev(self):
  83. """Mean time between index pulses, in seconds (float)"""
  84. return self.ticks_per_rev / self.sample_freq
  85. class WriteoutFlux(Flux):
  86. def __init__(self, ticks_to_index, flux_list, sample_freq,
  87. index_cued, terminate_at_index):
  88. super().__init__([ticks_to_index], flux_list, sample_freq)
  89. self.index_cued = index_cued
  90. self.terminate_at_index = terminate_at_index
  91. def __str__(self):
  92. s = ("\nWriteoutFlux: %.2f MHz, %.2fms to index, %s\n"
  93. " Total: %u samples, %.2fms"
  94. % (self.sample_freq*1e-6,
  95. self.index_list[0]*1000/self.sample_freq,
  96. ("Write all", "Terminate at index")[self.terminate_at_index],
  97. len(self.list), sum(self.list)*1000/self.sample_freq))
  98. return s
  99. def flux_for_writeout(self):
  100. return self
  101. @property
  102. def ticks_per_rev(self):
  103. """Mean time between index pulses, in sample ticks"""
  104. return sum(self.index_list) / len(self.index_list)
  105. # Local variables:
  106. # python-indent: 4
  107. # End: