"""hal library python interface using ctypes ffi interface""" from ctypes import* lib = CDLL('liblinuxcnchal.so') lib.hal_malloc.restype = c_void_p lib.hal_malloc.argtype = [c_long] lib.hal_comp_name.restype = c_char_p lib.hal_pin_new.argtypes = [c_char_p, c_int, c_int, c_void_p, c_int] lib.hal_signal_new.argtypes = [c_char_p, c_int] lib.hal_link.argtypes = [c_char_p, c_char_p] lib.hal_port_read.argtypes = [c_int, c_char_p, c_uint] lib.hal_port_read.restype = c_bool lib.hal_port_peek.argtypes = [c_int, c_char_p, c_uint] lib.hal_port_peek.restype = c_bool lib.hal_port_peek_commit.argtypes = [c_int, c_char_p, c_uint] lib.hal_port_peek.restype = c_bool lib.hal_port_write.argtypes = [c_int, c_char_p, c_uint] lib.hal_port_write.restype = c_bool lib.hal_port_readable.argtypes = [c_int] lib.hal_port_readable.restype = c_uint lib.hal_port_writable.argtypes = [c_int] lib.hal_port_writable.restype = c_uint lib.hal_port_buffer_size.argtypes = [c_int] lib.hal_port_buffer_size.restype = c_uint lib.hal_port_clear.argtypes = [c_int] lib.hal_port_wait_readable.argtypes = [POINTER(POINTER(c_int)), c_uint, c_int] lib.hal_port_wait_writable.argtypes = [POINTER(POINTER(c_int)), c_uint, c_int] class HalException(Exception): """An exception raised by hal library functions""" pass class halType: BIT = 1 FLOAT = 2 SIGNED = 3 UNSIGNED = 4 PORT = 5 values = [BIT, FLOAT, SIGNED, UNSIGNED, PORT ] typeConversion = { BIT : c_bool, FLOAT : c_double, SIGNED : c_int32, UNSIGNED : c_uint32, PORT : c_int } class pinDir: IN = 16 OUT = 32 IO = IN | OUT values = [IN, OUT, IO] class pin(object): def __init__(self, component, name, type, dir, data_ptr): self.comp = component self.name = name self.type = type self.dir = dir self.data_ptr = data_ptr @property def fullname(self): return "{0}.{1}".format(self.comp.name, self.name) @property def value(self): if self.type == halType.PORT: raise HalException("cannot get value of PORT pin") else: return self.data_ptr.contents.contents.value @value.setter def value(self, val): if self.type == halType.PORT: raise HalException("cannot set value of PORT pin") else: self.data_ptr.contents.contents.value = val class port(pin): def __init__(self, component, name, type, dir, data_ptr): pin.__init__(self, component, name, type, dir, data_ptr) @property def __port(self): return self.data_ptr.contents.contents.value def read(self, count): if self.dir != pinDir.IN: raise HalException("cannot read output port") buff = create_string_buffer(count) if not lib.hal_port_read(self.__port, buff, count): return '' else: return buff.raw def peek(self, count): if self.dir != pinDir.IN: raise HalException("cannot peek output port") buff = create_string_buffer(count) if not lib.hal_port_peek(self.__port, buff, count): return '' else: return buff.raw def peek_commit(self, count): if self.dir != pinDir.IN: raise HalException("cannot peek commit output port") return lib.hal_port_peek_commit(self.__port, count) def write(self, buff): if self.dir != pinDir.OUT: raise HalException("cannot write input port") return lib.hal_port_write(self.__port, buff.encode(), len(buff)) def readable(self): if self.dir != pinDir.IN: raise HalException("cannot read output port") return lib.hal_port_readable(self.__port) def writable(self): if self.dir != pinDir.OUT: raise HalException("cannot write input port") return lib.hal_port_writable(self.__port) def size(self): return lib.hal_port_buffer_size(self.__port) def clear(self): if self.dir != pinDir.IN: raise HalException("cannot clear output port") lib.hal_port_clear(self.__port) def waitReadable(self, count): if self.dir != pinDir.IN: raise HalException("cannot read output port") lib.hal_port_wait_readable(self.data_ptr, count, 0) def waitWritable(self, count): if self.dir != pinDir.OUT: raise HalException("cannot write input port") lib.hal_port_wait_writable(self.data_ptr, count, 0) class component: def __init__(self, name): self.id = lib.hal_init(name.encode()) self.name = name self.pins = {} if self.id < 0: raise HalException('failed to initialized component "{0}"'.format(name)) def __del__(self): self.exit() def exit(self): if self.id > 0: result = lib.hal_exit(self.id) self.id = -1 if result < 0: raise HalException('hal_exit failed with code {0}'.format(result)) def ready(self): result = lib.hal_ready(self.id) if result < 0: raise HalException('hal_ready failed with code {0}'.format(result)) def name(self): return lib.hal_comp_name(self.id) def pinNew(self, name, type, dir): if not type in halType.typeConversion: raise HalException('failed to create pin "{0}". Unknown type {1}'.format(name, type)) if not dir in pinDir.values: raise HalException('failed to create pin "{0}". Unknown dir {1}'.format(name, dir)) ctype = halType.typeConversion[type] ptr = self.halMalloc(sizeof(c_void_p)) result = lib.hal_pin_new("{0}.{1}".format(self.name, name).encode(), type, dir, ptr, self.id) if result < 0: raise HalException('failed to create pin "{0}" with code {1}'.format(name, result)) if type == halType.PORT: self.pins[name] = port(self, name, type, dir, cast(ptr, POINTER(POINTER(ctype)))) else: self.pins[name] = pin(self, name, type, dir, cast(ptr, POINTER(POINTER(ctype)))) return self.pins[name] def sigNew(self, name, type): if not type in halType.values: raise HalException('failed to create signal "{0}". Invalid type {1}'.format(name, type)) result = lib.hal_signal_new(name.encode(), type) if result < 0: raise HalException('failed to create signal "{0}" with code {1}'.format(name, result)) def sigLink(self, pin_name, sig_name): result = lib.hal_link(pin_name.encode(), sig_name.encode()) if result < 0: raise HalException('failed to link sig "{0}" to pin "{1}" with result {2}'.format(sig_name, pin_name, result)) def halMalloc(self, count): ptr = lib.hal_malloc(count) memset(ptr, 0, count) return ptr