hardware_access.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. """
  2. # TOP Open Source programming suite
  3. #
  4. # TOP853 Lowlevel hardware access
  5. #
  6. # Copyright (c) 2022 Michael Buesch <m@bues.ch>
  7. #
  8. # This program is free software; you can redistribute it and/or modify
  9. # it under the terms of the GNU General Public License as published by
  10. # the Free Software Foundation; either version 2 of the License, or
  11. # (at your option) any later version.
  12. #
  13. # This program is distributed in the hope that it will be useful,
  14. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. # GNU General Public License for more details.
  17. #
  18. # You should have received a copy of the GNU General Public License along
  19. # with this program; if not, write to the Free Software Foundation, Inc.,
  20. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. """
  22. from libtoprammer.util import *
  23. from libtoprammer.hardware_access_usb import *
  24. class HardwareAccess(HardwareAccessUSB):
  25. "TOP853 hardware access"
  26. def __init__(self, foundUSBDev, noQueue=False, doRawDump=False):
  27. HardwareAccessUSB.__init__(self,
  28. usbdev = foundUSBDev.usbdev,
  29. maxPacketBytes = 64,
  30. noQueue = noQueue,
  31. doRawDump = doRawDump)
  32. def getOscillatorHz(self):
  33. "Get the 'OSC' frequency."
  34. return 8000000
  35. def getBufferRegSize(self):
  36. "Get the buffer register size, in bytes."
  37. return 64
  38. def readBufferReg(self, nrBytes):
  39. "Reads and returns the buffer register from hardware."
  40. self.queueCommand(int2byte(0x07))
  41. return self.receive(self.getBufferRegSize())[:nrBytes]
  42. def hardwareInit(self):
  43. "Initialize the hardware."
  44. self.queueCommand(b"\x0D")
  45. if self.readBufferReg(3) != b"\x69\x0C\x02":
  46. print("Init: Unexpected status (a)")
  47. self.runCommandSync(b"\x0E\x2C\x01\x00")
  48. for i in range(0x18):
  49. self.queueCommand(b"\x3E" + int2byte(i))
  50. if self.readBufferReg(4) != b"\x24\x37\x55\x04":
  51. print("Init: Unexpected status (b)")
  52. self.setVPPVoltage(0)
  53. for i in range(0x18):
  54. self.queueCommand(b"\x3E" + int2byte(i))
  55. if self.readBufferReg(4) != b"\x24\x37\x55\x04":
  56. print("Init: Unexpected status (c)")
  57. self.setVPPVoltage(12)
  58. self.runCommandSync(b"\x0E\x20\x00\x00")
  59. self.__delay_10msec(sync=True)
  60. self.runCommandSync(b"\x0E\x13\x00\x00")
  61. self.__delay_10msec(sync=True)
  62. self.runCommandSync(b"\x0A\x1D\x86")
  63. self.flushCommands()
  64. self.loadGNDLayout(0)
  65. self.loadVPPLayout(0)
  66. self.loadVCCLayout(0)
  67. for i in range(0x18):
  68. self.queueCommand(b"\x3E" + int2byte(i))
  69. if self.readBufferReg(4) != b"\x24\x37\x55\x04":
  70. print("Init: Unexpected status (c)")
  71. self.setVPPVoltage(12)
  72. self.runCommandSync(b"\x0E\x20\x00\x00")
  73. self.__delay_10msec(sync=True)
  74. for _ in range(2):
  75. self.queueCommand(b"\x57\x00\x50")
  76. if self.readBufferReg(4) != b"\xB0\x37\x55\x04":
  77. print("Init: Unexpected status (d)")
  78. for i in range(0x18):
  79. self.queueCommand(b"\x3E" + int2byte(i))
  80. if self.readBufferReg(4) != b"\x24\x37\x55\x04":
  81. print("Init: Unexpected status (c)")
  82. for i in range(0x20, 0x24):
  83. self.runCommandSync(b"\x57\x00" + int2byte(i))
  84. if self.readBufferReg(4) != b"\x80\xBE\x90\x00":
  85. print("Init: Unexpected status (e)")
  86. for i in range(0x40, 0x60):
  87. self.runCommandSync(b"\x57\x00" + int2byte(i))
  88. if self.readBufferReg(32) != b"\x54\x15\x62\x9E\x6E\xCB\xED\x5D\x15\x32\x70\x81\x05\xF9\x4F\x2E\xB0\x3C\x7E\x7B\x02\x40\x0B\x48\x28\x78\x63\x1D\x0C\x39\x3B\x79":
  89. print("Init: Unexpected status (f)")
  90. self.queueCommand(b"\x4F\x02\x00\x00")
  91. if self.readBufferReg(32) != b"\x48\xFF\x6F\x06\x49\x65\x52\x57\x52\x15\x20\x87\x05\xF9\x4F\x2E\xB0\x3C\x7E\x7B\x02\x40\x0B\x48\x28\x78\x63\x1D\x0C\x39\x3B\x79":
  92. print("Init: Unexpected status (g)")
  93. self.runCommandSync(b"\x0E\x10\x00\x00")
  94. self.runCommandSync(b"\x0E\x2D\x01\x00" + b"\x00\x00" + (b"\x33" * 57))
  95. self.runCommandSync(b"\x0E\x2D\x02\x00" + (b"\x33" * 56))
  96. self.runCommandSync(b"\x0E\x2D\x03\x00" + b"\x28" + (b"\x33" * 31) + b"\x00\x00\x00\x00")
  97. self.loadGNDLayout(20)
  98. for i in range(0x18):
  99. self.queueCommand(b"\x3E" + int2byte(i))
  100. if self.readBufferReg(4) != b"\x24\x37\x55\x04":
  101. print("Init: Unexpected status (h)")
  102. self.setVPPVoltage(12)
  103. # import libtoprammer.top853.sniffer as sniffer
  104. # sniffer.sniffVPP(self)
  105. #TODO
  106. self.flushCommands()
  107. assert 0#XXX
  108. def readVersionString(self):
  109. "Returns the device ID and versioning string."
  110. self.queueCommand(b"\x0E\x11\x00\x00")
  111. data = self.readBufferReg(32)
  112. return data.decode("ASCII", "ignore").replace("\x00", "").strip()
  113. def getFPGAType(self):
  114. "Get the FPGA architecture."
  115. return None # The hardware doesn't have an FPGA.
  116. def getFPGAMaxConfigChunkSize(self):
  117. raise NotImplementedError
  118. def FPGAInitiateConfig(self):
  119. raise NotImplementedError
  120. def FPGAUploadConfig(self, offset, data):
  121. raise NotImplementedError
  122. def makeFPGAAddr(self, address):
  123. raise NotImplementedError
  124. def FPGARead(self, address):
  125. raise NotImplementedError
  126. def FPGAWrite(self, address, byte):
  127. raise NotImplementedError
  128. def loadGNDLayout(self, layout):
  129. "Load the GND configuration into the shift registers."
  130. cmd = int2byte(0x0E) + int2byte(0x16) +\
  131. int2byte(layout) + int2byte(0)
  132. self.queueCommand(cmd)
  133. self.delay(0.01)
  134. self.flushCommands(0.15)
  135. def setVPPVoltage(self, voltage):
  136. "Set the VPP voltage. voltage is a floating point voltage number."
  137. for centivolt in (0, int(voltage * 10)):
  138. cmd = int2byte(0x0E) + int2byte(0x0F) +\
  139. int2byte(centivolt) + int2byte(0)
  140. self.queueCommand(cmd)
  141. self.delay(0.01)
  142. def loadVPPLayout(self, layout):
  143. "Load the VPP configuration into the shift registers."
  144. cmd = int2byte(0x0E) + int2byte(0x14) +\
  145. int2byte(layout) + int2byte(0)
  146. self.queueCommand(cmd)
  147. self.delay(0.01)
  148. self.flushCommands(0.15)
  149. def setVCCVoltage(self, voltage):
  150. "Set the VCC voltage. This is a no-op. The programmer can only do 5V."
  151. assert voltage == 0 or voltage == 5
  152. self.flushCommands()
  153. def loadVCCLayout(self, layout):
  154. "Load the VCC configuration into the shift registers."
  155. cmd = int2byte(0x0E) + int2byte(0x15) +\
  156. int2byte(layout) + int2byte(0)
  157. self.queueCommand(cmd)
  158. self.delay(0.01)
  159. self.flushCommands(0.15)
  160. def enableZifPullups(self, enable):
  161. #TODO
  162. "Enable the ZIF socket signal pullups."
  163. param = 1 if enable else 0
  164. cmd = int2byte(0x0E) + int2byte(0x28) +\
  165. int2byte(param) + int2byte(0)
  166. self.queueCommand(cmd)
  167. def __delay_4usec(self):
  168. #TODO
  169. self.queueCommand(int2byte(0x00))
  170. def __delay_10msec(self, sync=False):
  171. #TODO
  172. if sync:
  173. self.runCommandSync(int2byte(0x1B))
  174. else:
  175. self.queueCommand(int2byte(0x1B))
  176. def delay(self, seconds):
  177. "Perform an on-device or host delay."
  178. if seconds >= 0.5:
  179. # Perform long delays on the host
  180. self.flushCommands(seconds)
  181. elif seconds > 0.000255:
  182. # Need to round up to ten milliseconds
  183. millisecs = int(math.ceil(seconds * 1e3))
  184. millisecs = roundup(millisecs, 10)
  185. for _ in range(millisecs // 10):
  186. self.__delay_10msec()
  187. else:
  188. # Round up to 4 usec boundary
  189. microsecs = int(math.ceil(seconds * 1e6))
  190. microsecs = roundup(microsecs, 4)
  191. for _ in range(microsecs // 4):
  192. self.__delay_4usec()