Compare commits
29 Commits
dev/eis
...
rel/v1.3.0
| Author | SHA1 | Date | |
|---|---|---|---|
| 31b6a60046 | |||
| 12e0ec7c69 | |||
| 7087ded6d4 | |||
| cdb4ddfe04 | |||
| 8d68d15023 | |||
| 3ebf283c89 | |||
| a70d20c4b8 | |||
| 8be3e1fa0e | |||
| e33b4d9a21 | |||
| a38fe5066f | |||
| b6abf0885a | |||
| a3c0f1e4a3 | |||
| 6446204013 | |||
| 3b60d74c47 | |||
| d1c4b0a29f | |||
| 0034681e55 | |||
| 6b3649c8a0 | |||
| 3f1ba0971c | |||
| 95d27aa6f2 | |||
| 651e34d6e0 | |||
| d3621e0c9c | |||
| 0d1b1f4825 | |||
| ec0fe2ec9f | |||
| 67b645dac6 | |||
| a3d794d9a1 | |||
| 197a3a6f05 | |||
| b9dc607ac0 | |||
| ae2f8e7e70 | |||
| a13dde3055 |
@@ -0,0 +1,7 @@
|
||||
.DS_Store
|
||||
*.cpython-37.opt-2.pyc
|
||||
*.pyc
|
||||
*/__pycache__
|
||||
/.vscode
|
||||
/media
|
||||
python/biopro/sever/_identify.py
|
||||
@@ -315,14 +315,6 @@ class CC2650MasterDevice(MasterDevice, metaclass=abc.ABCMeta):
|
||||
|
||||
return cls.CC2650_RESET_PIN
|
||||
|
||||
@classmethod
|
||||
def get_uart_irq_pin(cls) -> OutputPin:
|
||||
if cls.CC2650_UART_IRQ is None:
|
||||
cls.CC2650_UART_IRQ = OutputPin.get_used(P3Pin.MEM_RST, initial=True)
|
||||
|
||||
return cls.CC2650_UART_IRQ
|
||||
|
||||
|
||||
class CC2650Device(Device):
|
||||
|
||||
def __init__(self,
|
||||
@@ -955,9 +947,6 @@ class CC2650SingleMasterDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
self._cc2650.recv_util(..., when=self._cond, timeout=timeout)
|
||||
|
||||
def available_device(self) -> List[int]:
|
||||
return [0]
|
||||
|
||||
@synchronized
|
||||
def scan_callback(self, callback: Callable[[DeviceResponseInfo], None], timeout=5, all_device=False) -> bool:
|
||||
if self._scan_max_time != timeout:
|
||||
@@ -1442,11 +1431,6 @@ class CC2650MultiMasterDevice(CC2650MasterDevice, Synchronized):
|
||||
super().shutdown()
|
||||
self._selector.close()
|
||||
|
||||
def available_device(self) -> List[int]:
|
||||
return list(map(lambda it: it[0],
|
||||
filter(lambda it: it[1] is not None,
|
||||
enumerate(self._cc2650))))
|
||||
|
||||
def get_device(self, device: int) -> Optional[Device]:
|
||||
return self._device[device]
|
||||
|
||||
@@ -1942,10 +1926,8 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
self.log_verbose('reset (hardware)')
|
||||
|
||||
pin.output(False)
|
||||
sleep(0.1)
|
||||
|
||||
# sleep(0.001)
|
||||
pin.output(True)
|
||||
sleep(0.1)
|
||||
|
||||
@synchronized
|
||||
def reset_software(self):
|
||||
@@ -1968,9 +1950,6 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
"""initialize cc2650 (master)"""
|
||||
pass
|
||||
|
||||
def available_device(self) -> List[int]:
|
||||
return [0]
|
||||
|
||||
def scan_send_ins(self):
|
||||
# send scan command
|
||||
try:
|
||||
@@ -1986,21 +1965,16 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
clean_buf = self._cc2650.receive_timeout("20B", timeout=3)
|
||||
print("clean_buf = ", clean_buf)
|
||||
|
||||
def cc2650_uart_irq(self):
|
||||
uart_irq = self.get_uart_irq_pin()
|
||||
uart_irq.output(False)
|
||||
sleep(0.001)
|
||||
uart_irq.output(True)
|
||||
# def cc2650_uart_irq(self):
|
||||
# uart_irq = self.get_uart_irq_pin()
|
||||
# uart_irq.output(False)
|
||||
# sleep(0.001)
|
||||
# uart_irq.output(True)
|
||||
|
||||
@synchronized
|
||||
def scan_callback(self, callback: Callable[[DeviceResponseInfo], None], timeout=5, all_device=False) -> bool:
|
||||
# if self._scan_max_time != timeout:
|
||||
# self.log_info('set max scan limit time', timeout)
|
||||
# self._scan_max_time = timeout
|
||||
|
||||
self._found = found = []
|
||||
self._found_with_id = []
|
||||
number_of_device = 0
|
||||
hdr_BPHS = [66, 80, 72, 83]
|
||||
scan_response: Union[Optional[tuple], Any] = None
|
||||
|
||||
@@ -2013,39 +1987,13 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
# print('send_scan', bytes(scan_ins))
|
||||
self._cc2650.send("bytes", bytes(scan_ins))
|
||||
|
||||
# for wait_scan_response in range(5):
|
||||
# try:
|
||||
# scan_response = self._cc2650.recv_uart(0.2)
|
||||
# except RecvTimeout:
|
||||
# if wait_scan_response == 4:
|
||||
# self.reset_internal()
|
||||
# self.reset_hardware()
|
||||
# self._interface.flush()
|
||||
# return True
|
||||
# else:
|
||||
# self.log_info("wait for scan response")
|
||||
# continue
|
||||
|
||||
# # check if response is valid
|
||||
# if scan_response is None:
|
||||
# if wait_scan_response == 4:
|
||||
# self.reset_internal()
|
||||
# self.reset_hardware()
|
||||
# self._interface.flush()
|
||||
# else:
|
||||
# self.log_info("wait for scan response")
|
||||
# continue
|
||||
# else:
|
||||
# break
|
||||
|
||||
try:
|
||||
scan_response = self._cc2650.recv_uart(0.2)
|
||||
scan_response = self._cc2650.recv_uart(timeout)
|
||||
except RecvTimeout:
|
||||
self.reset_internal()
|
||||
self.reset_hardware()
|
||||
self._interface.flush()
|
||||
return True
|
||||
|
||||
# self.reset_internal()
|
||||
# self.reset_hardware()
|
||||
# self._interface.flush()
|
||||
return False
|
||||
|
||||
# instruction format:
|
||||
# ins[0]: get_scan_response = 0x04
|
||||
@@ -2140,6 +2088,35 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
def found(self) -> List[DeviceResponseInfo]:
|
||||
return self._found
|
||||
|
||||
def check_mem_survive(self) -> Optional[CC2650Device]:
|
||||
ack = []
|
||||
ins = bytearray()
|
||||
ins.append(10)
|
||||
ins.append(1) #length
|
||||
ins.append(0xF1)
|
||||
# print('ins', list(ins))
|
||||
|
||||
try:
|
||||
self._cc2650.send("bytes", bytes(ins))
|
||||
|
||||
except SerialTimeoutException as e:
|
||||
raise RecvTimeout('device CC2650 check_mem_survive timeout') from e
|
||||
|
||||
else:
|
||||
try:
|
||||
ack = self._cc2650.recv_uart(0.001)
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_info("no memory board")
|
||||
|
||||
# else:
|
||||
# print('ack=', ack)
|
||||
|
||||
if ack == [3]:
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
@synchronized
|
||||
def connect(self, response: DeviceResponseInfo, direct_connect: bool = False) -> Optional[CC2650Device]:
|
||||
if self._handle is not None:
|
||||
@@ -2555,11 +2532,10 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
if m is None:
|
||||
m = CC2650SingleMasterCentralDevice(self._master, self._interface, self._options)
|
||||
# m.set_log_level(self._cc2650_log_level)
|
||||
self._cc2650[i] = m
|
||||
|
||||
self._interface.flush()
|
||||
self._selector.select(i)
|
||||
# self._mem_selector.select(i)
|
||||
|
||||
try:
|
||||
self.log_info('reset device', i)
|
||||
@@ -2567,10 +2543,7 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
with m:
|
||||
m.reset_internal()
|
||||
m.reset_hardware()
|
||||
|
||||
if software_reset:
|
||||
m.reset_software()
|
||||
self._cc2650[i] = m
|
||||
m.reset_software()
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_warn('reset device', i, 'fail')
|
||||
@@ -2579,83 +2552,11 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
if not software_reset:
|
||||
return
|
||||
|
||||
# check reset result
|
||||
available_device_id = list(map(lambda it: it[0],
|
||||
filter(lambda it: it[1] is not None,
|
||||
enumerate(self._cc2650))))
|
||||
|
||||
if len(available_device_id) == 0:
|
||||
raise RuntimeError("reset fail, no device found")
|
||||
|
||||
self.log_verbose('available device', ' '.join(map(str, available_device_id)))
|
||||
|
||||
# initial hardware
|
||||
for i in range(len(self._cc2650)):
|
||||
m = self._cc2650[i]
|
||||
|
||||
if m is not None:
|
||||
self._interface.flush()
|
||||
self._selector.select(i)
|
||||
# self._mem_selector.select(i)
|
||||
|
||||
try:
|
||||
self.log_info('init device', i)
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_warn('init device', i, 'fail')
|
||||
self._cc2650[i] = None
|
||||
|
||||
# check init result, again
|
||||
available_device_id = list(map(lambda it: it[0],
|
||||
filter(lambda it: it[1] is not None,
|
||||
enumerate(self._cc2650))))
|
||||
|
||||
if len(available_device_id) == 0:
|
||||
raise RuntimeError("init fail, no device success")
|
||||
|
||||
def reset_empty_master(self, device: Optional[List[int]] = None, software_reset=True):
|
||||
self.log_verbose('reset')
|
||||
|
||||
# reset hardware
|
||||
# print("reset device = ", device)
|
||||
for i in range(len(self._cc2650)):
|
||||
# print(i)
|
||||
|
||||
m = self._cc2650[i]
|
||||
d = self._device[i]
|
||||
|
||||
# print(m, d)
|
||||
|
||||
if m is not None and d is None:
|
||||
m = CC2650SingleMasterCentralDevice(self._master, self._interface, self._options)
|
||||
# m.set_log_level(self._cc2650_log_level)
|
||||
|
||||
self._interface.flush()
|
||||
self._selector.select(i)
|
||||
self._mem_selector.select(i)
|
||||
|
||||
try:
|
||||
self.log_info('reset device', i)
|
||||
|
||||
with m:
|
||||
m.reset_internal()
|
||||
m.reset_hardware()
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_warn('reset device', i, 'fail')
|
||||
self._cc2650[i] = None
|
||||
|
||||
def available_device(self) -> List[int]:
|
||||
return list(map(lambda it: it[0],
|
||||
filter(lambda it: it[1] is not None,
|
||||
enumerate(self._cc2650))))
|
||||
|
||||
def _foreach_empty_master(self) -> Iterable[int]:
|
||||
for i in range(len(self._cc2650)):
|
||||
m = self._cc2650[i]
|
||||
for i in range(len(self._device)):
|
||||
d = self._device[i]
|
||||
|
||||
if m is not None and d is None:
|
||||
if d is None:
|
||||
yield i
|
||||
|
||||
def scan_callback(self, callback: Callable[[DeviceResponseInfo], None], timeout=5, all_device=False) -> bool:
|
||||
@@ -2663,28 +2564,35 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
all_result = False
|
||||
|
||||
for device in self._foreach_empty_master():
|
||||
for device in range(len(self._cc2650)):
|
||||
self.log_verbose('use', device)
|
||||
|
||||
m = self._cc2650[device]
|
||||
d = self._device[device]
|
||||
|
||||
if m is not None and d is None:
|
||||
if d is None:
|
||||
error = None
|
||||
|
||||
with self:
|
||||
self._interface.flush()
|
||||
self._selector.select(device)
|
||||
# self._mem_selector.select(device)
|
||||
|
||||
try:
|
||||
sleep(0.0001)
|
||||
result = m.scan_callback(callback, timeout=timeout)
|
||||
if m.check_mem_survive() == False:
|
||||
continue
|
||||
|
||||
result = m.scan_callback(callback, timeout=0.001)
|
||||
|
||||
except RuntimeError as e:
|
||||
error = e
|
||||
|
||||
else:
|
||||
|
||||
if result == False:
|
||||
result = True
|
||||
all_result = all_result or result
|
||||
continue
|
||||
|
||||
all_result = all_result or result
|
||||
|
||||
if result and not all_device:
|
||||
@@ -2692,8 +2600,7 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
if error is not None:
|
||||
self.log_warn('suppressed error : ' + str(error))
|
||||
# self.reset(device)
|
||||
sleep(1)
|
||||
|
||||
return all_result
|
||||
|
||||
def found(self) -> List[DeviceResponseInfo]:
|
||||
@@ -2746,7 +2653,6 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
with self:
|
||||
self._interface.flush()
|
||||
self._selector.select(master)
|
||||
# self._mem_selector.select(device)
|
||||
|
||||
sleep(0.0001)
|
||||
d = m.connect(response, direct_connect)
|
||||
|
||||
@@ -383,9 +383,6 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
self._demo.clear()
|
||||
self._centralMaster.reset(device, software_reset)
|
||||
|
||||
def available_device(self) -> List[int]:
|
||||
return self._centralMaster.available_device()
|
||||
|
||||
@logging_info
|
||||
def shutdown(self, release_resource=True):
|
||||
# shutdown reset memeryboard
|
||||
@@ -575,6 +572,11 @@ class DeviceManager(MasterDevice, Synchronized):
|
||||
if slave.device_id == device:
|
||||
return slave
|
||||
|
||||
elif isinstance(device, str):
|
||||
for slave in self._device:
|
||||
if ':'.join('{:02x}'.format(b) for b in slave.mac_address) == device:
|
||||
return slave
|
||||
|
||||
elif isinstance(device, DeviceInfo):
|
||||
for slave in self._device:
|
||||
if device.match(slave):
|
||||
|
||||
@@ -948,12 +948,13 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
ret.append_data(3, cycle_number)
|
||||
|
||||
# memoryboard information
|
||||
ret.append_data(4, mem_wrong)
|
||||
ret.append_data(5, mem_retry_cnt)
|
||||
ret.append_data(6, mem_green_wrong)
|
||||
ret.append_data(7, mem_green_retry_cnt)
|
||||
ret.append_data(8, ram_num)
|
||||
ret.append_data(9, broken_flag)
|
||||
# ret.append_data(4, mem_wrong)
|
||||
# ret.append_data(5, mem_retry_cnt)
|
||||
# ret.append_data(6, mem_green_wrong)
|
||||
# ret.append_data(7, mem_green_retry_cnt)
|
||||
# ret.append_data(8, ram_num)
|
||||
# ret.append_data(9, broken_flag)
|
||||
# ret.append_data(4, ram_num)
|
||||
|
||||
if cycle_number != self._cycle_number:
|
||||
# notify cycle_number change
|
||||
|
||||
@@ -963,10 +963,6 @@ class MasterDevice(LoggerFlag, metaclass=abc.ABCMeta):
|
||||
"""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def available_device(self) -> List[int]:
|
||||
pass
|
||||
|
||||
def scan(self, timeout=5, all_device=False) -> List[DeviceResponseInfo]:
|
||||
"""scan the nearby device.
|
||||
|
||||
@@ -1101,9 +1097,6 @@ class NullMasterDevice(MasterDevice):
|
||||
def shutdown(self, release_resource=True):
|
||||
pass
|
||||
|
||||
def available_device(self) -> List[int]:
|
||||
return []
|
||||
|
||||
def scan(self, timeout=5, all_device=False) -> List[DeviceResponseInfo]:
|
||||
return []
|
||||
|
||||
|
||||
@@ -3720,12 +3720,9 @@ class CC2650Central(LoggerFlag):
|
||||
if ret is not None and len(ret) > 0:
|
||||
return ret
|
||||
|
||||
elif _time() - start > 1:
|
||||
elif _time() - start > 0.01: # read timeout
|
||||
return None
|
||||
|
||||
else:
|
||||
sleep(0.01)
|
||||
|
||||
def _recv_event(self, timeout: Optional[float] = 1) -> Optional[list]:
|
||||
code = self._recv_byte()
|
||||
# print("code = ", code)
|
||||
|
||||
+83
-338
@@ -16,8 +16,6 @@ MEM_REG_READ = 0x05
|
||||
DEFAULT_REGISTER_VALUE = 0b0100_0011 # 67
|
||||
MEM_SIZE = 0x1000
|
||||
|
||||
_RUNTIME_COMPILE = False
|
||||
|
||||
_SLEEP_TIME_ = 0.001
|
||||
|
||||
|
||||
@@ -25,73 +23,94 @@ _SLEEP_TIME_ = 0.001
|
||||
def zero_buffer(size: int) -> List[int]:
|
||||
return [0] * size
|
||||
|
||||
|
||||
class ExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
MEM_INS_MARKED = [MEM_INS_WRITE, 0, 2, 1, 1]
|
||||
MEM_INS_RESET = [MEM_INS_WRITE, 0, 2, 1, 1, 0, 0xFF]
|
||||
|
||||
__slots__ = ('_spi', '_tx_buffer', '_tx_buffer_header', '_tx_buffer_data',
|
||||
'pin_busy', 'pin_request', 'pin_reset', 'pin_sel',
|
||||
__slots__ = ('_selector', '_wait_for_first_data', '_spi', '_tx_buffer_header', '_tx_buffer_data',
|
||||
'pin_busy', 'pin_mem_req', 'pin_mem_sel', 'pin_ram_sel',
|
||||
'_pin_sel_val',
|
||||
'_pin_ram_sel_value', '_pin_mem_sel_value', '_pin_mem_req_value',
|
||||
'_read_green_times','_read_red_times',
|
||||
'_elite_data_len', '_mem_header_len', '_mem_tailer_len', '_single_data_len',
|
||||
'_head_wrong_cnt')
|
||||
|
||||
def __init__(self, device: Tuple[int, int] = None):
|
||||
super().__init__()
|
||||
self._spi = HardwareImplSpiInterface(device,
|
||||
spi_speed=12_000_000 # XXX temp parameter
|
||||
)
|
||||
def __init__(self,
|
||||
select: Selector,
|
||||
device: Tuple[int, int] = None):
|
||||
|
||||
self._elite_data_len = 20
|
||||
self._spi = HardwareImplSpiInterface(device,
|
||||
spi_speed=12_000_000)
|
||||
|
||||
self._elite_data_len = 120
|
||||
self._mem_header_len = 3
|
||||
self._mem_tailer_len = 8
|
||||
self._single_data_len = self._elite_data_len + self._mem_header_len + self._mem_tailer_len
|
||||
|
||||
# buffer
|
||||
self._tx_buffer = [0] * 512
|
||||
self._tx_buffer_header = [0] * 11
|
||||
self._tx_buffer_data = [0] * (self._single_data_len * 10 + 3)
|
||||
|
||||
# memory control pin
|
||||
self.pin_busy = OutputPin.get_used(P3Pin.MEM_BZY, True)
|
||||
self.pin_request = OutputPin.get_used(P3Pin.MEM_REQ, True)
|
||||
self.pin_reset = OutputPin.get_used(P3Pin.MEM_RST, True)
|
||||
self.pin_sel: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_SEL)
|
||||
self.pin_mem_req = OutputPin.get_used(P3Pin.MEM_REQ, False)
|
||||
self.pin_mem_sel = OutputPin.get_used(P3Pin.MEM_RST, True) # MEM_RST -> actually which memory board is assign
|
||||
self.pin_ram_sel: Optional[InputPin] = InputPin.get_used(P3Pin.MEM_SEL) # MEM_SEL -> actually is RAM_SEL, which RAM is assign
|
||||
|
||||
self._pin_sel_val = False
|
||||
self._pin_ram_sel_value = [bool(self.pin_ram_sel) for _ in range(Selector.SIZE)]
|
||||
self._pin_mem_sel_value = [bool(self.pin_mem_sel) for _ in range(Selector.SIZE)]
|
||||
self._pin_mem_req_value = [bool(self.pin_mem_req) for _ in range(Selector.SIZE)]
|
||||
|
||||
self._read_green_times = 0
|
||||
self._read_red_times = 0
|
||||
|
||||
self._head_wrong_cnt = [0, 0, 0, 0, 0, 0, 0, 0]
|
||||
|
||||
def reset(self):
|
||||
self._spi.reset()
|
||||
|
||||
def close(self):
|
||||
self._spi.close()
|
||||
self._selector = select
|
||||
|
||||
def flush(self):
|
||||
self.pin_reset.output(False)
|
||||
self.pin_reset.output(True)
|
||||
self._pin_sel_val = [False for _ in range(Selector.SIZE)]
|
||||
self._wait_for_first_data = [True for _ in range(Selector.SIZE)]
|
||||
|
||||
def set_pin_mem_req(self, value: bool):
|
||||
channel = self.select
|
||||
self.pin_mem_req.output(value)
|
||||
self._pin_mem_req_value[channel] = value
|
||||
|
||||
def set_pin_mem_sel(self, value: bool):
|
||||
channel = self.select
|
||||
self.pin_mem_sel.output(value)
|
||||
self._pin_mem_sel_value[channel] = value
|
||||
|
||||
def get_pin_mem_req(self):
|
||||
channel = self.select
|
||||
return self._pin_mem_req_value[channel]
|
||||
|
||||
def get_pin_ram_sel(self):
|
||||
channel = self.select
|
||||
if self.pin_ram_sel.input() == 0:
|
||||
self._pin_ram_sel_value[channel] = False
|
||||
else:
|
||||
self._pin_ram_sel_value[channel] = True
|
||||
return self._pin_ram_sel_value[channel]
|
||||
|
||||
@property
|
||||
def select(self) -> int:
|
||||
return 0
|
||||
return self._selector.channel
|
||||
|
||||
@select.setter
|
||||
def select(self, value: int):
|
||||
self._selector.select(value)
|
||||
|
||||
def reset(self):
|
||||
self._spi.reset()
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def changed(self, flip=False) -> bool:
|
||||
old = self._pin_sel_val
|
||||
value = self.pin_sel.input()
|
||||
|
||||
if flip:
|
||||
self._pin_sel_val = value
|
||||
|
||||
return value != old
|
||||
def close(self):
|
||||
self._selector.close()
|
||||
self._spi.close()
|
||||
|
||||
def send_byte(self, data: bytes):
|
||||
raise RuntimeError()
|
||||
@@ -99,25 +118,18 @@ class ExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
def recv_byte(self, size: int) -> Optional[bytes]:
|
||||
raise RuntimeError()
|
||||
|
||||
def request_data(self):
|
||||
self.pin_request.output(False)
|
||||
sleep(0.001)
|
||||
def foreach(self) -> Iterable[int]:
|
||||
for channel in self._selector.foreach():
|
||||
yield channel
|
||||
|
||||
# count = 0
|
||||
# for i in range(300):
|
||||
# count = count + 1
|
||||
def set_wait_flag(self, spi_idx:int = None, value:bool = None):
|
||||
self._wait_for_first_data[spi_idx] = value
|
||||
|
||||
self.pin_request.output(True)
|
||||
|
||||
# sleep(0.001) -> 1.2ms
|
||||
# no sleep -> 5us ~ 12us (central can't receive)
|
||||
|
||||
# for i in range
|
||||
# (1000) -> 500us ~ 1ms
|
||||
# (500) -> 200us ~ 500us
|
||||
# (300) -> 120us ~ 270us (seldom)
|
||||
# (200) -> 70us ~ 160us (skip req about every 64 time) x
|
||||
# (100) -> 40us ~ 100us (skip req sometimes) x
|
||||
def get_wait_flag(self, spi_idx:int = None) -> Optional[bool]:
|
||||
if spi_idx < Selector.SIZE:
|
||||
return self._wait_for_first_data[spi_idx]
|
||||
else:
|
||||
return None
|
||||
|
||||
def compare_green_data(self, data_first: Union[bytes, List[int]], data_second: Union[bytes, List[int]], data_third: Union[bytes, List[int]], length: int):
|
||||
data = []
|
||||
@@ -162,7 +174,6 @@ class ExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
address = 0
|
||||
|
||||
# first read to get data length
|
||||
tx = self._tx_buffer
|
||||
tx_h = self._tx_buffer_header
|
||||
|
||||
tx_h[0] = MEM_INS_READ
|
||||
@@ -178,8 +189,8 @@ class ExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
|
||||
if (data[0] != 255 or data[1] != 255 or data[2] != 255):
|
||||
self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
|
||||
if (self._head_wrong_cnt[device] < 6):
|
||||
print('data_first[0:3] != [255, 255, 255]', device)
|
||||
if (self._head_wrong_cnt[device] <= 5): # print 5 times
|
||||
print('data_first[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times')
|
||||
print(list(data[0:7]))
|
||||
|
||||
data[0:3] = [255, 255, 255]
|
||||
@@ -198,13 +209,13 @@ class ExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
# if (data_first[0] != 255 or data_first[1] != 255 or data_first[2] != 255):
|
||||
# self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
|
||||
# if (self._head_wrong_cnt[device] < 10):
|
||||
# print('data_first[0:3] != [255, 255, 255]', device)
|
||||
# print('data_first[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times')
|
||||
# print(list(data_first[0:7]))
|
||||
|
||||
# if (data_second[0] != 255 or data_second[1] != 255 or data_second[2] != 255):
|
||||
# self._head_wrong_cnt[device] = self._head_wrong_cnt[device] + 1
|
||||
# if (self._head_wrong_cnt[device] < 10):
|
||||
# print('data_second[0:3] != [255, 255, 255]', device)
|
||||
# print('data_first[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times')
|
||||
# print(list(data_second[0:7]))
|
||||
|
||||
# if (data_first[3:] == data_second[3:]):
|
||||
@@ -356,108 +367,39 @@ class ExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
|
||||
self._spi.send_byte(tx)
|
||||
|
||||
def flush_all(self):
|
||||
self.flush()
|
||||
|
||||
def foreach(self) -> Iterable[int]:
|
||||
yield 0
|
||||
|
||||
|
||||
class MultiExtMemSpiInterface(ExtMemSpiInterface):
|
||||
__slots__ = ('_selector', '_wait_for_first_data')
|
||||
|
||||
def __init__(self,
|
||||
select: Selector,
|
||||
device: Tuple[int, int] = None):
|
||||
super().__init__(device)
|
||||
|
||||
self._selector = select
|
||||
|
||||
self._pin_sel_val = [False for _ in range(Selector.SIZE)]
|
||||
self._wait_for_first_data = [True for _ in range(Selector.SIZE)]
|
||||
|
||||
@property
|
||||
def select(self) -> int:
|
||||
return self._selector.channel
|
||||
|
||||
@select.setter
|
||||
def select(self, value: int):
|
||||
self._selector.select(value)
|
||||
|
||||
def changed(self, flip=False) -> bool:
|
||||
channel = self._selector.channel
|
||||
old = self._pin_sel_val[channel]
|
||||
value = bool(self.pin_sel)
|
||||
|
||||
if flip:
|
||||
self._pin_sel_val[channel] = value
|
||||
|
||||
return value != old
|
||||
|
||||
def reset(self):
|
||||
self._spi.reset()
|
||||
|
||||
def close(self):
|
||||
self._selector.close()
|
||||
super().close()
|
||||
|
||||
def flush_all(self):
|
||||
for _ in self._selector.foreach():
|
||||
self.pin_reset.output(False)
|
||||
self.pin_reset.output(True)
|
||||
|
||||
def foreach(self) -> Iterable[int]:
|
||||
for channel in self._selector.foreach():
|
||||
yield channel
|
||||
|
||||
def set_wait_flag(self, spi_idx:int = None, value:bool = None):
|
||||
self._wait_for_first_data[spi_idx] = value
|
||||
|
||||
def get_wait_flag(self, spi_idx:int = None) -> Optional[bool]:
|
||||
if spi_idx < Selector.SIZE:
|
||||
return self._wait_for_first_data[spi_idx]
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
class ExtMemManager:
|
||||
def __init__(self, ext_mem: ExtMemSpiInterface):
|
||||
self._mem_sel = InputPin.get_used(P3Pin.MEM_SEL, pull_up_down=True)
|
||||
self._mem_req = OutputPin.get_used(P3Pin.MEM_REQ, initial=True)
|
||||
|
||||
def __init__(self, ext_mem: MultiExtMemSpiInterface):
|
||||
self._ext_mem = ext_mem
|
||||
|
||||
@property
|
||||
def mem_sel(self) -> int:
|
||||
return int(self._mem_sel)
|
||||
|
||||
@property
|
||||
def mem_req(self) -> int:
|
||||
return int(self._mem_req)
|
||||
|
||||
def mem_request(self):
|
||||
self._mem_req.pulse()
|
||||
sleep(_SLEEP_TIME_)
|
||||
|
||||
def get_ext_mem_register(self) -> List[Tuple[Optional[int], Optional[int]]]:
|
||||
ret = [(None, None) for _ in range(Selector.SIZE)]
|
||||
|
||||
for channel in self._ext_mem.foreach():
|
||||
r = [None, None]
|
||||
|
||||
self.mem_request()
|
||||
sleep(0.01)
|
||||
m1 = int(self._mem_sel)
|
||||
self._ext_mem.set_pin_mem_sel(False)
|
||||
pin_value = self._ext_mem.get_pin_mem_req()
|
||||
self._ext_mem.set_pin_mem_req(not pin_value)
|
||||
|
||||
m1 = int(self._ext_mem.get_pin_ram_sel())
|
||||
# print("m1 = ", m1)
|
||||
self._ext_mem.write_register(DEFAULT_REGISTER_VALUE)
|
||||
r[m1] = self._ext_mem.read_register()
|
||||
sleep(0.040)
|
||||
self._ext_mem.set_pin_mem_sel(True)
|
||||
sleep(0.200)
|
||||
|
||||
self.mem_request()
|
||||
sleep(0.01)
|
||||
m2 = int(self._mem_sel)
|
||||
self._ext_mem.set_pin_mem_sel(False)
|
||||
pin_value = self._ext_mem.get_pin_mem_req()
|
||||
self._ext_mem.set_pin_mem_req(not pin_value)
|
||||
|
||||
m2 = int(self._ext_mem.get_pin_ram_sel())
|
||||
# print("m2 = ", m2)
|
||||
self._ext_mem.write_register(DEFAULT_REGISTER_VALUE)
|
||||
r[m2] = self._ext_mem.read_register()
|
||||
sleep(0.040)
|
||||
self._ext_mem.set_pin_mem_sel(True)
|
||||
sleep(0.200)
|
||||
|
||||
ret[channel] = tuple(r)
|
||||
|
||||
@@ -483,33 +425,6 @@ class ExtMemManager:
|
||||
|
||||
return 0
|
||||
|
||||
def get_no_device_channel(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
||||
if result is None:
|
||||
result = self.get_ext_mem_register()
|
||||
|
||||
ret = []
|
||||
|
||||
for channel, result in enumerate(result):
|
||||
if self.is_no_device(result):
|
||||
ret.append(channel)
|
||||
|
||||
return ret
|
||||
|
||||
def get_memory_test_fail(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
||||
if result is None:
|
||||
result = self.get_ext_mem_register()
|
||||
|
||||
ret = []
|
||||
|
||||
for channel, result in enumerate(result):
|
||||
if self.is_no_device(result):
|
||||
continue
|
||||
|
||||
if self.is_memory_test_fail(result) != 0:
|
||||
ret.append(channel)
|
||||
|
||||
return ret
|
||||
|
||||
def get_available_channel(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
||||
if result is None:
|
||||
result = self.get_ext_mem_register()
|
||||
@@ -526,173 +441,3 @@ class ExtMemManager:
|
||||
ret.append(channel)
|
||||
|
||||
return ret
|
||||
|
||||
def test_available_channel(self, result: List[Tuple[Optional[int], Optional[int]]] = None) -> List[int]:
|
||||
if result is None:
|
||||
result = self.get_ext_mem_register()
|
||||
|
||||
available_channel = []
|
||||
|
||||
for channel, result in enumerate(result):
|
||||
r1, r2 = result
|
||||
|
||||
if self.is_no_device(result):
|
||||
print('channel', channel, 'no device')
|
||||
continue
|
||||
|
||||
test_pass = True
|
||||
|
||||
if r1 is None or r2 is None:
|
||||
test_pass = False
|
||||
print('channel', channel, 'mem_sel', 'x', 'not change')
|
||||
|
||||
if r1 is not None and r1 > 0 and r1 != DEFAULT_REGISTER_VALUE:
|
||||
test_pass = False
|
||||
print('channel', channel, 'mem_sel', 0, 'register', r1)
|
||||
|
||||
if r2 is not None and r2 > 0 and r2 != DEFAULT_REGISTER_VALUE:
|
||||
test_pass = False
|
||||
print('channel', channel, 'mem_sel', 1, 'register', r2)
|
||||
|
||||
if test_pass:
|
||||
print('channel', channel, 'mem_sel', 0, 'register', r1)
|
||||
print('channel', channel, 'mem_sel', 1, 'register', r2)
|
||||
available_channel.append(channel)
|
||||
|
||||
return available_channel
|
||||
|
||||
def test_memory_read_write(self, channel: int, print_result=False) -> bool:
|
||||
self._ext_mem.select = channel
|
||||
|
||||
addr = 4
|
||||
size = 100
|
||||
test_pass = True
|
||||
|
||||
while addr < MEM_SIZE:
|
||||
d1 = [randint(10, 99) for _ in range(size)]
|
||||
d2 = [randint(10, 99) for _ in range(size)]
|
||||
|
||||
self.mem_request()
|
||||
m1 = int(self._mem_sel)
|
||||
self._ext_mem.write_memory(addr, d1)
|
||||
|
||||
self.mem_request()
|
||||
m2 = int(self._mem_sel)
|
||||
self._ext_mem.write_memory(addr, d2)
|
||||
|
||||
self.mem_request()
|
||||
m11 = int(self._mem_sel)
|
||||
r1 = self._ext_mem.read_memory(addr, size)
|
||||
|
||||
if m1 != m11:
|
||||
test_pass = False
|
||||
if print_result:
|
||||
print('channel', channel, 'mem_sel not change')
|
||||
|
||||
if d1 != r1:
|
||||
test_pass = False
|
||||
if print_result:
|
||||
self.print_bytes_diff(d1, r1)
|
||||
|
||||
self.mem_request()
|
||||
m22 = int(self._mem_sel)
|
||||
r2 = self._ext_mem.read_memory(addr, size)
|
||||
|
||||
if m2 != m22:
|
||||
test_pass = False
|
||||
if print_result:
|
||||
print('channel', channel, 'mem_sel not change')
|
||||
|
||||
if d2 != r2:
|
||||
test_pass = False
|
||||
if print_result:
|
||||
self.print_bytes_diff(d2, r2)
|
||||
|
||||
addr += size
|
||||
|
||||
return test_pass
|
||||
|
||||
@staticmethod
|
||||
def print_bytes_diff(_1: List[int], _2: List[int]):
|
||||
s1 = ''
|
||||
s2 = ''
|
||||
|
||||
l1 = len(_1)
|
||||
l2 = len(_2)
|
||||
|
||||
for i in range(min(l1, l2)):
|
||||
v1 = _1[i]
|
||||
v2 = _2[i]
|
||||
|
||||
if v1 == v2:
|
||||
s1 += '%02X ' % v1
|
||||
s2 += '%02X ' % v2
|
||||
else:
|
||||
s1 += '%02X ' % v1
|
||||
s2 += pc('%02X' % v2, RED) + ' '
|
||||
|
||||
if l1 == l2:
|
||||
pass
|
||||
|
||||
elif l1 < l2:
|
||||
for i in range(l1, l2):
|
||||
s2 += pc('%02X' % _2[i], GREEN) + ' '
|
||||
else:
|
||||
for i in range(l2, l1):
|
||||
s1 += pc('%02X' % _1[i], RED) + ' '
|
||||
|
||||
print(s1)
|
||||
print(s2)
|
||||
|
||||
|
||||
def hardware_test():
|
||||
ext_mem = MultiExtMemSpiInterface(Selector.get(Selector.MEM_SELECTOR))
|
||||
|
||||
fake_mode = False
|
||||
|
||||
try:
|
||||
ext_mem.reset()
|
||||
except FileNotFoundError:
|
||||
fake_mode = True
|
||||
|
||||
ret = {
|
||||
'channel_count': Selector.SIZE,
|
||||
'memory_size': MEM_SIZE,
|
||||
'pin_mem_req': P3Pin.MEM_REQ,
|
||||
'pin_mem_sel': P3Pin.MEM_SEL,
|
||||
}
|
||||
|
||||
if not fake_mode:
|
||||
tester = ExtMemManager(ext_mem)
|
||||
|
||||
result = tester.get_ext_mem_register()
|
||||
no_device = tester.get_no_device_channel(result)
|
||||
reg_fail = tester.get_memory_test_fail(result)
|
||||
available = tester.get_available_channel(result)
|
||||
|
||||
channel = ['unknown' for _ in range(Selector.SIZE)]
|
||||
|
||||
for ch in range(len(channel)):
|
||||
if ch in no_device:
|
||||
channel[ch] = 'no_device'
|
||||
|
||||
elif ch in reg_fail:
|
||||
channel[ch] = 'reg_fail'
|
||||
|
||||
elif not tester.test_memory_read_write(ch):
|
||||
channel[ch] = 'mem_fail'
|
||||
|
||||
else:
|
||||
channel[ch] = 'available'
|
||||
|
||||
ret['register'] = result
|
||||
ret['available'] = available
|
||||
ret['channel'] = channel
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from pprint import pprint
|
||||
|
||||
pprint(hardware_test())
|
||||
|
||||
@@ -53,7 +53,7 @@ class HardwareImplSpiInterface(LowLevelHardwareInterface):
|
||||
*MISO*, *SCLK*, *GE0_N*
|
||||
"""
|
||||
|
||||
__slots__ = ('_device', '_spi', '_spi_mode', 'pin_request', '_spi_speed')
|
||||
__slots__ = ('_device', '_spi', '_spi_mode', '_spi_speed')
|
||||
|
||||
def __init__(self,
|
||||
device: Tuple[int, int] = None,
|
||||
|
||||
@@ -28,7 +28,7 @@ class UARTInterface(LowLevelHardwareInterface):
|
||||
self._serial = serial.Serial(self._port,
|
||||
baudrate=self._baudrate,
|
||||
timeout=0,
|
||||
writeTimeout=1)
|
||||
writeTimeout=0.01)
|
||||
# deprecate function name which change at version 3.0
|
||||
self._serial.flushInput()
|
||||
self._serial.flushOutput()
|
||||
|
||||
@@ -117,14 +117,14 @@ class Selector:
|
||||
self._p1.output(p[1])
|
||||
self._p2.output(p[2])
|
||||
|
||||
if (value == 4 and self._last_sel != 6):
|
||||
print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
elif (value == 5 and self._last_sel != 4):
|
||||
print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
elif (value == 7 and self._last_sel != 5):
|
||||
print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
elif (value == 6 and self._last_sel != 7):
|
||||
print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
# if (value == 4 and self._last_sel != 6):
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
# elif (value == 5 and self._last_sel != 4):
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
# elif (value == 7 and self._last_sel != 5):
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
# elif (value == 6 and self._last_sel != 7):
|
||||
# print('mem_sel is not use gray code, value:', value, ', last value:', self._last_sel)
|
||||
|
||||
self._last_sel = value
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ class RoutineConnectDeviceThread(ServerThread):
|
||||
self._current_times = 0
|
||||
self._time = time()
|
||||
|
||||
if len(self._manager._device) < len(self._manager.available_device()) and not self.check_device_status('update') and not self.check_device_status('running') and self._current_times < 3:
|
||||
if not self.check_device_status('update') and not self.check_device_status('running') and self._current_times < 3:
|
||||
self._current_times += 1
|
||||
register_device = DeviceAPI.getAll()
|
||||
if register_device is not None:
|
||||
|
||||
+54
-241
@@ -10,7 +10,7 @@ import base64
|
||||
from biopro.data import *
|
||||
from biopro.devlib.data import *
|
||||
from biopro.generator import GeneratorOptions
|
||||
from biopro.impl.ext_mem import ExtMemSpiInterface, MultiExtMemSpiInterface, ExtMemManager
|
||||
from biopro.impl.ext_mem import MultiExtMemSpiInterface, ExtMemManager
|
||||
from biopro.impl.selector import Selector
|
||||
from biopro.recording import RecordingMetaFile, RecordingFileWriter
|
||||
from biopro.util.address import EMPTY_ADDRESS, address_str
|
||||
@@ -131,9 +131,6 @@ class DataServer(SocketServer, DataAPI):
|
||||
self._available_channel.clear()
|
||||
|
||||
if self._spi is not None:
|
||||
self.log_verbose('spi flush')
|
||||
self._spi.flush_all()
|
||||
|
||||
self.reset_available_channel()
|
||||
|
||||
LEAK.reset()
|
||||
@@ -200,7 +197,7 @@ class DataServer(SocketServer, DataAPI):
|
||||
self.setup_spi(spi_mode)
|
||||
|
||||
# restart
|
||||
self.setup()
|
||||
# self.setup()
|
||||
|
||||
# data_server setup mqtt start
|
||||
if self.mqtt_thread is not None:
|
||||
@@ -224,8 +221,6 @@ class DataServer(SocketServer, DataAPI):
|
||||
return
|
||||
elif spi_mode == self.MODE_DISABLE:
|
||||
spi = None
|
||||
elif spi_mode == self.MODE_SINGLE:
|
||||
spi = ExtMemSpiInterface()
|
||||
elif spi_mode == self.MODE_SELECTOR:
|
||||
spi = MultiExtMemSpiInterface(Selector.get(Selector.MEM_SELECTOR))
|
||||
else:
|
||||
@@ -511,8 +506,6 @@ class DataServer(SocketServer, DataAPI):
|
||||
# start sync
|
||||
for runtime in r:
|
||||
if runtime is not None and not runtime.sync_started:
|
||||
# if isinstance(runtime, DeviceDataRuntime):
|
||||
# self.spi_flush(runtime.device)
|
||||
|
||||
# if client is not None:
|
||||
# client.drop_data(runtime.device)
|
||||
@@ -562,28 +555,11 @@ class DataServer(SocketServer, DataAPI):
|
||||
# self.spi_reset_ram_header(c._device)
|
||||
self._spi.set_wait_flag(c._device, True)
|
||||
|
||||
self._configurations[d] = None
|
||||
del self._configurations[d]
|
||||
self.log_info('stop_sync', c._device)
|
||||
self.mqtt_thread.broadcast_command('stop:' + str(c._device))
|
||||
# r.append(c)
|
||||
|
||||
# stop sync
|
||||
# for runtime in r:
|
||||
# if runtime is not None and runtime.sync_started:
|
||||
# self.log_info('stop_sync', runtime.device)
|
||||
# self.mqtt_thread.broadcast_command('stop:' + str(runtime.device))
|
||||
|
||||
# try:
|
||||
# runtime.shutdown()
|
||||
# except:
|
||||
# print_exception(self)
|
||||
|
||||
# # finally:
|
||||
# # # self.spi_flush(runtime.device)
|
||||
# # if _FLAG_DATA_LOST_STATS_:
|
||||
# # if isinstance(runtime, DeviceDataRuntime):
|
||||
# # runtime.log_data_receive_statistics(self)
|
||||
# # runtime.shutdown()
|
||||
|
||||
# stop runtime, none device working
|
||||
if not self.sync_started:
|
||||
@@ -663,52 +639,40 @@ class DataServer(SocketServer, DataAPI):
|
||||
client.clear()
|
||||
client.close_socket()
|
||||
|
||||
def recv_data_form_spi(self) -> bool:
|
||||
"""
|
||||
"""
|
||||
current_time = time()
|
||||
|
||||
def get_spi_obj(self):
|
||||
return self._spi
|
||||
|
||||
def whether_to_record(self, device):
|
||||
# if user click "start", return True; if user click "stop", return False;
|
||||
if device in self._configurations.keys() and self._configurations[device] is not None:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def recv_data_form_spi_new(self, device) -> bool:
|
||||
ret = False
|
||||
sync = self.get_spi_obj()
|
||||
|
||||
devicelist = self._configurations.keys()
|
||||
if sync.get_pin_mem_req() == sync.get_pin_ram_sel():
|
||||
spi_data = sync.recv_memory(device)
|
||||
signal = sync.get_pin_mem_req()
|
||||
sync.set_pin_mem_req(not signal)
|
||||
data = spi_data
|
||||
|
||||
devicelist = [4, 5, 7, 6]
|
||||
else:
|
||||
data = None
|
||||
|
||||
for c in devicelist:
|
||||
sync = self._spi
|
||||
sync.select = c
|
||||
if data is not None:
|
||||
if self._configurations[device].queue_flag:
|
||||
self._configurations[device].queue_flag = False
|
||||
print("q size= ", self._configurations[device]._queue_rec.qsize())
|
||||
|
||||
# delay 120us ~ 270us
|
||||
count = 0
|
||||
for i in range(300):
|
||||
count = count + 1
|
||||
|
||||
if c in self._configurations.keys() and self._configurations[c] is not None:
|
||||
data = self.spi_recv(c)
|
||||
if time() - current_time > 0.1:
|
||||
print('time, spi_recv', current_time, time() - current_time)
|
||||
current_time = time()
|
||||
if data is not None:
|
||||
try:
|
||||
|
||||
if self._configurations[c].queue_flag:
|
||||
self._configurations[c].queue_flag = False
|
||||
print("q size= ", self._configurations[c]._queue_rec.qsize())
|
||||
|
||||
self._configurations[c].put_rec_queue(data)
|
||||
if time() - current_time > 0.05:
|
||||
print('time, queue', current_time, time() - current_time)
|
||||
current_time = time()
|
||||
# print('done put queue')
|
||||
except:
|
||||
return
|
||||
else:
|
||||
ret = True
|
||||
# else:
|
||||
# print('****1')
|
||||
self._configurations[device].put_rec_queue(data)
|
||||
ret = True
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def rec_update(self) -> bool:
|
||||
|
||||
device_id = self._queue_db_error.get()
|
||||
@@ -722,165 +686,6 @@ class DataServer(SocketServer, DataAPI):
|
||||
|
||||
return True
|
||||
|
||||
def recv_data_foreach_runtime(self, device_id: int) -> bool:
|
||||
# """foreach data runtime to receive data. called by :class:`DataRuntimeThread`.
|
||||
|
||||
# :return: has runtime received data
|
||||
# """
|
||||
# q = None
|
||||
# data = None
|
||||
# try:
|
||||
# q = self._queue_spi_dict[device_id].get()
|
||||
# except:
|
||||
# return False
|
||||
|
||||
# ret = False
|
||||
|
||||
|
||||
# if self._queue_spi_dict[device_id].qsize() > 10:
|
||||
# print('qsize: ', device_id, self._queue_spi_dict[device_id].qsize())
|
||||
|
||||
# for c in self._configurations:
|
||||
# if self._configurations[c] is not None and self._configurations[c].sync_started:
|
||||
# if self._configurations[c]._device == device_id:
|
||||
# try:
|
||||
# data = self._configurations[c].sync_data(q)
|
||||
# except EODInterrupt:
|
||||
# self._configurations[c].sync_started = False
|
||||
# except:
|
||||
# # catch any error and ignore it
|
||||
# print_exception(self)
|
||||
# self._configurations[c].sync_started = False
|
||||
|
||||
# else:
|
||||
# if data is not None and len(data) > 0:
|
||||
# ret = True
|
||||
# # if self._configurations[c].sync_file_request:
|
||||
# # self._configurations[c].sync_file()
|
||||
# # for c in self._configurations:
|
||||
# # # print('_configurations', c)
|
||||
# # if c is not None and c.sync_started:
|
||||
# # if q[0] == c._device:
|
||||
# # try:
|
||||
# # # print('c.time', c._prev_data, c._prev_time_stamp, c._prev_delta_time)
|
||||
# # # c._timer_of_not_send = int(time())
|
||||
# # data = c.sync_data(q[1])
|
||||
|
||||
# # except EODInterrupt:
|
||||
# # c.sync_started = False
|
||||
|
||||
# # except:
|
||||
# # # catch any error and ignore it
|
||||
# # print_exception(self)
|
||||
# # c.sync_started = False
|
||||
|
||||
# # else:
|
||||
# # if data is not None and len(data) > 0:
|
||||
# # ret = True
|
||||
|
||||
# # if c.sync_file_request:
|
||||
# # c.sync_file()
|
||||
# del q
|
||||
# del data
|
||||
|
||||
return
|
||||
|
||||
def spi_flush(self, device: int):
|
||||
"""clean spi buffer"""
|
||||
|
||||
if self._spi is not None:
|
||||
self._spi.select = device
|
||||
self._spi.flush()
|
||||
return
|
||||
|
||||
def spi_reset_ram_header(self, device: int):
|
||||
if self._spi is not None:
|
||||
self._spi.select = device
|
||||
self._spi.request_data()
|
||||
sleep(0.01)
|
||||
self._spi.reset()
|
||||
self._spi.flush()
|
||||
return
|
||||
|
||||
def spi_send(self, device: int, address: int, data: bytes):
|
||||
sync = self._spi
|
||||
|
||||
if sync is None:
|
||||
return
|
||||
|
||||
sync.select = device
|
||||
sync.write_memory(address, data)
|
||||
return
|
||||
|
||||
def spi_recv(self, device: int) -> Optional[bytes]:
|
||||
sync = self._spi
|
||||
|
||||
if sync is None:
|
||||
return None
|
||||
if self._is_usb_port(device):
|
||||
# if self._is_demo_usb_port(device):
|
||||
# self._usb will be a list when suporting multi usb device
|
||||
sync = self._usb
|
||||
|
||||
if sync is None:
|
||||
return None
|
||||
|
||||
data = sync.recv_memory()
|
||||
if data is None:
|
||||
return None
|
||||
|
||||
data_length = len(data) + 1
|
||||
header = 0xFF
|
||||
data_counter = 0x00
|
||||
data_header = [header, data_counter, data_length, device]
|
||||
data_header.extend(data)
|
||||
|
||||
return bytes(data_header)
|
||||
|
||||
else:
|
||||
sync = self._spi
|
||||
|
||||
if sync is None:
|
||||
return None
|
||||
|
||||
# sync.select = device
|
||||
|
||||
# sleep(0.003)
|
||||
|
||||
if sync.changed(flip=True):
|
||||
spi_data = sync.recv_memory(device)
|
||||
|
||||
return spi_data
|
||||
# if sync.get_wait_flag(device) is False:
|
||||
# return spi_data
|
||||
# else:
|
||||
# sync.set_wait_flag(device, False)
|
||||
# print("discard first data")
|
||||
# return None
|
||||
# return sync.recv_memory()
|
||||
else:
|
||||
sync.request_data()
|
||||
|
||||
return None
|
||||
|
||||
def _is_usb_port(self, device: int) -> bool:
|
||||
max_spi_port_number = 8
|
||||
|
||||
if device >= max_spi_port_number:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
sync.select = device
|
||||
|
||||
if sync.changed(flip=True):
|
||||
# print('recv_memory~~~')
|
||||
return sync.recv_memory()
|
||||
else:
|
||||
# print('request_data___')
|
||||
return sync.request_data()
|
||||
|
||||
|
||||
class DataRuntime(metaclass=abc.ABCMeta):
|
||||
__slots__ = ('_server', '_device', '_meta_file', '_data_format',
|
||||
'_sync_started', 'sync_file_request', '_writer')
|
||||
@@ -1328,12 +1133,6 @@ class DataRuntimeThread(ServerThread):
|
||||
return True
|
||||
|
||||
def routine(self, event = None) -> None:
|
||||
# start = time()
|
||||
# ret = self._server.recv_data_foreach_runtime(self._device_id)
|
||||
# self._counter += 1
|
||||
# if self._counter > 10000:
|
||||
# gc.collect()
|
||||
# self._counter = 0
|
||||
del ret
|
||||
return
|
||||
|
||||
@@ -1346,8 +1145,9 @@ class SpiRuntimeThread(ServerThread):
|
||||
# routine period control
|
||||
self._start_time = 0.0
|
||||
self._time_stamp = 0.0
|
||||
self._interval = 0.15
|
||||
self._interval = 0.045
|
||||
self._timer = time()
|
||||
self._read_memory_board_idx = 0
|
||||
|
||||
def setup(self) -> None:
|
||||
super().setup()
|
||||
@@ -1360,27 +1160,40 @@ class SpiRuntimeThread(ServerThread):
|
||||
# self._server.close_cache_client()
|
||||
return True
|
||||
|
||||
def routine(self, event = None) -> None:
|
||||
def routine(self, event = None) -> None: # routine 50 ms
|
||||
server = self._server
|
||||
self._timer = time()
|
||||
ret = server.recv_data_form_spi()
|
||||
|
||||
sync = server.get_spi_obj()
|
||||
|
||||
# select channel
|
||||
devicelist = [4, 5, 7, 6]
|
||||
c = devicelist[self._read_memory_board_idx]
|
||||
sync.select = c
|
||||
|
||||
if server.whether_to_record(c):
|
||||
sync.set_pin_mem_sel(False)
|
||||
ret = server.recv_data_form_spi_new(c) # read ram & put data into queue, if has data, ret = true
|
||||
|
||||
self._read_memory_board_idx = 0 if self._read_memory_board_idx == 3 else self._read_memory_board_idx + 1
|
||||
|
||||
run_time = time() - self._timer
|
||||
if run_time > self._interval:
|
||||
print('time, recv_data_form_spi_routine_time', time(), run_time)
|
||||
|
||||
if run_time > 0.15:
|
||||
run_time = 0.15
|
||||
if run_time > 0.045:
|
||||
print('time, recv_data_form_spi_routine_time', time(), run_time)
|
||||
run_time = 0.045
|
||||
|
||||
if server.sync_started:
|
||||
event.wait((self._interval - run_time))
|
||||
event.wait(self._interval - run_time)
|
||||
sync.set_pin_mem_sel(True)
|
||||
sleep(0.005)
|
||||
return
|
||||
else:
|
||||
event.wait(self._interval - run_time)
|
||||
sync.set_pin_mem_sel(True)
|
||||
self.close()
|
||||
return
|
||||
|
||||
self._start_time = time()
|
||||
return
|
||||
|
||||
class RecRuntimeThread(ServerThread):
|
||||
def __init__(self, server: DataServer):
|
||||
super().__init__('RecRunTime', MAGENTA)
|
||||
|
||||
@@ -213,8 +213,8 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
self.led_thread.set_state(LED.POWER_ON)
|
||||
|
||||
# sha checking
|
||||
if _RUNTIME_COMPILE or not self._controller_options.flag_disable_sha_check:
|
||||
self.run_thread(_RandomCrashThread())
|
||||
# if _RUNTIME_COMPILE or not self._controller_options.flag_disable_sha_check:
|
||||
# self.run_thread(_RandomCrashThread())
|
||||
|
||||
# data server
|
||||
interface = self.device_manager.interface
|
||||
@@ -307,8 +307,15 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
if len(controller) == 0:
|
||||
ControllerAPI.create(hardware_info)
|
||||
elif len(controller) > 0:
|
||||
if hardware_info['mac_address'] != controller[0]['mac_address'] or hardware_info['software_version'] != controller[0]['software_version'] or hardware_info['mqtt_id'] != controller[0]['mqtt_id']:
|
||||
ControllerAPI.updateByAttrs('mac_address', hardware_info['mac_address'], {'software_version': hardware_info['software_version'], 'mqtt_id': mqtt_id })
|
||||
if hardware_info['mac_address'] != controller[0]['mac_address'] or hardware_info['software_version'] != controller[0]['software_version'] or hardware_info['mqtt_id'] != controller[0]['mqtt_id'] or hardware_info['wifi_name'] != controller[0]['wifi_name']:
|
||||
ControllerAPI.updateByAttrs (
|
||||
'mac_address', hardware_info['mac_address'], {
|
||||
'software_version': hardware_info['software_version'],
|
||||
'mqtt_id': mqtt_id,
|
||||
'name': hardware_info['name'],
|
||||
'wifi_name': hardware_info['wifi_name']
|
||||
}
|
||||
)
|
||||
|
||||
def _setup_device(self):
|
||||
# wait data server
|
||||
@@ -328,7 +335,7 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
if available_channel is None:
|
||||
self.device_manager.setup(DeviceHardwareInterface.INTERFACE_DUMMY)
|
||||
else:
|
||||
self._setup_device_manager(available_channel)
|
||||
self.broadcast_command('state:device_available')
|
||||
|
||||
except ServerShutdownException as e:
|
||||
self.interrupt(e)
|
||||
@@ -400,24 +407,6 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
self.log_verbose('available channel', available_channel)
|
||||
return available_channel
|
||||
|
||||
def _setup_device_manager(self, available_channel: List[int]):
|
||||
# device reset
|
||||
# only reset those device has channel available
|
||||
self.log_verbose('reset device')
|
||||
self.device_manager.reset(available_channel)
|
||||
|
||||
# device checking
|
||||
available_device = self.device_manager.available_device()
|
||||
|
||||
self.log_verbose('available device', available_device)
|
||||
self.broadcast_command('state:device_available')
|
||||
|
||||
if len(available_device) == 0:
|
||||
raise RuntimeError('empty device')
|
||||
|
||||
elif available_device != available_channel:
|
||||
raise RuntimeError('device/channel mismatch')
|
||||
|
||||
def _setup_restart_device_manager(self, interface: str):
|
||||
self.log_info('shutdown device manager')
|
||||
self.device_manager.shutdown()
|
||||
@@ -656,9 +645,9 @@ class ControlServer(SocketServer, ControlServerAPI, CacheAPI, CacheNotifyHandler
|
||||
if self.device_manager.scan_callback(callback, timeout=self._scan_max_timeout, all_device=True):
|
||||
self.broadcast_command(DataMessage.scan('done'))
|
||||
|
||||
if device_not_found:
|
||||
# no device found, longer the max scan time
|
||||
self._scan_max_timeout = min(10, self._scan_max_timeout + 2)
|
||||
# if device_not_found:
|
||||
# # no device found, longer the max scan time
|
||||
# self._scan_max_timeout = min(10, self._scan_max_timeout + 2)
|
||||
|
||||
@logging_info
|
||||
def hardware_device(self) -> List[DeviceResponseInfo]:
|
||||
|
||||
@@ -324,19 +324,52 @@ class RecordingProcess(Process):
|
||||
|
||||
if (save == False):
|
||||
self._wrong_cnt += 1
|
||||
print('jump cnt', self._wrong_cnt, 'times', datetime.now())
|
||||
print('jump cnt', self._wrong_cnt, 'times, device:', device, ',', datetime.now())
|
||||
|
||||
return save
|
||||
|
||||
def _check_jump_ram(self, raw_data: bytes, colum_now: int, colum_total: int, save: bool, device: int):
|
||||
i = colum_now
|
||||
|
||||
if (raw_data[i][0] == 255 and raw_data[i][3] == device):
|
||||
if (i <= colum_total - 3):
|
||||
if(raw_data[i + 1][1] - raw_data[i][1] == 1 and raw_data[i + 2][1] - raw_data[i + 1][1] == 1):
|
||||
if colum_total < 3:
|
||||
print('this ram data < 3 records, need to fix, colum_total = ', colum_total)
|
||||
if colum_total == 1:
|
||||
print('raw_data[0]', raw_data[0])
|
||||
|
||||
elif colum_total == 2:
|
||||
print('raw_data[0]', raw_data[0])
|
||||
print('raw_data[1]', raw_data[1])
|
||||
|
||||
else:
|
||||
|
||||
if((raw_data[i + 1][1] - raw_data[i][1] == 1 and raw_data[i + 2][1] - raw_data[i + 1][1] == 1) or
|
||||
(raw_data[i][1] == 255 and raw_data[i + 1][1] == 0 and raw_data[i + 2][1] == 1) or
|
||||
(raw_data[i][1] == 254 and raw_data[i + 1][1] == 255 and raw_data[i + 2][1] == 0)):
|
||||
|
||||
if ((raw_data[i][1] == 255 and raw_data[i + 1][1] == 0 and raw_data[i + 2][1] == 1) or
|
||||
(raw_data[i][1] == 254 and raw_data[i + 1][1] == 255 and raw_data[i + 2][1] == 0)):
|
||||
print('cnt = [254, 255, 0] or [255, 0, 1]')
|
||||
|
||||
save = True
|
||||
self._skip_ram_cnt += 1
|
||||
last_data_cnt = raw_data[i][1]
|
||||
if (device == 4):
|
||||
print('self._last_cnt[4]:', self._last_cnt[4], ', last_data_cnt:', last_data_cnt)
|
||||
if (device == 5):
|
||||
print('self._last_cnt[5]:', self._last_cnt[5], ', last_data_cnt:', last_data_cnt)
|
||||
if (device == 6):
|
||||
print('self._last_cnt[6]:', self._last_cnt[6], ', last_data_cnt:', last_data_cnt)
|
||||
if (device == 7):
|
||||
print('self._last_cnt[7]:', self._last_cnt[7], ', last_data_cnt:', last_data_cnt)
|
||||
|
||||
print('skip RAM, but data is right, solve data', list(raw_data[i]), 'skip Ram', self._skip_ram_cnt, 'times')
|
||||
print('data:')
|
||||
print('|', list(raw_data[0]))
|
||||
print('|', list(raw_data[1]))
|
||||
print('| ... ... ...')
|
||||
print('| ... ... ...')
|
||||
print('|', list(raw_data[colum_total-1]))
|
||||
print()
|
||||
|
||||
if (device == 4):
|
||||
@@ -465,7 +498,7 @@ class RecordingProcess(Process):
|
||||
"""
|
||||
raw_data = []
|
||||
index = 0
|
||||
elite_data_len = 20
|
||||
elite_data_len = 120
|
||||
mem_header_len = 3
|
||||
mem_tailer_len = 8
|
||||
single_data_len = elite_data_len + mem_header_len + mem_tailer_len
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
"FREQ_STOP": {
|
||||
"description": "End of Freq Scan",
|
||||
"record_meta": true,
|
||||
"initial": 1,
|
||||
"initial": 7,
|
||||
"domain": [
|
||||
"FREQ_MAX"
|
||||
],
|
||||
@@ -100,7 +100,7 @@
|
||||
"DC_BIAS": {
|
||||
"description": "DC voltage bias in mV",
|
||||
"record_meta": true,
|
||||
"initial": 0,
|
||||
"initial": 15000,
|
||||
"domain": [
|
||||
35001
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user