# -*- coding: utf-8 -*- # # LinuxCNC fake Python HAL module for unit testing # # Copyright 2014 Michael Buesch # # 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 _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): assert(self.__ready) try: pin = self.__pins[k] assert(pin.halDir in (HAL_IN, HAL_IO)) return pin.halData except KeyError: param = self.__params[k] 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)