class BaseRegisterClient(BaseReceiveClient): def __init__(self, expires=2): BaseReceiveClient.__init__(self) self._recv_queue = IndexQueue() self._cache = {} self._expires = expires def _update_cache(self, register_values): self._cache.update({ name: (value, time.time() + self._expires) for (name, value) in register_values.iteritems() }) def write_registers(self, register_values): """ Write registers. register_values must be a dictionary {name: value, ...} """ self.socket.sendall(json.dumps(['w', register_values]) + '\n') self._update_cache(register_values) def read_registers(self, registers): """ Read registers. registers must be a sequence of register names. """ needed = [ name for name in registers if (not name in self._cache or time.time() > self._cache[name][1]) ] if needed: self.socket.sendall(json.dumps(['r', needed]) + '\n') read = {name: self._recv_queue.get(name) for name in needed} self._update_cache(read) return {name: self._cache[name][0] for name in registers} def _recv_job(self): buf = '' p = re.compile('\n') while not self._stop.is_set(): try: received = self.socket.recv(1024) except socket.timeout: continue data = buf + received while True: m = p.search(data) if not m: buf = data break i = m.end() chunk, data = data[:i], data[i:] try: registers = json.loads(chunk) except ValueError: continue for (name, value) in registers.iteritems(): self._recv_queue.put(name, value)
class BaseRegisterClient(BaseReceiveClient): def __init__(self, expires=2): BaseReceiveClient.__init__(self) self._recv_queue = IndexQueue() self._cache = {} self._expires = expires def _update_cache(self, register_values): self._cache.update({name: (value, time.time()+self._expires) for (name, value) in register_values.iteritems()}) def write_registers(self, register_values): """ Write registers. register_values must be a dictionary {name: value, ...} """ self.socket.sendall(json.dumps(['w', register_values])+'\n') self._update_cache(register_values) def read_registers(self, registers): """ Read registers. registers must be a sequence of register names. """ needed = [name for name in registers if (not name in self._cache or time.time() > self._cache[name][1])] if needed: self.socket.sendall(json.dumps(['r', needed])+'\n') read = {name: self._recv_queue.get(name) for name in needed} self._update_cache(read) return {name: self._cache[name][0] for name in registers} def _recv_job(self): buf = '' p = re.compile('\n') while not self._stop.is_set(): try: received = self.socket.recv(1024) except socket.timeout: continue data = buf + received while True: m = p.search(data) if not m: buf = data break i = m.end() chunk, data = data[:i], data[i:] try: registers = json.loads(chunk) except ValueError: continue for (name, value) in registers.iteritems(): self._recv_queue.put(name, value)
def __init__(self, reset=False, load=None, **kwargs): try: ftdi_cbmnet.FtdiCbmnetThreaded.__init__(self) except IOError: raise # TODO enter offline mode # here we enforce arguments to be passed as keyword arguments debug_kwargs = ['_debug_out', '_debug_ftdi', '_debug_cbmif'] for arg in debug_kwargs: if arg in kwargs: setattr(self, arg, kwargs[arg]) self.readout_enable(0) # message splitters and output queues for groups A and B self._dataA_splitter = MessageSplitter() self._dataB_splitter = MessageSplitter() self._dataA_queue = Queue.Queue() self._dataB_queue = Queue.Queue() # register read result Queue (indexable) self._ctrl_queue = IndexQueue() # data reader thread self._recv_worker = threading.Thread(name="recv worker") self._recv_worker.run = self._recv_job self._recv_worker.daemon = True self._recv_worker.start() # higher level register file access def rf_write_gen(name, addr): def write(value): self.write_register(addr, value) return write def rf_read_gen(name, addr): def read(): return self.read_register(addr) return read self._registerfile = SpadicRegisterFile(rf_write_gen, rf_read_gen) # higher level shift register access self._shiftregister = SpadicShiftRegister(self.write_register, self.read_register) # highest level configuration controller self.control = SpadicController(self._registerfile, self._shiftregister, reset, load) self.readout_enable(1)
def __init__(self, expires=2): BaseReceiveClient.__init__(self) self._recv_queue = IndexQueue() self._cache = {} self._expires = expires
class Spadic(ftdi_cbmnet.FtdiCbmnetThreaded): """ Wrapper for CBMnet interface <-> SPADIC communication. Arguments: reset - flag for initial reset of the chip configuration load - name of .spc configuration file to be loaded Optional debugging keyword arguments: _debug_out - file-like object where debug output is sent to _debug_ftdi - flag for logging FTDI communication _debug_cbmif - flag for logging CBMnet interface communication """ def __init__(self, reset=False, load=None, **kwargs): try: ftdi_cbmnet.FtdiCbmnetThreaded.__init__(self) except IOError: raise # TODO enter offline mode # here we enforce arguments to be passed as keyword arguments debug_kwargs = ['_debug_out', '_debug_ftdi', '_debug_cbmif'] for arg in debug_kwargs: if arg in kwargs: setattr(self, arg, kwargs[arg]) self.readout_enable(0) # message splitters and output queues for groups A and B self._dataA_splitter = MessageSplitter() self._dataB_splitter = MessageSplitter() self._dataA_queue = Queue.Queue() self._dataB_queue = Queue.Queue() # register read result Queue (indexable) self._ctrl_queue = IndexQueue() # data reader thread self._recv_worker = threading.Thread(name="recv worker") self._recv_worker.run = self._recv_job self._recv_worker.daemon = True self._recv_worker.start() # higher level register file access def rf_write_gen(name, addr): def write(value): self.write_register(addr, value) return write def rf_read_gen(name, addr): def read(): return self.read_register(addr) return read self._registerfile = SpadicRegisterFile(rf_write_gen, rf_read_gen) # higher level shift register access self._shiftregister = SpadicShiftRegister(self.write_register, self.read_register) # highest level configuration controller self.control = SpadicController(self._registerfile, self._shiftregister, reset, load) self.readout_enable(1) def _recv_job(self): """Process data received from the CBMnet interface.""" while not self._stop.is_set(): try: (addr, words) = self._cbmif_read() except TypeError: # read result is None continue if addr == ftdi_cbmnet.ADDR_DATA_A: for m in self._dataA_splitter(words): self._dataA_queue.put(m) elif addr == ftdi_cbmnet.ADDR_DATA_B: for m in self._dataB_splitter(words): self._dataB_queue.put(m) elif addr == ftdi_cbmnet.ADDR_CTRL: [reg_addr, reg_val] = words self._ctrl_queue.put(reg_addr, reg_val) def __exit__(self, *args): """Bring all threads to halt.""" if not hasattr(self, '_stop'): return if not self._stop.is_set(): self._stop.set() ftdi_cbmnet.FtdiCbmnetThreaded.__exit__(self) self._recv_worker.join() # maybe do: #while self._recv_worker.is_alive(): # self._recv_worker.join(timeout=1) if self._debug_cbmif: self._debug("[main]", self._recv_worker.name, "finished") #---------------------------------------------------------------- # access register file #---------------------------------------------------------------- def write_register(self, address, value): """Write a value into a register.""" addr = ftdi_cbmnet.ADDR_CTRL words = [RF_WRITE, address, value] self._cbmif_write(addr, words) def read_register(self, address, clear_skip=False, request_skip=False, request_only=False): """Read the value from a register.""" if not request_skip: if not clear_skip: # Workaround for retransmit bug in SPADIC 1.0 CBMnet: # Sometimes old register reads are retransmitted -> Clear # software read buffer before sending the read request to be # sure to get the newest value. self._ctrl_queue.clear(address) # End workaround addr = ftdi_cbmnet.ADDR_CTRL words = [RF_READ, address, 0] self._cbmif_write(addr, words) if not request_only: try: return self._ctrl_queue.get(address, timeout=1) except IOError: raise #---------------------------------------------------------------- # send DLMs #---------------------------------------------------------------- def send_dlm(self, number): """Send a DLM.""" addr = ftdi_cbmnet.ADDR_DLM words = [number] self._cbmif_write(addr, words) def readout_enable(self, enable): """Start or stop data taking in the chip.""" dlm = 8 if enable else 9 self.send_dlm(dlm) #---------------------------------------------------------------- # read messages from groups A and B #---------------------------------------------------------------- def read_groupA(self, timeout=1, raw=False): """Get one message from group A, if available.""" try: data = self._dataA_queue.get(timeout=timeout) except Queue.Empty: return None return (data if raw else Message(data)) def read_groupB(self, timeout=1, raw=False): """Get one message from group B, if available.""" try: data = self._dataB_queue.get(timeout=timeout) except Queue.Empty: return None return (data if raw else Message(data))