Beispiel #1
0
    def _usb_init_connection(self, model):

        if model not in _OOModelConfig.keys():
            raise _OOError('Unkown OceanOptics spectrometer model: %s' % model)

        vendorId, productId = _OOVendorId, _OOModelConfig[model]['ProductId']
        self._EPout = _OOModelConfig[model]['EPout']
        self._EPin0 = _OOModelConfig[model]['EPin0']
        self._EPin1 = _OOModelConfig[model]['EPin1']
        self._EPin0_size = _OOModelConfig[model]['EPin0_size']
        self._EPin1_size = _OOModelConfig[model]['EPin1_size']

        devices = usb.core.find(find_all=True,
                        custom_match=lambda d: (d.idVendor==vendorId and
                                                d.idProduct in productId))
        # FIXME: generator fix
        devices = list(devices)

        try:
            self._dev = devices.pop(0)
        except (AttributeError, IndexError):
            raise _OOError('No OceanOptics %s spectrometer found!' % model)
        else:
            if devices:
                warnings.warn('Currently the first device matching the '
                              'Vendor/Product id is used')

        self._dev.set_configuration()
        self._USBTIMEOUT = self._dev.default_timeout * 1e-3
Beispiel #2
0
    def _usb_init_connection(self, model):

        if model not in _OOModelConfig.keys():
            raise _OOError('Unkown OceanOptics spectrometer model: %s' % model)

        # Add model
        self.model = model

        vendorId, productId = _OOVendorId, _OOModelConfig[model]['ProductId']
        self._EPout = _OOModelConfig[model]['EPout']
        self._EPin0 = _OOModelConfig[model]['EPin0']
        self._EPin1 = _OOModelConfig[model]['EPin1']
        self._EPin0_size = _OOModelConfig[model]['EPin0_size']
        self._EPin1_size = _OOModelConfig[model]['EPin1_size']
        self._min_integration_time, self._max_integration_time = _OOMinMaxIT[model]

        devices = usb.core.find(find_all=True,
                        custom_match=lambda d: (d.idVendor==vendorId and
                                                d.idProduct in productId))
        # FIXME: generator fix
        devices = list(devices)

        try:
            self._dev = devices.pop(0)
        except (AttributeError, IndexError):
            raise _OOError('No OceanOptics %s spectrometer found!' % model)
        else:
            if devices:
                warnings.warn('Currently the first device matching the '
                              'Vendor/Product id is used')

        self._dev.set_configuration()
        self._USBTIMEOUT = self._dev.default_timeout * 1e-3
Beispiel #3
0
    def _check_incoming_message_header(self, header):
        """message layout, see STS datasheet

        """
        assert len(
            header
        ) == 44, "header has wrong length! len(header): %d" % len(header)

        data = struct.unpack(self._const.HEADER_FMT, header)

        assert data[
            0] == self._const.HEADER_START_BYTES, 'header start_bytes wrong: %d' % data[
                0]
        assert data[
            1] == self._const.HEADER_PROTOCOL_VERSION, 'header protocol version wrong: %d' % data[
                1]

        flags = data[2]
        if flags == 0:
            pass
        if flags & self._const.FLAG_RESPONSE_TO_REQUEST:
            pass  # TODO: propagate?
        if flags & self._const.FLAG_ACK:
            pass  # TODO: propagate?
        if flags & self._const.FLAG_REQUEST_ACK:
            pass  # TODO: only the host should be able to set this?
        if (flags & self._const.FLAG_NACK) or (
                flags & self._const.FLAG_HW_EXCEPTION):
            error = data[3]
            if error != 0:  # != SUCCESS
                raise _OOError(self._const.ERROR_CODES[error])
            else:
                pass  # TODO: should we do simething here?
        if flags & self._const.FLAG_PROTOCOL_DEPRECATED:
            raise _OOError("Protocol deprecated?!?")

        # msgtype = data[4]
        # regarding = data[5]

        checksumtype = data[7]  # TODO: implement checksums.
        assert checksumtype in [
            self._const.CHECKSUM_TYPE_NONE, self._const.CHECKSUM_TYPE_MD5
        ], 'the checksum type is unkown: %d' % checksumtype

        # immediate_length = data[8]
        # immediate_data = data[9]
        bytes_remaining = data[10]

        return bytes_remaining, checksumtype
def get_a_random_spectrometer():
    ProductId = {}
    for model in _OOSupMod:
        pid = _OOModConf[model]['ProductId']
        ProductId.update(zip(pid, [model] * len(pid)))

    devices = usb.core.find(
        find_all=True,
        custom_match=lambda d:
        (d.idVendor == _OOVendorId and d.idProduct in ProductId.keys()))
    # TODO: ??? usb.core.find can also return a generator ???
    devices = list(devices)

    if devices:
        print '> found:'
    else:
        raise _OOError('no supported spectrometers found')
    for d in devices:
        print '>  - %s' % ProductId[d.idProduct]

    mod = ProductId[devices[0].idProduct]
    print '>'
    print '> returning first %s as OceanOpticsSpectrometer' % mod

    spec_class = _models[mod]
    return spec_class()
Beispiel #5
0
 def _query_information(self, address, raw=False):
     """ send command 0x05 """
     ret = self._usb_query(struct.pack('<BB', 0x05, int(address)))
     if bool(raw): return ret
     if ret[0] != 0x05 or ret[1] != int(address) % 0xFF:
         raise _OOError('query_information: Wrong answer')
     return ret[2:ret[2:].index(0) + 2].tostring()
Beispiel #6
0
    def _request_spectrum(self):
        """returns the spectrum array.

        """
        # Get all data
        msg = self._construct_outgoing_message(self._const.MSG_GET_AND_SEND_RAW_SPECTRUM, "")
        self._usb_send(msg)
        time.sleep(max(self._integration_time - self._USBTIMEOUT, 0))
        ret = self._usb_read()

        remaining_bytes, checksumtype = self._check_incoming_message_header(ret[:44])
        length_payload_footer = remaining_bytes

        remaining_bytes -= len(ret[44:])

        while True:
            if remaining_bytes <= 0:
                break
            N_bytes = min(remaining_bytes, self._EPin0_size)
            ret += self._usb_read(epi_size=N_bytes)
            remaining_bytes -= N_bytes

        if length_payload_footer != len(ret[44:]):
            raise _OOError("There is a remaining packet length error: %d vs %d" % (remaining_bytes, len(ret[44:])))

        checksum = self._check_incoming_message_footer(ret[-20:])
        if (checksumtype == self._const.CHECKSUM_TYPE_MD5) and (checksum != hashlib.md5(ret[:-20]).digest()):
            # TODO: raise Error
            warnings.warn("The checksums differ, but we ignore this for now.")
        data = self._extract_message_data(ret)

        spectrum = struct.unpack("<%dH" % self._pixels, data)
        return np.array(spectrum, dtype=np.float64)
Beispiel #7
0
    def _extract_message_data(self, msg):
        """message layout, see STS datasheet

        """
        payload_length = len(msg) - 44 - 20  # - HeaderLength - FooterLength
        assert payload_length >= 0, "the received message was shorter than 64 bytes: %d" % payload_length
        payload_fmt = "%ds" % payload_length
        FMT = self._const.HEADER_FMT + payload_fmt + self._const.FOOTER_FMT

        data = struct.unpack(FMT, msg)

        msgtype = data[4]

        immediate_length = data[8]
        immediate_data = data[9]
        payload = data[11]

        if (immediate_length > 0) and len(payload) > 0:
            raise _OOError("the device returned immediate data and payload data? cmd: %d" % msgtype)
        elif immediate_length > 0:
            return immediate_data[:immediate_length]
        elif payload_length > 0:
            return payload
        else:
            return ""
Beispiel #8
0
    def _request_spectrum(self):
        """returns the spectrum array.

        """
        # Get all data
        msg = self._construct_outgoing_message(self._const.MSG_GET_AND_SEND_RAW_SPECTRUM, "")
        self._usb_send(msg)
        time.sleep(max(self._integration_time - self._USBTIMEOUT, 0))
        ret = self._usb_read()

        remaining_bytes, checksumtype = self._check_incoming_message_header(ret[:44])
        length_payload_footer = remaining_bytes

        remaining_bytes -= len(ret[44:])

        while True:
            if remaining_bytes <= 0:
                break
            N_bytes = min(remaining_bytes, self._EPin0_size)
            ret += self._usb_read(epi_size=N_bytes)
            remaining_bytes -= N_bytes

        if length_payload_footer != len(ret[44:]):
            raise _OOError("There is a remaining packet length error: %d vs %d" % (remaining_bytes, len(ret[44:])))

        checksum = self._check_incoming_message_footer(ret[-20:])
        if (checksumtype == self._const.CHECKSUM_TYPE_MD5) and (checksum != hashlib.md5(ret[:-20]).digest()):
            # TODO: raise Error
            warnings.warn("The checksums differ, but we ignore this for now.")
        data = self._extract_message_data(ret)

        spectrum = struct.unpack("<%dH" % self._pixels, data)
        return np.array(spectrum, dtype=np.float64)
Beispiel #9
0
    def _extract_message_data(self, msg):
        """message layout, see STS datasheet

        """
        payload_length = len(msg) - 44 - 20  # - HeaderLength - FooterLength
        assert payload_length >= 0, "the received message was shorter than 64 bytes: %d" % payload_length
        payload_fmt = "%ds" % payload_length
        FMT = self._const.HEADER_FMT + payload_fmt + self._const.FOOTER_FMT

        data = struct.unpack(FMT, msg)

        msgtype = data[4]

        immediate_length = data[8]
        immediate_data = data[9]
        payload = data[11]

        if (immediate_length > 0) and len(payload) > 0:
            raise _OOError(
                "the device returned immediate data and payload data? cmd: %d"
                % msgtype)
        elif immediate_length > 0:
            return immediate_data[:immediate_length]
        elif payload_length > 0:
            return payload
        else:
            return ""
Beispiel #10
0
 def _query_information(self, address, raw=False):
     """ send command 0x05 """
     ret = self._usb_query(struct.pack('<BB', 0x05, int(address)))
     if bool(raw): return ret
     if ret[0] != 0x05 or ret[1] != int(address) % 0xFF:
         raise _OOError('query_information: Wrong answer')
     return ret[2:ret[2:].index(0) + 2].tostring()
Beispiel #11
0
def get_a_random_spectrometer():
    ProductId = {}
    for model in _OOSupMod:
        pid = _OOModConf[model]['ProductId']
        ProductId.update(zip(pid, [model] * len(pid)))

    devices = usb.core.find(find_all=True,
                            custom_match=lambda d: (d.idVendor == _OOVendorId and
                                                    d.idProduct in ProductId.keys()))
    # TODO: ??? usb.core.find can also return a generator ???
    devices = list(devices)

    if devices:
        print '> found:'
    else:
        raise _OOError('no supported spectrometers found')
    for d in devices:
        print '>  - %s' % ProductId[d.idProduct]

    mod = ProductId[devices[0].idProduct]
    print '>'
    print '> returning first %s as OceanOpticsSpectrometer' % mod

    spec_class = _models[mod]
    return spec_class()
Beispiel #12
0
 def _init_robust_spectrum(self):
     self.integration_time(0.005)
     for i in range(10):
         try:
             self._request_spectrum()
             break
         except: raise
     else: raise _OOError('Initialization SPECTRUM')
Beispiel #13
0
 def _init_robust_status(self):
     for i in range(10):
         try:
             status = self._query_status()
             break
         except usb.core.USBError: pass
     else: raise _OOError('Initialization USBCOM')
     return status
Beispiel #14
0
 def _init_robust_status(self):
     for i in range(10):
         try:
             status = self._query_status()
             break
         except usb.core.USBError: pass
     else: raise _OOError('Initialization USBCOM')
     return status
Beispiel #15
0
 def _init_robust_spectrum(self):
     self.integration_time(0.005)
     for i in range(10):
         try:
             self._request_spectrum()
             break
         except: raise
     else: raise _OOError('Initialization SPECTRUM')
Beispiel #16
0
 def _read_pcb_temperature(self):
     """ just for compatibility with parent class """
     """ 0x6C read pcb temperature """
     self._usb_send(struct.pack('<B', 0x6C))
     ret = self._usb_read()
     if (ret[0] != 0x08) | (ret[0] != 0x08):
         raise _OOError('read_temperatures: Wrong answer')
     ret = struct.unpack('<h', ret[1:3])[0] * 0.003906
     return ret
Beispiel #17
0
 def _read_pcb_temperature(self):
     """ just for compatibility with parent class """
     """ 0x6C read pcb temperature """
     self._usb_send(struct.pack('<B', 0x6C))
     ret = self._usb_read()
     if (ret[0] != 0x08) | (ret[0] != 0x08):
         raise _OOError('read_temperatures: Wrong answer')
     ret = struct.unpack('<h', ret[1:3])[0] * 0.003906
     return ret
Beispiel #18
0
    def _check_incoming_message_header(self, header):
        """message layout, see STS datasheet

        """
        assert len(header) == 44, "header has wrong length! len(header): %d" % len(header)

        data = struct.unpack(self._const.HEADER_FMT, header)

        assert data[0] == self._const.HEADER_START_BYTES, "header start_bytes wrong: %d" % data[0]
        assert data[1] == self._const.HEADER_PROTOCOL_VERSION, "header protocol version wrong: %d" % data[1]

        flags = data[2]
        if flags == 0:
            pass
        if flags & self._const.FLAG_RESPONSE_TO_REQUEST:
            pass  # TODO: propagate?
        if flags & self._const.FLAG_ACK:
            pass  # TODO: propagate?
        if flags & self._const.FLAG_REQUEST_ACK:
            pass  # TODO: only the host should be able to set this?
        if (flags & self._const.FLAG_NACK) or (flags & self._const.FLAG_HW_EXCEPTION):
            error = data[3]
            if error != 0:  # != SUCCESS
                raise _OOError(self._const.ERROR_CODES[error])
            else:
                pass  # TODO: should we do simething here?
        if flags & self._const.FLAG_PROTOCOL_DEPRECATED:
            raise _OOError("Protocol deprecated?!?")

        # msgtype = data[4]
        # regarding = data[5]

        checksumtype = data[7]  # TODO: implement checksums.
        assert checksumtype in [self._const.CHECKSUM_TYPE_NONE, self._const.CHECKSUM_TYPE_MD5], (
            "the checksum type is unkown: %d" % checksumtype
        )

        # immediate_length = data[8]
        # immediate_data = data[9]
        bytes_remaining = data[10]

        return bytes_remaining, checksumtype
Beispiel #19
0
    def integration_time(self, time_sec=None):
        """get or set the integration_time in seconds

        """
        if time_sec is not None:
            if self._min_integration_time <= time_sec < self._max_integration_time:
                self._integration_time = self._set_integration_time(time_sec)
            else:
                raise _OOError("Integration time for %s required to be %f <= t < %f" %
                               (self.model, self._min_integration_time, self._max_integration_time))
        return self._integration_time
def get_spectrometer(serial_num=None):
    """
    If serial_num is specified, then returns the object corresponding to that 
    particular spectrometer, otherwise the first available spectrometer is 
    returned.
    
    Parameters
    ----------
    serial_num : string, optional
        the serial number of the spectrometer that you want to connect to
    
    Returns
    -------
    spectrometer : OceanOpticsBase object
        the spectrometer with the requested serial number, or the first 
        available spectrometer if serial_num=None
    
    Raises
    ------
        OceanOpticsError: 
            if the requested spectrometer is not available.
    """

    spectrometers = get_available_spectrometers()

    if not spectrometers:
        raise _OOError('no available spectrometers found')

    if serial_num is None:
        #then just return the first spectrometer in the list
        serial_num = spectrometers.keys()[0]

    try:
        selected_spectro = spectrometers.pop(serial_num)
    except KeyError:
        raise _OOError('Spectrometer %s is not available' % serial_num)
    finally:
        for s in spectrometers.values():
            s.dispose()

    return selected_spectro
Beispiel #21
0
 def integration_time(self, time_sec=None):
     """get or set integration_time in seconds
     """
     if not (time_sec is None):
         if self._min_integration_time <= time_sec < self._max_integration_time:
             time_us = time_sec * 1000000
             self._set_integration_time(time_us)
         else:
             raise _OOError("Integration time for %s required to be %f <= t < %f" %
                            (self.model, self._min_integration_time, self._max_integration_time))
     self._integration_time = self._query_status()['integration_time']*1e-6
     return self._integration_time
Beispiel #22
0
 def _request_spectrum(self):
     self._usb_send(struct.pack('<B', 0x09))
     time.sleep(max(self._integration_time - self._USBTIMEOUT, 0))
     ret = [ self._usb_read(epi=self._EPspec, epi_size=self._packet_size)
                         for _ in range(self._packet_N) ]
     ret = sum( ret[1:], ret[0] )
     sync = self._usb_read(epi=self._EPspec, epi_size=1)
     if sync[0] != 0x69:
         raise _OOError('request_spectrum: Wrong sync byte')
     spectrum = struct.unpack('<'+'H'*self._pixels, ret)
     spectrum = map(self._packet_func, spectrum)
     return spectrum
Beispiel #23
0
 def _request_spectrum(self):
     self._usb_send(struct.pack('<B', 0x09))
     time.sleep(max(self._integration_time - 0.1*self._USBTIMEOUT, 0))
     ret = [ self._usb_read(epi=self._EPspec, epi_size=self._packet_size)
                         for _ in range(self._packet_N) ]
     ret = sum( ret[1:], ret[0] )
     sync = self._usb_read(epi=self._EPspec, epi_size=1)
     if sync[0] != 0x69:
         raise _OOError('request_spectrum: Wrong sync byte')
     spectrum = struct.unpack('<'+'H'*self._pixels, ret)
     spectrum = map(self._packet_func, spectrum)
     return spectrum
Beispiel #24
0
    def integration_time(self, time_sec=None):
        """get or set the integration_time in seconds

        """
        if time_sec is not None:
            if self._min_integration_time <= time_sec < self._max_integration_time:
                self._integration_time = self._set_integration_time(time_sec)
            else:
                raise _OOError(
                    "Integration time for %s required to be %f <= t < %f" %
                    (self.model, self._min_integration_time,
                     self._max_integration_time))
        return self._integration_time
Beispiel #25
0
 def get_temperatures(self):
     """
     0x6C read pcb and heatsink temperature
     """
     self._usb_send(struct.pack('<B', 0x6C))
     time.sleep(0.1)  # wait 200ms
     ret = self._usb_read()
     time.sleep(0.1)
     if (ret[0] != 0x08) | (ret[0] != 0x08):
         raise _OOError('read_temperatures: Wrong answer')
     pcb = struct.unpack('<h', ret[1:3])[0] * 0.003906
     heatsink = struct.unpack('<h', ret[4:6])[0] * 0.003906
     ret = (pcb, heatsink)
     return ret
Beispiel #26
0
 def get_temperatures(self):
     """
     0x6C read pcb and heatsink temperature
     """
     self._usb_send(struct.pack('<B', 0x6C))
     time.sleep(0.1)  # wait 200ms
     ret = self._usb_read()
     time.sleep(0.1)
     if (ret[0] != 0x08) | (ret[0] != 0x08):
         raise _OOError('read_temperatures: Wrong answer')
     pcb = struct.unpack('<h', ret[1:3])[0] * 0.003906
     heatsink = struct.unpack('<h', ret[4:6])[0] * 0.003906
     ret = (pcb, heatsink)
     return ret
Beispiel #27
0
 def integration_time(self, time_sec=None):
     """get or set integration_time in seconds
     """
     if not (time_sec is None):
         if self._min_integration_time <= time_sec < self._max_integration_time:
             time_us = time_sec * 1000000
             self._set_integration_time(time_us)
         else:
             raise _OOError(
                 "Integration time for %s required to be %f <= t < %f" %
                 (self.model, self._min_integration_time,
                  self._max_integration_time))
     self._integration_time = self._query_status(
     )['integration_time'] * 1e-6
     return self._integration_time
Beispiel #28
0
    def _query_data(self, msgtype, payload):
        """recommended query function"""
        msg = self._construct_outgoing_message(msgtype, payload, request_ACK=False)
        ret = self._usb_query(msg)

        remaining_bytes, checksumtype = self._check_incoming_message_header(ret[:44])
        if remaining_bytes != len(ret[44:]):
            raise _OOError("There is a remaining packet length error: %d vs %d" % (remaining_bytes, len(ret[44:])))

        checksum = self._check_incoming_message_footer(ret[-20:])
        if (checksumtype == self._const.CHECKSUM_TYPE_MD5) and (checksum != hashlib.md5(ret[:-20]).digest()):
            # TODO: raise Error
            warnings.warn("The checksums differ, but we ignore this for now.")
        data = self._extract_message_data(ret)
        return data
Beispiel #29
0
    def _query_data(self, msgtype, payload):
        """recommended query function"""
        msg = self._construct_outgoing_message(msgtype, payload, request_ACK=False)
        ret = self._usb_query(msg)

        remaining_bytes, checksumtype = self._check_incoming_message_header(ret[:44])
        if remaining_bytes != len(ret[44:]):
            raise _OOError("There is a remaining packet length error: %d vs %d" % (remaining_bytes, len(ret[44:])))

        checksum = self._check_incoming_message_footer(ret[-20:])
        if (checksumtype == self._const.CHECKSUM_TYPE_MD5) and (checksum != hashlib.md5(ret[:-20]).digest()):
            # TODO: raise Error
            warnings.warn("The checksums differ, but we ignore this for now.")
        data = self._extract_message_data(ret)
        return data
Beispiel #30
0
    def _request_spectrum(self):
        self._usb_send(struct.pack('<B', 0x09))
        time.sleep(max(self._integration_time - self._USBTIMEOUT, 0))
        ret = [ self._usb_read(epi=self._EPspec, epi_size=self._packet_size)
                            for _ in range(self._packet_N) ]
        ret = sum( ret[1:], ret[0] )

        # XXX: This sorts the the packets in the right order
        ret = "".join(ret[j*self._packet_size + i] + ret[(j+1)*self._packet_size + i]
                      for j in range(self._packet_N) for i in range(self._packet_size))

        sync = self._usb_read(epi=self._EPspec, epi_size=1)
        if sync[0] != 0x69:
            raise _OOError('request_spectrum: Wrong sync byte')
        spectrum = struct.unpack('<'+'H'*self._pixels, ret)
        spectrum = map(self._packet_func, spectrum)
        return spectrum
Beispiel #31
0
    def _request_spectrum(self):
        self._usb_send(struct.pack('<B', 0x09))
        time.sleep(max(self._integration_time - self._USBTIMEOUT, 0))
        ret = []
        for _ in range(4):
            ret += self._usb_read(epi=self._EPin6, epi_size=self._packet_size)
        for _ in range(self._packet_N - 4):
            ret += self._usb_read(epi=self._EPin2, epi_size=self._packet_size)
        ret = struct.pack('<'+'B'*(self._pixels*2), *ret)

        sync = self._usb_read(epi=self._EPin2, epi_size=1)
        if sync[0] != 0x69:
            raise _OOError('request_spectrum: Wrong sync byte')

        spectrum = struct.unpack('<'+'H'*self._pixels, ret)
        spectrum = map(self._packet_func, spectrum)
        return spectrum
Beispiel #32
0
    def _request_spectrum(self):
        self._usb_send(struct.pack("<B", 0x09))
        time.sleep(max(self._integration_time - self._USBTIMEOUT, 0))
        ret = [self._usb_read(epi=self._EPspec, epi_size=self._packet_size) for _ in range(self._packet_N)]
        ret = sum(ret[1:], ret[0])

        # XXX: This sorts the the packets in the right order
        sorted_ret = []
        for j in range(0, self._packet_N, 2):
            for i in range(self._packet_size):
                sorted_ret.append(chr(ret[j * self._packet_size + i]))
                sorted_ret.append(chr(ret[(j + 1) * self._packet_size + i]))
        ret = "".join(sorted_ret)

        sync = self._usb_read(epi=self._EPspec, epi_size=1)
        if sync[0] != 0x69:
            raise _OOError("request_spectrum: Wrong sync byte")
        spectrum = struct.unpack("<" + "H" * self._pixels, ret)
        spectrum = map(self._packet_func, spectrum)
        return spectrum
    def _request_spectrum(self):
        self._usb_send(struct.pack('<B', 0x09))
        time.sleep(max(self._integration_time - self._USBTIMEOUT, 0))
        ret = [
            self._usb_read(epi=self._EPspec, epi_size=self._packet_size)
            for _ in range(self._packet_N)
        ]
        ret = sum(ret[1:], ret[0])

        # XXX: This sorts the the packets in the right order
        sorted_ret = []
        for j in range(0, self._packet_N, 2):
            for i in range(self._packet_size):
                sorted_ret.append(chr(ret[j * self._packet_size + i]))
                sorted_ret.append(chr(ret[(j + 1) * self._packet_size + i]))
        ret = "".join(sorted_ret)

        sync = self._usb_read(epi=self._EPspec, epi_size=1)
        if sync[0] != 0x69:
            raise _OOError('request_spectrum: Wrong sync byte')
        spectrum = struct.unpack('<' + 'H' * self._pixels, ret)
        spectrum = map(self._packet_func, spectrum)
        return spectrum