def get_next(self): poll_t = time() while True: status = self.read_reg("status") if not status: if (time() - poll_t) > self.poll_timeout: raise ClientError("gave up polling") continue elif status & protocol.STATUS_DATA_READY_MASK: break elif status & protocol.STATUS_ERROR_MASK: self.write_reg("main_control", "clear_status") log.info("lost sweep due to server error") else: raise ClientError("got unexpected status ({})".format(status)) buffer_size = self.fixed_buf_size or self.read_reg( "output_data_buffer_length") if buffer_size > 0: buffer = self.read_buf_raw(protocol.MAIN_BUFFER_ADDR, buffer_size) else: buffer = bytearray() info = {} info_regs = utils.get_sweep_info_regs(self.mode) for reg in info_regs: info[reg.name] = self.read_reg(reg) self.write_reg("main_control", "clear_status") return info, buffer
def _connect(self): self._link.timeout = self.CONNECT_ROUTINE_TIMEOUT if self.override_baudrate: self._link.baudrate = self.override_baudrate self._link.connect() try: self._handshake() except links.LinkError as e: raise ClientError("could not connect, no response") from e else: baudrates = [product.baudrate for product in protocol.PRODUCTS] baudrates.append(self.DEFAULT_BASE_BAUDRATE) baudrates = sorted(list(set(baudrates))) self._link.baudrate = baudrates[0] self._link.connect() for i, baudrate in enumerate(baudrates): if i != 0: self._link.baudrate = baudrate sleep(0.2) try: self._handshake() except links.LinkError: log.debug("handshake failed at {} baud".format(baudrate)) else: log.debug("handshake succeeded at {} baud".format(baudrate)) break else: raise ClientError("could not connect, no response") product_id = self._read_reg("product_id") product = {product.id: product for product in protocol.PRODUCTS}[product_id] if baudrate != product.baudrate: log.debug("switching to {} baud...".format(product.baudrate)) self._write_reg("uart_baudrate", product.baudrate) self._link.baudrate = product.baudrate sleep(0.2) self._handshake() log.debug("handshake succeeded at {} baud".format(product.baudrate)) self._link.timeout = self._link.DEFAULT_TIMEOUT ver = self._read_reg("product_version") if ver < protocol.MIN_VERSION: log.warning("server version is not supported (too old)") elif ver != protocol.DEV_VERSION: log.warning("server version might not be fully supported") version_buffer = self._read_buf_raw() version_info = decode_version_buffer(version_buffer) info = {} info.update(version_info) return info
def _write_gpio(self, pin, val): req = protocol.GPIOPinAndVal(pin, val) self._send_packet(req) res = self._recv_packet() if not isinstance(res, protocol.GPIOPinAndVal): raise ClientError("got unexpected packet (expected gpio pin and value)") if res.val != val: raise ClientError("gpio write failed")
def _get_next(self): header, payload = self._recv_frame() status = header["status"] if status == "end": raise ClientError("session ended") elif status != "ok": raise ClientError("server error") return protocol.decode_stream_frame(header, payload, self.squeeze, self._num_subsweeps)
def _connect(self): use_dual_baudrate = bool(self.conf_baudrate) init_baudrate = self.conf_baudrate if use_dual_baudrate else self.base_baudrate self._link.baudrate = init_baudrate self._link.connect() log.debug("port opened at {} baud".format(init_baudrate)) old_timeout = self._link.timeout self._link.timeout = self.CONNECT_ROUTINE_TIMEOUT if use_dual_baudrate: success = False try: self._handshake() except ClientError: log.info( "handshake failed at {} baud, trying {} baud...".format( self.conf_baudrate, self.base_baudrate)) else: success = True if not success: self._link.baudrate = self.base_baudrate try: self._handshake() except links.LinkError as e: raise ClientError("could not connect, no response") from e log.info( "handshake successful, switching to {} baud...".format( self.conf_baudrate)) self._write_reg("uart_baudrate", self.conf_baudrate) self._link.baudrate = self.conf_baudrate sleep(0.2) self._handshake() log.info("successfully connected at {} baud!".format( self.conf_baudrate)) else: try: self._handshake() except links.LinkError as e: raise ClientError("could not connect, no response") from e ver = self._read_reg("product_version") if ver < protocol.MIN_VERSION: log.warning("server version is not supported (too old)") elif ver != protocol.DEV_VERSION: log.warning("server version might not be fully supported") self._link.timeout = old_timeout
def _stop_streaming(self): self._write_reg("main_control", "stop", expect_response=False) t0 = time() while time() - t0 < self._link._timeout: res = self._recv_packet() if isinstance(res, protocol.UnpackedRegWriteResponse): break if not isinstance(res, protocol.UnpackedStreamData): raise ClientError("got unexpected packet while stopping session") else: raise ClientError("timeout while stopping session")
def _setup_session(self, config): if len(config.sensor) > 1: raise ValueError("the register protocol does not support multiple sensors") if config.sensor[0] != 1: raise ValueError("the register protocol currently only supports using sensor 1") mode = protocol.get_mode(config.mode) self._mode = mode self._experimental_stitching = bool(config.experimental_stitching) sweep_rate = None if config.experimental_stitching else config.sweep_rate self.__cmd_proc("set_mode_and_rate", mode, sweep_rate) self._write_reg("main_control", "stop") self._write_reg("mode_selection", mode) if config.experimental_stitching: self._write_reg("repetition_mode", "max") log.warning("experimental stitching on - switching to max freq. mode") else: self._write_reg("repetition_mode", "fixed") self._write_reg("streaming_control", "disable") self._write_reg("sensor_power_mode", "d") if mode == "iq": self._write_reg("output_data_compression", 1) rvs = utils.get_reg_vals_for_config(config) for rv in rvs: self._write_reg_raw(rv.addr, rv.val) self._write_reg("main_control", "create") sleep(SPI_MAIN_CTRL_SLEEP) status = self._read_reg("status") if status & protocol.STATUS_ERROR_ON_SERVICE_CREATION_MASK: raise ClientError("session setup failed") info = {} info_regs = utils.get_session_info_regs(mode) for reg in info_regs: info[reg.name] = self._read_reg(reg) self._num_subsweeps = info.get("number_of_subsweeps") # data rate check data_length = info.get("data_length") freq = info.get("frequency") bpp = protocol.BYTE_PER_POINT.get(mode) if data_length: log.debug("assumed data length: {}".format(data_length)) if bpp and freq and not config.experimental_stitching: data_rate = 8 * bpp * data_length * freq log_text = "data rate: {:.2f} Mbit/s".format(data_rate*1e-6) log.info(log_text) return info
def _connect(self): self._cmd_queue = mp.Queue() self._data_queue = mp.Queue() args = ( self._cmd_queue, self._data_queue, ) self._proc = SPICommProcess(*args) self._proc.start() self.__cmd_proc("connect") log.debug("connected") idn_reg = self._read_reg("product_id") possible_ids = [product.id for product in protocol.PRODUCTS] if idn_reg not in possible_ids: raise ClientError("unexpected product id") ver = self._read_reg("product_version") if ver < protocol.MIN_VERSION: log.warning("server version is not supported (too old)") elif ver != protocol.DEV_VERSION: log.warning("server version might not be fully supported") version_buffer = self._read_main_buffer() version_info = utils.decode_version_buffer(version_buffer) info = {} info.update(version_info) return info
def _write_reg_raw(self, addr, enc_val, expect_response=True): addr = protocol.get_addr_for_reg(addr) rrv = protocol.UnpackedRegVal(addr, enc_val) req = protocol.UnpackedRegWriteRequest(rrv) self._send_packet(req) log.debug("sent reg w req: addr: {:3} val: {}".format(addr, self._fmt_enc_val(enc_val))) if expect_response: res = self._recv_packet() if not isinstance(res, protocol.UnpackedRegWriteResponse): raise ClientError("got unexpected packet (expected reg write response)") if res.reg_val != rrv: raise ClientError("reg write failed") log.debug("recv reg w res: ok")
def _get_next(self): packet = self._recv_packet(allow_recovery_skip=True) if not isinstance(packet, protocol.UnpackedStreamData): raise ClientError("got unexpected type of frame") info = {} for addr, enc_val in packet.result_info: try: reg = protocol.get_reg(addr, self._mode) val = protocol.decode_reg_val(reg, enc_val) except protocol.ProtocolError: log.info("got unknown reg val in result info") log.info("addr: {}, value: {}".format( addr, utils.fmt_enc_val(enc_val))) else: info[reg.name] = val data = protocol.decode_output_buffer(packet.buffer, self._mode, self._num_subsweeps) if self.squeeze: return info, data else: return [info], np.expand_dims(data, 0)
def _get_next(self): ret_cmd, ret_args = self._data_queue.get() if ret_cmd == "error": raise ClientError("exception raised in SPI communcation process") elif ret_cmd != "get_next": raise ClientError info, buffer = ret_args data = protocol.decode_output_buffer(buffer, self._mode, self._num_subsweeps) if not self._experimental_stitching: cur_seq_num = info.get("sequence_number") if cur_seq_num: if self._seq_num: if cur_seq_num > self._seq_num + 1: log.info("missed sweep") if cur_seq_num <= self._seq_num: log.info("got same sweep twice") self._seq_num = cur_seq_num if self.squeeze: return info, data else: return [info], np.expand_dims(data, 0)
def _init_session(self): if self._session_cmd is None: raise ClientError self._send_cmd(self._session_cmd) header, _ = self._recv_frame() if header["status"] == "error": raise ClientError("server error while initializing session") elif header["status"] != "ok": raise ClientError("got unexpected header") log.debug("session initialized") self._session_ready = True return protocol.get_session_info_for_header(header)
def _recv_packet(self, allow_recovery_skip=False): buf_1 = self._link.recv(1 + protocol.LEN_FIELD_SIZE) start_marker = buf_1[0] packet_len = int.from_bytes(buf_1[1:], protocol.BO) if start_marker != protocol.START_MARKER: raise ClientError("got invalid frame (incorrect start marker)") buf_2 = self._link.recv(packet_len + 2) packet = buf_2[:-1] end_marker = buf_2[-1] if end_marker != protocol.END_MARKER: if not allow_recovery_skip: raise ClientError("got invalid frame (incorrect end marker)") log.debug( "got invalid frame (incorrect end marker), attempting recovery" ) buf_2.extend(self._link.recv(1 + protocol.LEN_FIELD_SIZE)) si = 0 ei = len(buf_2) expected_sub_len = protocol.LEN_FIELD_SIZE + packet_len + 3 while True: si = buf_2.find(buf_1, si, ei) if si < 0: raise ClientError( "got invalid frame and could not recover") sub_len_diff = expected_sub_len - (len(buf_2) - si) if sub_len_diff > 0: buf_2.extend(self._link.recv(sub_len_diff)) if buf_2[-1] != protocol.END_MARKER: log.debug("recovery attempt failed") continue packet = buf_2[si + 1 + protocol.LEN_FIELD_SIZE:-1] break log.warning("successfully recovered from corrupt frame") return protocol.unpack_packet(packet)
def _read_gpio(self, pin): req = protocol.GPIOPin(pin) self._send_packet(req) res = self._recv_packet() if not isinstance(res, protocol.GPIOPinAndVal): raise ClientError("got unexpected packet (expected gpio pin and value)") return res.val
def _setup_session(self, config): self._config = config try: mock_class = mock_class_map[config.mode] except KeyError as e: raise ClientError("mode not supported") from e self._mocker = mock_class(config) return self._mocker.session_info
def __cmd_proc(self, cmd, *args): log.debug("sending cmd to proc: {}".format(cmd)) self._cmd_queue.put((cmd, args)) if cmd == "stop_streaming": while True: ret_cmd, _ = self._data_queue.get() if ret_cmd == cmd: break elif ret_cmd == "error": raise ClientError("exception raised in SPI communcation process") elif ret_cmd != "get_next": raise ClientError ret_args = None else: ret_cmd, ret_args = self._data_queue.get() if ret_cmd == "error": raise ClientError("exception raised in SPI communcation process") elif ret_cmd != cmd: raise ClientError return ret_args
def start_streaming(self): self.write_reg("main_control", "activate") sleep(SPI_MAIN_CTRL_SLEEP) self.write_reg("main_control", "clear_status") if protocol.FIXED_BUF_SIZE.get(self.mode): self.fixed_buf_size = self.read_reg("output_data_buffer_length") log.info("using fixed buffer size of {}".format(self.fixed_buf_size)) if self.fixed_buf_size == 0: raise ClientError("got unexpected buffer length of 0") else: self.fixed_buf_size = None
def _init_session(self, retry=True): if self._session_cmd is None: raise ClientError self._send_cmd(self._session_cmd) header, _ = self._recv_frame() if header["status"] == "error": if retry: return self._init_session(retry=False) else: raise ClientError("server error while initializing session") elif header["status"] != "ok": raise ClientError("got unexpected header") log.debug("session initialized") self._session_ready = True info = protocol.get_session_info_for_header(header) self._num_subsweeps = info.get("number_of_subsweeps") return info
def _read_buf_raw(self, addr=protocol.MAIN_BUFFER_ADDR): req = protocol.BufferReadRequest(addr) self._send_packet(req) log.debug("sent buf r req: addr: 0x{:02x}".format(addr)) res = self._recv_packet() if not isinstance(res, protocol.BufferReadResponse): raise ClientError("got unexpected type of frame") log.debug("recv buf r res: addr: 0x{:02x} len: {}".format(addr, len(res.buffer))) return res.buffer
def _handshake(self): self._write_reg("main_control", "stop", expect_response=False) exp_addr = protocol.get_addr_for_reg("main_control") exp_enc_val = protocol.encode_reg_val("main_control", "stop") exp_reg_val = protocol.UnpackedRegVal(exp_addr, exp_enc_val) exp_packet = protocol.UnpackedRegWriteResponse(exp_reg_val) exp_frame = protocol.insert_packet_into_frame(exp_packet) self._link.recv_until(exp_frame) idn_reg = self._read_reg("product_id") if idn_reg != protocol.EXPECTED_ID: raise ClientError("unexpected product id")
def _connect(self): info = {} self._link.connect() cmd = {"cmd": "get_version"} self._send_cmd(cmd) try: header, _ = self._recv_frame() except links.LinkError as e: raise ClientError("no response from server") from e log.debug("connected and got a response") if header["status"] != "ok": raise ClientError("server error while connecting") msg = header["message"].lower() log.info("version msg: {}".format(msg)) startstr = "server version v" if not msg.startswith(startstr): log.warning("server version unknown") return info server_version_str = msg[len(startstr):].strip() info.update(decode_version_str(server_version_str)) if info["strict_version"] >= StrictVersion("1.10"): cmd = {"cmd": "get_board_sensor_count"} self._send_cmd(cmd) header, _ = self._recv_frame() msg = header["message"] board_sensor_count = int(msg) info["board_sensor_count"] = board_sensor_count return info
def _run(self): while True: (cmd, cmd_args) = self.cmd_q.get() if hasattr(self, cmd): ret = getattr(self, cmd)(*cmd_args) self.data_q.put((cmd, ret)) if cmd == "start_streaming": self.poll() elif cmd == "disconnect": break else: raise ClientError("unknown cmd {}".format(cmd))
def _handshake(self): self._write_reg("main_control", "stop", expect_response=False) exp_addr = protocol.get_addr_for_reg("main_control") exp_enc_val = protocol.encode_reg_val("main_control", "stop") exp_reg_val = protocol.RegVal(exp_addr, exp_enc_val) exp_packet = protocol.RegWriteResponse(exp_reg_val) exp_frame = protocol.insert_packet_into_frame(exp_packet) self._link.recv_until(exp_frame) idn_reg = self._read_reg("product_id") possible_ids = [product.id for product in protocol.PRODUCTS] if idn_reg not in possible_ids: raise ClientError("unexpected product id")
def get_dict_for_config(config): d = {} for pair in KEY_AND_CONFIG_ATTR_PAIRS: config_val = getattr(config, pair.config_attr, None) if config_val is None: if pair.required: raise ClientError("{} needs to be set in config".format( pair.config_attr)) else: if isinstance(config_val, bool): d[pair.key] = int(config_val) else: d[pair.key] = config_val return d
def _connect(self): self._link.connect() cmd = {"cmd": "get_version"} self._send_cmd(cmd) try: header, _ = self._recv_frame() except links.LinkError as e: raise ClientError("no response from server") from e log.debug("connected and got a response") if header["status"] != "ok": raise ClientError("server error while connecting") msg = header["message"].lower() log.debug("version msg: {}".format(msg)) startstr = "server version v" if not msg.startswith(startstr): log.warn("server version unknown") return server_version_str = msg[len(startstr):].strip() try: server_version = StrictVersion(server_version_str) except ValueError: log.warn("server version unknown") return if server_version < MIN_VERSION: log.warn("server version is not supported (too old)") elif server_version != DEV_VERSION: log.warn("server version might not be fully supported")
def _read_reg_raw(self, addr): addr = protocol.get_addr_for_reg(addr) req = protocol.UnpackedRegReadRequest(addr) self._send_packet(req) log.debug("sent reg r req: addr: {:3}".format(addr)) res = self._recv_packet() if not isinstance(res, protocol.UnpackedRegReadResponse): raise ClientError("got unexpected type of frame") enc_val = res.reg_val.val log.debug("recv reg r res: addr: {:3} val: {}".format(addr, self._fmt_enc_val(enc_val))) return enc_val
def _setup_session(self, config): self._config = config update_rate_limit = 100 if config.experimental_stitching or config.sweep_rate > update_rate_limit: self._update_rate = update_rate_limit else: self._update_rate = config.sweep_rate try: mock_class = mock_class_map[config.mode] except KeyError as e: raise ClientError("mode not supported") from e self._mocker = mock_class(config) return self._mocker.session_info
def _connect(self): max_baud = links.BaseSerialLink.MAX_BAUDRATE default_baud = links.BaseSerialLink.DEFAULT_BAUDRATE self._link.baudrate = max_baud self._link.connect() log.debug("connected at {} baud".format(max_baud)) success = False try: self._handshake() except ClientError: log.info("handshake failed at {} baud, trying {} baud..." .format(max_baud, default_baud)) else: success = True if not success: self._link.disconnect() self._link.baudrate = default_baud self._link.connect() try: self._handshake() except links.LinkError as e: raise ClientError("could not connect, no response") from e log.info("handshake successful, switching to {} baud...".format(max_baud)) self._write_reg("uart_baudrate", max_baud) self._link.disconnect() self._link.baudrate = max_baud self._link.connect() self._handshake() log.info("successfully connected at {} baud!".format(max_baud)) ver = self._read_reg("product_version") if ver < protocol.MIN_VERSION: log.warn("server version is not supported (too old)") elif ver != protocol.DEV_VERSION: log.warn("server version might not be fully supported")
def _connect(self): self._cmd_queue = mp.Queue() self._data_queue = mp.Queue() args = ( self._cmd_queue, self._data_queue, ) self._proc = SPICommProcess(*args) self._proc.start() self.__cmd_proc("connect") log.debug("connected") idn_reg = self._read_reg("product_id") if idn_reg != protocol.EXPECTED_ID: raise ClientError("unexpected product id") ver = self._read_reg("product_version") if ver < protocol.MIN_VERSION: log.warning("server version is not supported (too old)") elif ver != protocol.DEV_VERSION: log.warning("server version might not be fully supported")