QuTech-Delft / QMI

Quantum Measurement Infrastructure
Other
14 stars 4 forks source link

Implement `read_until_timeout` and `discard_read` in QMI_UsbTmcTransport class #43

Closed heevasti closed 1 year ago

heevasti commented 1 year ago

Description =========== For the UsbTmc, the current read and/or read_until and/or read_until_timeout should (try to) return the whole _read_buffer AND whatever the _read_message(timeout) returns, up to their nbytes or message_terminator limits. This is not happening now. Also discard_read should get implemented.

  1. The read method should be modified to work the same way as the QMI_Transport.read base class. It should also start with the existing buffer check

        nbuf = len(self._read_buffer)
        if nbuf >= nbytes:
            # The requested number of bytes are already in the buffer.
            # Return them immediately.
            ret = bytes(self._read_buffer[:nbytes])
            self._read_buffer = self._read_buffer[nbytes:]
            return ret

    And if no buffer is present, then check the timeout value as now and read-in the buffer.

        # USB requires a timeout
        if timeout is None:
            timeout = self.DEFAULT_READ_TIMEOUT
    
        # Read buffer was too short or is empty - read a new message from the instrument.
        self._read_buffer.extend(self._read_message(timeout))

    Then re-check the buffer length. By too short buffer length discard buffer and raise exception. By too long data discard buffer after nbytes and return nbytes data like now. And the with nbytes of data return and clear whole data buffer.

  2. The read_until (of the QMI_UsbTmcTransport) command says in the description that the message_terminator is ignored as it is not somehow valid for USBTMC protocol. This means that actually this command should not be implemented and be set with NotImplementedError and the read_until_timeout be implemented instead. The problem here is that instruments using SCPI protocol use ScpiProtocol class where in ask the read_until is used by default. We cannot change this to read_until_timeout there as also other transports can use this and that would mess things up. So, we would need to keep read_until but change the implementation such that it forwards then to read_until_timeout.

NOTE: If there remains partial messages in the self._read_buffer and this keeps messing up the parsing of responses or similar, currently it is up to the user or e.g. implemented QMI driver commands to call discard_read() to reset the buffer.

  1. Set the discard_read method of the QMI_UsbTmcTransport class to clear the current buffer (self._read_buffer = bytes<array>()).

    def discard_read():
    # We should empty the buffer, or if it is empty, discard the next message from the source
    if not len(self._read_buffer):
        # Read buffer is empty - read a new message from the instrument.
        self._read_message(self.DEFAULT_READ_TIMEOUT)
    
    else:
        self._read_buffer = bytes()     

Affected components


QMI All affected drivers in diamondos and qmi - TBD

Modules to be created


N/A

Modules to be modified


qmi.core.transport

Tests to be created/updated


tests.core.test_transport_usbtmc

Documentation to be updated


CHANGELOG.md