hal.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. # -*- coding: utf-8 -*-
  2. #
  3. # LinuxCNC fake Python HAL module for unit testing
  4. #
  5. # Copyright 2014 Michael Buesch <m@bues.ch>
  6. #
  7. # This program is free software; you can redistribute it and/or modify
  8. # it under the terms of the GNU General Public License as published by
  9. # the Free Software Foundation; either version 2 of the License, or
  10. # (at your option) any later version.
  11. #
  12. # This program is distributed in the hope that it will be useful,
  13. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. # GNU General Public License for more details.
  16. #
  17. # You should have received a copy of the GNU General Public License along
  18. # with this program; if not, write to the Free Software Foundation, Inc.,
  19. # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. #
  21. from __future__ import division, absolute_import, print_function, unicode_literals
  22. HAL_BIT = 1
  23. HAL_FLOAT = 2
  24. HAL_S32 = 3
  25. HAL_U32 = 4
  26. HAL_IN = 16
  27. HAL_OUT = 32
  28. HAL_IO = HAL_IN | HAL_OUT
  29. HAL_RO = 64
  30. HAL_RW = 192
  31. class error(Exception):
  32. pass
  33. class _Pin(object):
  34. def __init__(self, halName, halType, halDir):
  35. assert(halType in (HAL_BIT, HAL_FLOAT, HAL_S32, HAL_U32))
  36. assert(halDir in (HAL_IN, HAL_OUT, HAL_IO))
  37. self.halName = halName
  38. self.halType = halType
  39. self.halDir = halDir
  40. self.signals = []
  41. if self.halType == HAL_FLOAT:
  42. self.setHalData(0.0)
  43. else:
  44. self.setHalData(0)
  45. def setHalData(self, v):
  46. if self.halType == HAL_BIT:
  47. assert(v in (0, 1))
  48. elif self.halType == HAL_FLOAT:
  49. assert(isinstance(v, float))
  50. elif self.halType == HAL_S32:
  51. assert(v >= -2147483648 and v <= 2147483647) #@nocy
  52. #@cy assert(v >= -2147483648LL and v <= 2147483647LL)
  53. elif self.halType == HAL_U32:
  54. assert(v >= 0 and v <= 2147483647)
  55. else:
  56. assert(0)
  57. self.halData = v
  58. if self.halDir in (HAL_OUT, HAL_IO):
  59. for signal in self.signals:
  60. signal.setHalData(v)
  61. def _connectSignal(self, signal):
  62. if self.halDir == HAL_IN:
  63. assert(not self.signals)
  64. self.signals.append(signal)
  65. class _Param(_Pin):
  66. def __init__(self, halName, halType, halDir):
  67. assert(halType in (HAL_BIT, HAL_FLOAT, HAL_S32, HAL_U32))
  68. assert(halDir in (HAL_RO, HAL_RW))
  69. self.halName = halName
  70. self.halType = halType
  71. self.halDir = halDir
  72. if self.halType == HAL_FLOAT:
  73. self.setHalData(0.0)
  74. else:
  75. self.setHalData(0)
  76. class _Signal(object):
  77. def __init__(self, halName):
  78. self.halName = halName
  79. self.halType = None
  80. self.connectedPins = []
  81. def connectPin(self, pin):
  82. assert(pin.halDir in (HAL_IN, HAL_OUT, HAL_IO))
  83. assert(pin not in self.connectedPins)
  84. if self.halType is None:
  85. assert(not self.connectedPins)
  86. self.halType = pin.halType
  87. assert(self.halType == pin.halType)
  88. self.connectedPins.append(pin)
  89. pin._connectSignal(self)
  90. def setHalData(self, v):
  91. for pin in self.connectedPins:
  92. if pin.halDir in (HAL_IN, HAL_IO):
  93. pin.setHalData(v)
  94. class component(object):
  95. def __init__(self, name):
  96. self.__pins = {}
  97. self.__params = {}
  98. self.__signals = {}
  99. self.__ready = False
  100. def newpin(self, p, t, d):
  101. assert(p not in self.__pins)
  102. assert(p not in self.__params)
  103. assert(not self.__ready)
  104. assert(not self.__signals)
  105. self.__pins[p] = _Pin(p, t, d)
  106. def newparam(self, p, t, d):
  107. assert(p not in self.__pins)
  108. assert(p not in self.__params)
  109. assert(not self.__ready)
  110. assert(not self.__signals)
  111. self.__params[p] = _Param(p, t, d)
  112. def __sanitizePinName(self, pinName):
  113. assert(pinName.startswith("awlsim."))
  114. pinName = pinName[7:]
  115. assert(pinName)
  116. return pinName
  117. def __importHalFile(self, filename):
  118. assert(not self.__signals)
  119. with open(filename, "r") as fp:
  120. lines = fp.readlines()
  121. import re
  122. setp_re = re.compile(r'^setp\s+([\w\.\-]+)\s+([\w\.\-]+)$')
  123. net_re = re.compile(r'^net\s+([\w\.\-]+)\s+<?=?>?\s*([\w\.\-]+)(?:\s+<?=?>?\s*([\w\.\-]+))?$')
  124. for line in lines:
  125. line = line.strip()
  126. if not line:
  127. continue
  128. if line.startswith("#"):
  129. continue
  130. m = setp_re.match(line)
  131. if m: # setp statement
  132. halName, value = m.group(1), m.group(2)
  133. halName = self.__sanitizePinName(halName)
  134. value = int(value)
  135. try:
  136. self.__params[halName].setHalData(value)
  137. except KeyError:
  138. self.__pins[halName].setHalData(value)
  139. continue
  140. m = net_re.match(line)
  141. if m: # net statement
  142. if len(m.groups()) == 2:
  143. sigName, pin0Name, pin1Name =\
  144. m.group(1), m.group(2), None
  145. else:
  146. sigName, pin0Name, pin1Name =\
  147. m.group(1), m.group(2), m.group(3)
  148. if sigName in self.__signals:
  149. sig = self.__signals[sigName]
  150. else:
  151. sig = _Signal(sigName)
  152. self.__signals[sigName] = sig
  153. if pin0Name:
  154. sig.connectPin(self.__pins[self.__sanitizePinName(pin0Name)])
  155. if pin1Name:
  156. sig.connectPin(self.__pins[self.__sanitizePinName(pin1Name)])
  157. # Ignore other statements
  158. def ready(self):
  159. import os
  160. halFile = os.environ.get("FAKEHAL_HALFILE")
  161. if halFile:
  162. self.__importHalFile(halFile)
  163. self.__ready = True
  164. def __getitem__(self, k):
  165. try:
  166. pin = self.__pins[k]
  167. assert(pin.halDir in (HAL_IN, HAL_IO))
  168. return pin.halData
  169. except KeyError:
  170. try:
  171. param = self.__params[k]
  172. except KeyError:
  173. raise AttributeError
  174. assert(param.halDir in (HAL_RW, HAL_RO))
  175. return param.halData
  176. def __setitem__(self, k, v):
  177. assert(self.__ready)
  178. pin = self.__pins[k]
  179. assert(pin.halDir in (HAL_OUT, HAL_IO))
  180. pin.setHalData(v)
  181. def __len__(self):
  182. return len(self.__pins) + len(self.__params)