Esempio n. 1
0
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)
Esempio n. 2
0
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)
Esempio n. 3
0
    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)
Esempio n. 4
0
 def __init__(self, expires=2):
     BaseReceiveClient.__init__(self)
     self._recv_queue = IndexQueue()
     self._cache = {}
     self._expires = expires
Esempio n. 5
0
 def __init__(self, expires=2):
     BaseReceiveClient.__init__(self)
     self._recv_queue = IndexQueue()
     self._cache = {}
     self._expires = expires
Esempio n. 6
0
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))