pyhal.py
1 """hal library python interface using ctypes ffi interface""" 2 3 from ctypes import* 4 5 6 lib = CDLL('liblinuxcnchal.so') 7 lib.hal_malloc.restype = c_void_p 8 lib.hal_malloc.argtype = [c_long] 9 lib.hal_comp_name.restype = c_char_p 10 11 lib.hal_pin_new.argtypes = [c_char_p, c_int, c_int, c_void_p, c_int] 12 13 lib.hal_signal_new.argtypes = [c_char_p, c_int] 14 15 lib.hal_link.argtypes = [c_char_p, c_char_p] 16 17 lib.hal_port_read.argtypes = [c_int, c_char_p, c_uint] 18 lib.hal_port_read.restype = c_bool 19 20 lib.hal_port_peek.argtypes = [c_int, c_char_p, c_uint] 21 lib.hal_port_peek.restype = c_bool 22 23 lib.hal_port_peek_commit.argtypes = [c_int, c_char_p, c_uint] 24 lib.hal_port_peek.restype = c_bool 25 26 lib.hal_port_write.argtypes = [c_int, c_char_p, c_uint] 27 lib.hal_port_write.restype = c_bool 28 29 lib.hal_port_readable.argtypes = [c_int] 30 lib.hal_port_readable.restype = c_uint 31 32 lib.hal_port_writable.argtypes = [c_int] 33 lib.hal_port_writable.restype = c_uint 34 35 lib.hal_port_buffer_size.argtypes = [c_int] 36 lib.hal_port_buffer_size.restype = c_uint 37 38 lib.hal_port_clear.argtypes = [c_int] 39 40 lib.hal_port_wait_readable.argtypes = [POINTER(POINTER(c_int)), c_uint, c_int] 41 lib.hal_port_wait_writable.argtypes = [POINTER(POINTER(c_int)), c_uint, c_int] 42 43 class HalException(Exception): 44 """An exception raised by hal library functions""" 45 pass 46 47 48 class halType: 49 BIT = 1 50 FLOAT = 2 51 SIGNED = 3 52 UNSIGNED = 4 53 PORT = 5 54 55 values = [BIT, FLOAT, SIGNED, UNSIGNED, PORT ] 56 57 typeConversion = { BIT : c_bool, 58 FLOAT : c_double, 59 SIGNED : c_int32, 60 UNSIGNED : c_uint32, 61 PORT : c_int } 62 63 class pinDir: 64 IN = 16 65 OUT = 32 66 IO = IN | OUT 67 68 values = [IN, OUT, IO] 69 70 71 class pin(object): 72 def __init__(self, component, name, type, dir, data_ptr): 73 self.comp = component 74 self.name = name 75 self.type = type 76 self.dir = dir 77 self.data_ptr = data_ptr 78 79 @property 80 def fullname(self): 81 return "{0}.{1}".format(self.comp.name, self.name) 82 83 @property 84 def value(self): 85 if self.type == halType.PORT: 86 raise HalException("cannot get value of PORT pin") 87 else: 88 return self.data_ptr.contents.contents.value 89 90 @value.setter 91 def value(self, val): 92 if self.type == halType.PORT: 93 raise HalException("cannot set value of PORT pin") 94 else: 95 self.data_ptr.contents.contents.value = val 96 97 98 class port(pin): 99 def __init__(self, component, name, type, dir, data_ptr): 100 pin.__init__(self, component, name, type, dir, data_ptr) 101 102 @property 103 def __port(self): 104 return self.data_ptr.contents.contents.value 105 106 def read(self, count): 107 if self.dir != pinDir.IN: 108 raise HalException("cannot read output port") 109 110 buff = create_string_buffer(count) 111 if not lib.hal_port_read(self.__port, buff, count): 112 return '' 113 else: 114 return buff.raw 115 116 def peek(self, count): 117 if self.dir != pinDir.IN: 118 raise HalException("cannot peek output port") 119 120 buff = create_string_buffer(count) 121 if not lib.hal_port_peek(self.__port, buff, count): 122 return '' 123 else: 124 return buff.raw 125 126 def peek_commit(self, count): 127 if self.dir != pinDir.IN: 128 raise HalException("cannot peek commit output port") 129 return lib.hal_port_peek_commit(self.__port, count) 130 131 def write(self, buff): 132 if self.dir != pinDir.OUT: 133 raise HalException("cannot write input port") 134 135 return lib.hal_port_write(self.__port, buff, len(buff)) 136 137 def readable(self): 138 if self.dir != pinDir.IN: 139 raise HalException("cannot read output port") 140 141 return lib.hal_port_readable(self.__port) 142 143 def writable(self): 144 if self.dir != pinDir.OUT: 145 raise HalException("cannot write input port") 146 147 return lib.hal_port_writable(self.__port) 148 149 def size(self): 150 return lib.hal_port_buffer_size(self.__port) 151 152 def clear(self): 153 if self.dir != pinDir.IN: 154 raise HalException("cannot clear output port") 155 156 lib.hal_port_clear(self.__port) 157 158 def waitReadable(self, count): 159 if self.dir != pinDir.IN: 160 raise HalException("cannot read ouput port") 161 162 lib.hal_port_wait_readable(self.data_ptr, count, 0) 163 164 def waitWritable(self, count): 165 if self.dir != pinDir.OUT: 166 raise HalException("cannot write input port") 167 168 lib.hal_port_wait_writable(self.data_ptr, count, 0) 169 170 171 172 class component: 173 def __init__(self, name): 174 self.id = lib.hal_init(name) 175 self.name = name 176 self.pins = {} 177 if self.id < 0: 178 raise HalException('failed to initialized component "{0}"'.format(name)) 179 180 181 def __del__(self): 182 self.exit() 183 184 185 def exit(self): 186 if self.id > 0: 187 result = lib.hal_exit(self.id) 188 self.id = -1 189 if result < 0: 190 raise HalException('hal_exit failed with code {0}'.format(result)) 191 192 193 def ready(self): 194 result = lib.hal_ready(self.id) 195 if result < 0: 196 raise HalException('hal_ready failed with code {0}'.format(result)) 197 198 def name(self): 199 return lib.hal_comp_name(self.id) 200 201 202 def pinNew(self, name, type, dir): 203 if not type in halType.typeConversion: 204 raise HalException('failed to create pin "{0}". Unknown type {1}'.format(name, type)) 205 206 if not dir in pinDir.values: 207 raise HalException('failed to create pin "{0}". Unknown dir {1}'.format(name, dir)) 208 209 ctype = halType.typeConversion[type] 210 211 ptr = self.halMalloc(sizeof(c_void_p)) 212 result = lib.hal_pin_new("{0}.{1}".format(self.name, name), type, dir, ptr, self.id) 213 if result < 0: 214 raise HalException('failed to create pin "{0}" with code {1}'.format(name, result)) 215 216 if type == halType.PORT: 217 self.pins[name] = port(self, name, type, dir, cast(ptr, POINTER(POINTER(ctype)))) 218 else: 219 self.pins[name] = pin(self, name, type, dir, cast(ptr, POINTER(POINTER(ctype)))) 220 221 return self.pins[name] 222 223 def sigNew(self, name, type): 224 if not type in halType.values: 225 raise HalException('failed to create signal "{0}". Invalid type {1}'.format(name, type)) 226 227 result = lib.hal_signal_new(name, type) 228 229 if result < 0: 230 raise HalException('failed to create signal "{0}" with code {1}'.format(name, result)) 231 232 def sigLink(self, pin_name, sig_name): 233 result = lib.hal_link(pin_name, sig_name) 234 if result < 0: 235 raise HalException('failed to link sig "{0}" to pin "{1}" with result {2}'.format(sig_name, pin_name, result)) 236 237 238 def halMalloc(self, count): 239 ptr = lib.hal_malloc(count) 240 memset(ptr, 0, count) 241 return ptr 242 243 244 245