flux.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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.index_cued,
  44. "Cannot write non-index-cued raw flux")
  45. error.check(self.splice == 0 or len(self.index_list) > 1,
  46. "Cannot write single-revolution unaligned raw flux")
  47. splice_at_index = (self.splice == 0)
  48. # Copy the required amount of flux to a fresh list.
  49. flux_list = []
  50. to_index = self.index_list[0]
  51. remain = to_index + self.splice
  52. for f in self.list:
  53. if f > remain:
  54. break
  55. flux_list.append(f)
  56. remain -= f
  57. if splice_at_index:
  58. # Extend with "safe" 4us sample values, to avoid unformatted area
  59. # at end of track if drive motor is a little slow.
  60. four_us = max(self.sample_freq * 4e-6, 1)
  61. if remain > four_us:
  62. flux_list.append(remain)
  63. for i in range(round(to_index/(10*four_us))):
  64. flux_list.append(four_us)
  65. elif remain > 0:
  66. # End the write exactly where specified.
  67. flux_list.append(remain)
  68. return WriteoutFlux(to_index, flux_list, self.sample_freq,
  69. index_cued = True,
  70. terminate_at_index = (self.splice == 0))
  71. def flux(self):
  72. return self
  73. def scale(self, factor):
  74. """Scale up all flux and index timings by specified factor."""
  75. self.sample_freq /= factor
  76. @property
  77. def ticks_per_rev(self):
  78. """Mean time between index pulses, in sample ticks"""
  79. index_list = self.index_list
  80. if not self.index_cued:
  81. index_list = index_list[1:]
  82. return sum(index_list) / len(index_list)
  83. @property
  84. def time_per_rev(self):
  85. """Mean time between index pulses, in seconds (float)"""
  86. return self.ticks_per_rev / self.sample_freq
  87. class WriteoutFlux(Flux):
  88. def __init__(self, ticks_to_index, flux_list, sample_freq,
  89. index_cued, terminate_at_index):
  90. super().__init__([ticks_to_index], flux_list, sample_freq)
  91. self.index_cued = index_cued
  92. self.terminate_at_index = terminate_at_index
  93. def __str__(self):
  94. s = ("\nWriteoutFlux: %.2f MHz, %.2fms to index, %s\n"
  95. " Total: %u samples, %.2fms"
  96. % (self.sample_freq*1e-6,
  97. self.index_list[0]*1000/self.sample_freq,
  98. ("Write all", "Terminate at index")[self.terminate_at_index],
  99. len(self.list), sum(self.list)*1000/self.sample_freq))
  100. return s
  101. def flux_for_writeout(self):
  102. return self
  103. @property
  104. def ticks_per_rev(self):
  105. """Mean time between index pulses, in sample ticks"""
  106. return sum(self.index_list) / len(self.index_list)
  107. # Local variables:
  108. # python-indent: 4
  109. # End: