123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206 |
- # -*- coding: utf-8 -*-
- #
- # LinuxCNC fake Python HAL module for unit testing
- #
- # Copyright 2014 Michael Buesch <m@bues.ch>
- #
- # This program is free software; you can redistribute it and/or modify
- # it under the terms of the GNU General Public License as published by
- # the Free Software Foundation; either version 2 of the License, or
- # (at your option) any later version.
- #
- # This program is distributed in the hope that it will be useful,
- # but WITHOUT ANY WARRANTY; without even the implied warranty of
- # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- # GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public License along
- # with this program; if not, write to the Free Software Foundation, Inc.,
- # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- #
- from __future__ import division, absolute_import, print_function, unicode_literals
- HAL_BIT = 1
- HAL_FLOAT = 2
- HAL_S32 = 3
- HAL_U32 = 4
- HAL_IN = 16
- HAL_OUT = 32
- HAL_IO = HAL_IN | HAL_OUT
- HAL_RO = 64
- HAL_RW = 192
- class error(Exception):
- pass
- class _Pin(object):
- def __init__(self, halName, halType, halDir):
- assert(halType in (HAL_BIT, HAL_FLOAT, HAL_S32, HAL_U32))
- assert(halDir in (HAL_IN, HAL_OUT, HAL_IO))
- self.halName = halName
- self.halType = halType
- self.halDir = halDir
- self.signals = []
- if self.halType == HAL_FLOAT:
- self.setHalData(0.0)
- else:
- self.setHalData(0)
- def setHalData(self, v):
- if self.halType == HAL_BIT:
- assert(v in (0, 1))
- elif self.halType == HAL_FLOAT:
- assert(isinstance(v, float))
- elif self.halType == HAL_S32:
- assert(v >= -2147483648 and v <= 2147483647) #@nocy
- #@cy assert(v >= -2147483648LL and v <= 2147483647LL)
- elif self.halType == HAL_U32:
- assert(v >= 0 and v <= 2147483647)
- else:
- assert(0)
- self.halData = v
- if self.halDir in (HAL_OUT, HAL_IO):
- for signal in self.signals:
- signal.setHalData(v)
- def _connectSignal(self, signal):
- if self.halDir == HAL_IN:
- assert(not self.signals)
- self.signals.append(signal)
- class _Param(_Pin):
- def __init__(self, halName, halType, halDir):
- assert(halType in (HAL_BIT, HAL_FLOAT, HAL_S32, HAL_U32))
- assert(halDir in (HAL_RO, HAL_RW))
- self.halName = halName
- self.halType = halType
- self.halDir = halDir
- if self.halType == HAL_FLOAT:
- self.setHalData(0.0)
- else:
- self.setHalData(0)
- class _Signal(object):
- def __init__(self, halName):
- self.halName = halName
- self.halType = None
- self.connectedPins = []
- def connectPin(self, pin):
- assert(pin.halDir in (HAL_IN, HAL_OUT, HAL_IO))
- assert(pin not in self.connectedPins)
- if self.halType is None:
- assert(not self.connectedPins)
- self.halType = pin.halType
- assert(self.halType == pin.halType)
- self.connectedPins.append(pin)
- pin._connectSignal(self)
- def setHalData(self, v):
- for pin in self.connectedPins:
- if pin.halDir in (HAL_IN, HAL_IO):
- pin.setHalData(v)
- class component(object):
- def __init__(self, name):
- self.__pins = {}
- self.__params = {}
- self.__signals = {}
- self.__ready = False
- def newpin(self, p, t, d):
- assert(p not in self.__pins)
- assert(p not in self.__params)
- assert(not self.__ready)
- assert(not self.__signals)
- self.__pins[p] = _Pin(p, t, d)
- def newparam(self, p, t, d):
- assert(p not in self.__pins)
- assert(p not in self.__params)
- assert(not self.__ready)
- assert(not self.__signals)
- self.__params[p] = _Param(p, t, d)
- def __sanitizePinName(self, pinName):
- assert(pinName.startswith("awlsim."))
- pinName = pinName[7:]
- assert(pinName)
- return pinName
- def __importHalFile(self, filename):
- assert(not self.__signals)
- with open(filename, "r") as fp:
- lines = fp.readlines()
- import re
- setp_re = re.compile(r'^setp\s+([\w\.\-]+)\s+([\w\.\-]+)$')
- net_re = re.compile(r'^net\s+([\w\.\-]+)\s+<?=?>?\s*([\w\.\-]+)(?:\s+<?=?>?\s*([\w\.\-]+))?$')
- for line in lines:
- line = line.strip()
- if not line:
- continue
- if line.startswith("#"):
- continue
- m = setp_re.match(line)
- if m: # setp statement
- halName, value = m.group(1), m.group(2)
- halName = self.__sanitizePinName(halName)
- value = int(value)
- try:
- self.__params[halName].setHalData(value)
- except KeyError:
- self.__pins[halName].setHalData(value)
- continue
- m = net_re.match(line)
- if m: # net statement
- if len(m.groups()) == 2:
- sigName, pin0Name, pin1Name =\
- m.group(1), m.group(2), None
- else:
- sigName, pin0Name, pin1Name =\
- m.group(1), m.group(2), m.group(3)
- if sigName in self.__signals:
- sig = self.__signals[sigName]
- else:
- sig = _Signal(sigName)
- self.__signals[sigName] = sig
- if pin0Name:
- sig.connectPin(self.__pins[self.__sanitizePinName(pin0Name)])
- if pin1Name:
- sig.connectPin(self.__pins[self.__sanitizePinName(pin1Name)])
- # Ignore other statements
- def ready(self):
- import os
- halFile = os.environ.get("FAKEHAL_HALFILE")
- if halFile:
- self.__importHalFile(halFile)
- self.__ready = True
- def __getitem__(self, k):
- try:
- pin = self.__pins[k]
- assert(pin.halDir in (HAL_IN, HAL_IO))
- return pin.halData
- except KeyError:
- try:
- param = self.__params[k]
- except KeyError:
- raise AttributeError
- assert(param.halDir in (HAL_RW, HAL_RO))
- return param.halData
- def __setitem__(self, k, v):
- assert(self.__ready)
- pin = self.__pins[k]
- assert(pin.halDir in (HAL_OUT, HAL_IO))
- pin.setHalData(v)
- def __len__(self):
- return len(self.__pins) + len(self.__params)
|