# This file is part of the OpenMV project. # # Copyright (c) 2013-2020 Ibrahim Abdelkader # Copyright (c) 2013-2020 Kwabena W. Agyeman # # This work is licensed under the MIT license, see the file LICENSE for details. import gc, serial, socket, struct, time class rpc: _COMMAND_HEADER_PACKET_MAGIC = 0x1209 _COMMAND_DATA_PACKET_MAGIC = 0xABD1 _RESULT_HEADER_PACKET_MAGIC = 0x9021 _RESULT_DATA_PACKET_MAGIC = 0x1DBA def __def_crc_16(self, data, size): # private crc = 0xFFFF for i in range(size): crc ^= data[i] << 8 for j in range(8): crc = (crc << 1) ^ (0x1021 if crc & 0x8000 else 0) return crc & 0xFFFF def _zero(self, buff, size): # private for i in range(size): buff[i] = 0 def _same(self, data, size): # private if not size: return False old = data[0] for i in range(1, size): new = data[i] if new != old: return False old = new return True # djb2 algorithm; see http://www.cse.yorku.ca/~oz/hash.html def _hash(self, data, size): # private h = 5381 for i in range(size): h = ((h << 5) + h) ^ ord(data[i]) return h & 0xFFFFFFFF def __init__(self): # private self.__crc_16 = self.__def_crc_16 self._stream_writer_queue_depth_max = 255 def _get_packet_pre_alloc(self, payload_len=0): buff = bytearray(payload_len + 4) return (buff, memoryview(buff)[2:-2]) def _get_packet(self, magic_value, payload_buf_tuple, timeout): # private packet = self.get_bytes(payload_buf_tuple[0], timeout) if packet is not None: magic = packet[0] | (packet[1] << 8) crc = packet[-2] | (packet[-1] << 8) if magic == magic_value and crc == self.__crc_16(packet, len(packet) - 2): return payload_buf_tuple[1] return None def _set_packet(self, magic_value, payload=bytes()): # private new_payload = bytearray(len(payload) + 4) new_payload[:2] = struct.pack("> 1) ^ (0xB8 if tx_lfsr & 1 else 0x00) def stream_writer(self, call_back, write_timeout_ms=5000): # public packet = self._stream_get_bytes(bytearray(8), 1000) if packet is None: return magic = packet[0] | (packet[1] << 8) crc = packet[-2] | (packet[-1] << 8) if magic != 0xEDF6 and crc != self.__crc_16(packet, len(packet) - 2): return queue_depth = max(min(struct.unpack("> 1) ^ (0xB8 if rx_lfsr & 1 else 0x00) credits += 1 if credits > 0: data = call_back() try: self._stream_put_bytes(self._set_packet(0x542E, struct.pack("