Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ac5a6ef77a |
@@ -1,7 +0,0 @@
|
||||
.DS_Store
|
||||
*.cpython-37.opt-2.pyc
|
||||
*.pyc
|
||||
*/__pycache__
|
||||
/.vscode
|
||||
/media
|
||||
python/biopro/sever/_identify.py
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -315,6 +315,14 @@ 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,
|
||||
@@ -947,6 +955,9 @@ 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:
|
||||
@@ -1431,6 +1442,11 @@ 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]
|
||||
|
||||
@@ -1926,8 +1942,10 @@ class CC2650SingleMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
self.log_verbose('reset (hardware)')
|
||||
|
||||
pin.output(False)
|
||||
# sleep(0.001)
|
||||
sleep(0.1)
|
||||
|
||||
pin.output(True)
|
||||
sleep(0.1)
|
||||
|
||||
@synchronized
|
||||
def reset_software(self):
|
||||
@@ -1950,6 +1968,9 @@ 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:
|
||||
@@ -1965,16 +1986,21 @@ 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
|
||||
|
||||
@@ -1987,13 +2013,39 @@ 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(timeout)
|
||||
scan_response = self._cc2650.recv_uart(0.2)
|
||||
except RecvTimeout:
|
||||
# self.reset_internal()
|
||||
# self.reset_hardware()
|
||||
# self._interface.flush()
|
||||
return False
|
||||
self.reset_internal()
|
||||
self.reset_hardware()
|
||||
self._interface.flush()
|
||||
return True
|
||||
|
||||
|
||||
# instruction format:
|
||||
# ins[0]: get_scan_response = 0x04
|
||||
@@ -2088,35 +2140,6 @@ 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:
|
||||
@@ -2532,10 +2555,11 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
if m is None:
|
||||
m = CC2650SingleMasterCentralDevice(self._master, self._interface, self._options)
|
||||
self._cc2650[i] = m
|
||||
# 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)
|
||||
@@ -2543,7 +2567,10 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
with m:
|
||||
m.reset_internal()
|
||||
m.reset_hardware()
|
||||
m.reset_software()
|
||||
|
||||
if software_reset:
|
||||
m.reset_software()
|
||||
self._cc2650[i] = m
|
||||
|
||||
except RecvTimeout:
|
||||
self.log_warn('reset device', i, 'fail')
|
||||
@@ -2552,11 +2579,83 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
if not software_reset:
|
||||
return
|
||||
|
||||
def _foreach_empty_master(self) -> Iterable[int]:
|
||||
for i in range(len(self._device)):
|
||||
# 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]
|
||||
|
||||
if d is None:
|
||||
# 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]
|
||||
d = self._device[i]
|
||||
|
||||
if m is not None and d is None:
|
||||
yield i
|
||||
|
||||
def scan_callback(self, callback: Callable[[DeviceResponseInfo], None], timeout=5, all_device=False) -> bool:
|
||||
@@ -2564,35 +2663,28 @@ class CC2650MultiMasterCentralDevice(CC2650MasterDevice, Synchronized):
|
||||
|
||||
all_result = False
|
||||
|
||||
for device in range(len(self._cc2650)):
|
||||
for device in self._foreach_empty_master():
|
||||
self.log_verbose('use', device)
|
||||
|
||||
m = self._cc2650[device]
|
||||
d = self._device[device]
|
||||
|
||||
if d is None:
|
||||
if m is not None and d is None:
|
||||
error = None
|
||||
|
||||
with self:
|
||||
self._interface.flush()
|
||||
self._selector.select(device)
|
||||
# self._mem_selector.select(device)
|
||||
|
||||
try:
|
||||
if m.check_mem_survive() == False:
|
||||
continue
|
||||
|
||||
result = m.scan_callback(callback, timeout=0.001)
|
||||
sleep(0.0001)
|
||||
result = m.scan_callback(callback, timeout=timeout)
|
||||
|
||||
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:
|
||||
@@ -2600,7 +2692,8 @@ 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]:
|
||||
@@ -2653,6 +2746,7 @@ 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,6 +383,9 @@ 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
|
||||
@@ -572,11 +575,6 @@ 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):
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -889,14 +889,12 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
cycle_number = struct.unpack('>H', data[17:19])[0]
|
||||
finish_mode_falg = data[19]
|
||||
|
||||
mem_wrong_information = struct.unpack('>i', data[40:40+4])[0]
|
||||
|
||||
# print('decode', list(data[20:]))
|
||||
mem_wrong = data[40]
|
||||
mem_retry_cnt = data[41]
|
||||
mem_green_wrong = data[42]
|
||||
mem_green_retry_cnt = data[43]
|
||||
ram_num = data[44]
|
||||
mem_wrong = data[120]
|
||||
mem_retry_cnt = data[121]
|
||||
mem_green_wrong = data[122]
|
||||
mem_green_retry_cnt = data[123]
|
||||
ram_num = data[124]
|
||||
broken_flag = data[-1]
|
||||
|
||||
if (finish_mode_falg & 0b11110000 == 0b10100000):
|
||||
@@ -932,7 +930,6 @@ class I4V4Z4T4DataDecoder(RecDataDecoder):
|
||||
# '|', '{:5}'.format(mem_retry_cnt),
|
||||
# '|', '{:5}'.format(mem_green_wrong),
|
||||
# '|', '{:5}'.format(mem_green_retry_cnt),
|
||||
# '|', '{:5}'.format(mem_wrong_information),
|
||||
# '|', '{:5}'.format(ram_num),
|
||||
# '|', '{:5}'.format(broken_flag),
|
||||
# '@', str(self.device), '|')
|
||||
@@ -951,14 +948,12 @@ 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(4, ram_num)
|
||||
ret.append_data(5, broken_flag)
|
||||
ret.append_data(6, mem_wrong_information)
|
||||
# ret.append_data(4, ram_num)
|
||||
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)
|
||||
|
||||
if cycle_number != self._cycle_number:
|
||||
# notify cycle_number change
|
||||
@@ -1383,46 +1378,41 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
|
||||
index = 20
|
||||
for i in range(index, index+16, 8):
|
||||
phase_para_a.append(struct.unpack('>i', cali_coeff[i+1:i+5])[0])
|
||||
phase_para_a.append(struct.unpack('>I', cali_coeff[i+1:i+5])[0])
|
||||
phase_para_b.append(struct.unpack('>i', cali_coeff[i+5:i+9])[0])
|
||||
|
||||
index = 40
|
||||
for i in range(index, index+16, 8):
|
||||
phase_para_a.append(struct.unpack('>i', cali_coeff[i+1:i+5])[0])
|
||||
phase_para_a.append(struct.unpack('>I', cali_coeff[i+1:i+5])[0])
|
||||
phase_para_b.append(struct.unpack('>i', cali_coeff[i+5:i+9])[0])
|
||||
|
||||
#Lv[0] 160k
|
||||
index = 60
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_a.append(struct.unpack('>I', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
|
||||
#Lv[1] 20k
|
||||
index = 80
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_a.append(struct.unpack('>I', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_c.append(struct.unpack('>I', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
|
||||
#Lv[2] 5k
|
||||
index = 100
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_a.append(struct.unpack('>I', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_c.append(struct.unpack('>I', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
|
||||
#Lv[3] 200R
|
||||
index = 120
|
||||
hsrtia_a.append(struct.unpack('>i', cali_coeff[index+1:index+5])[0]/1e8)
|
||||
hsrtia_b.append(struct.unpack('>i', cali_coeff[index+5:index+9])[0]/1e8)
|
||||
hsrtia_c.append(struct.unpack('>i', cali_coeff[index+9:index+13])[0]/1e4)
|
||||
hsrtia_d.append(struct.unpack('>B', cali_coeff[index+13:index+14])[0])
|
||||
|
||||
# hsrtia_a.append(struct.unpack('>I', cali_coeff[index+1:index+5])[0])
|
||||
# hsrtia_b.append(struct.unpack('>I', cali_coeff[index+5:index+9])[0]/1e6)
|
||||
# hsrtia_c.append(struct.unpack('>I', cali_coeff[index+9:index+13])[0]/1e5)
|
||||
# hsrtia_d.append(struct.unpack('>I', cali_coeff[index+13:index+17])[0]/1e6)
|
||||
hsrtia_a.append(struct.unpack('>I', cali_coeff[index+1:index+5])[0])
|
||||
hsrtia_b.append(struct.unpack('>I', cali_coeff[index+5:index+9])[0]/1e6)
|
||||
hsrtia_c.append(struct.unpack('>I', cali_coeff[index+9:index+13])[0]/1e5)
|
||||
hsrtia_d.append(struct.unpack('>I', cali_coeff[index+13:index+17])[0]/1e6)
|
||||
|
||||
# print('cutoff_freq', cutoff_freq)
|
||||
# print('hsrtia_a', hsrtia_a)
|
||||
@@ -1502,19 +1492,13 @@ class EISZeroOneDataDecoder(RecDataDecoder):
|
||||
|
||||
voltage_mag = math.sqrt(img ** 2 + real ** 2) * (1 + freq ** 2 / cutoff_freq ** 2)
|
||||
|
||||
# if (gain == 3):
|
||||
# current = hsrtia_a[gain] * math.exp(hsrtia_b[gain] * voltage_mag) + hsrtia_c[gain] * math.exp(hsrtia_d[gain] * voltage_mag)
|
||||
# else:
|
||||
current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain] + hsrtia_c[gain]
|
||||
# print(current)
|
||||
# print(voltage_mag)
|
||||
# print(hsrtia_a[gain])
|
||||
# print(hsrtia_b[gain])
|
||||
# print(hsrtia_c[gain])
|
||||
if (gain == 3):
|
||||
current = hsrtia_a[gain] * math.exp(hsrtia_b[gain] * voltage_mag) + hsrtia_c[gain] * math.exp(hsrtia_d[gain] * voltage_mag)
|
||||
else:
|
||||
current = voltage_mag ** 2 * hsrtia_a[gain] + voltage_mag * hsrtia_b[gain] + hsrtia_c[gain]
|
||||
|
||||
if (current != 0):
|
||||
# impedance = voltage_amp * 1000_000 / 1.414213 / current
|
||||
impedance = voltage_amp * 707106.78 / current
|
||||
impedance = voltage_amp * 1000000 / current
|
||||
else:
|
||||
impedance = 0
|
||||
|
||||
|
||||
@@ -963,6 +963,10 @@ 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.
|
||||
|
||||
@@ -1097,6 +1101,9 @@ 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 []
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -3720,9 +3720,12 @@ class CC2650Central(LoggerFlag):
|
||||
if ret is not None and len(ret) > 0:
|
||||
return ret
|
||||
|
||||
elif _time() - start > 0.01: # read timeout
|
||||
elif _time() - start > 1:
|
||||
return None
|
||||
|
||||
else:
|
||||
sleep(0.01)
|
||||
|
||||
def _recv_event(self, timeout: Optional[float] = 1) -> Optional[list]:
|
||||
code = self._recv_byte()
|
||||
# print("code = ", code)
|
||||
|
||||
+341
-86
@@ -16,6 +16,8 @@ MEM_REG_READ = 0x05
|
||||
DEFAULT_REGISTER_VALUE = 0b0100_0011 # 67
|
||||
MEM_SIZE = 0x1000
|
||||
|
||||
_RUNTIME_COMPILE = False
|
||||
|
||||
_SLEEP_TIME_ = 0.001
|
||||
|
||||
|
||||
@@ -23,94 +25,73 @@ _SLEEP_TIME_ = 0.001
|
||||
def zero_buffer(size: int) -> List[int]:
|
||||
return [0] * size
|
||||
|
||||
class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
|
||||
class ExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
MEM_INS_MARKED = [MEM_INS_WRITE, 0, 2, 1, 1]
|
||||
MEM_INS_RESET = [MEM_INS_WRITE, 0, 2, 1, 1, 0, 0xFF]
|
||||
|
||||
__slots__ = ('_selector', '_wait_for_first_data', '_spi', '_tx_buffer_header', '_tx_buffer_data',
|
||||
'pin_busy', 'pin_mem_req', 'pin_mem_sel', 'pin_ram_sel',
|
||||
__slots__ = ('_spi', '_tx_buffer', '_tx_buffer_header', '_tx_buffer_data',
|
||||
'pin_busy', 'pin_request', 'pin_reset', 'pin_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,
|
||||
select: Selector,
|
||||
device: Tuple[int, int] = None):
|
||||
|
||||
def __init__(self, device: Tuple[int, int] = None):
|
||||
super().__init__()
|
||||
self._spi = HardwareImplSpiInterface(device,
|
||||
spi_speed=12_000_000)
|
||||
spi_speed=12_000_000 # XXX temp parameter
|
||||
)
|
||||
|
||||
self._elite_data_len = 40
|
||||
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_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_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_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._pin_sel_val = False
|
||||
|
||||
self._read_green_times = 0
|
||||
self._read_red_times = 0
|
||||
|
||||
self._head_wrong_cnt = [0, 0, 0, 0, 0, 0, 0, 0]
|
||||
|
||||
|
||||
self._selector = select
|
||||
|
||||
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 self._selector.channel
|
||||
|
||||
@select.setter
|
||||
def select(self, value: int):
|
||||
self._selector.select(value)
|
||||
|
||||
def reset(self):
|
||||
self._spi.reset()
|
||||
|
||||
def close(self):
|
||||
self._spi.close()
|
||||
|
||||
def flush(self):
|
||||
self.pin_reset.output(False)
|
||||
self.pin_reset.output(True)
|
||||
|
||||
@property
|
||||
def select(self) -> int:
|
||||
return 0
|
||||
|
||||
@select.setter
|
||||
def select(self, value: int):
|
||||
pass
|
||||
|
||||
def close(self):
|
||||
self._selector.close()
|
||||
self._spi.close()
|
||||
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 send_byte(self, data: bytes):
|
||||
raise RuntimeError()
|
||||
@@ -118,18 +99,25 @@ class MultiExtMemSpiInterface(LowLevelHardwareInterface):
|
||||
def recv_byte(self, size: int) -> Optional[bytes]:
|
||||
raise RuntimeError()
|
||||
|
||||
def foreach(self) -> Iterable[int]:
|
||||
for channel in self._selector.foreach():
|
||||
yield channel
|
||||
def request_data(self):
|
||||
self.pin_request.output(False)
|
||||
sleep(0.001)
|
||||
|
||||
def set_wait_flag(self, spi_idx:int = None, value:bool = None):
|
||||
self._wait_for_first_data[spi_idx] = value
|
||||
# count = 0
|
||||
# for i in range(300):
|
||||
# count = count + 1
|
||||
|
||||
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
|
||||
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 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 = []
|
||||
@@ -174,6 +162,7 @@ class MultiExtMemSpiInterface(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
|
||||
@@ -189,8 +178,8 @@ class MultiExtMemSpiInterface(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] <= 5): # print 5 times
|
||||
print('data_first[0:3] != [255, 255, 255], device:', device, ',', self._head_wrong_cnt[device], 'times')
|
||||
if (self._head_wrong_cnt[device] < 6):
|
||||
print('data_first[0:3] != [255, 255, 255]', device)
|
||||
print(list(data[0:7]))
|
||||
|
||||
data[0:3] = [255, 255, 255]
|
||||
@@ -209,13 +198,13 @@ class MultiExtMemSpiInterface(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:', device, ',', self._head_wrong_cnt[device], 'times')
|
||||
# print('data_first[0:3] != [255, 255, 255]', device)
|
||||
# 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:', device, ',', self._head_wrong_cnt[device], 'times')
|
||||
# print('data_second[0:3] != [255, 255, 255]', device)
|
||||
# print(list(data_second[0:7]))
|
||||
|
||||
# if (data_first[3:] == data_second[3:]):
|
||||
@@ -367,39 +356,108 @@ class MultiExtMemSpiInterface(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: MultiExtMemSpiInterface):
|
||||
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)
|
||||
|
||||
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._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())
|
||||
self.mem_request()
|
||||
sleep(0.01)
|
||||
m1 = int(self._mem_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._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())
|
||||
self.mem_request()
|
||||
sleep(0.01)
|
||||
m2 = int(self._mem_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)
|
||||
|
||||
@@ -425,6 +483,33 @@ 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()
|
||||
@@ -441,3 +526,173 @@ 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', '_spi_speed')
|
||||
__slots__ = ('_device', '_spi', '_spi_mode', 'pin_request', '_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=0.01)
|
||||
writeTimeout=1)
|
||||
# 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
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -64,7 +64,7 @@ class RoutineConnectDeviceThread(ServerThread):
|
||||
self._current_times = 0
|
||||
self._time = time()
|
||||
|
||||
if not self.check_device_status('update') and not self.check_device_status('running') and self._current_times < 3:
|
||||
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:
|
||||
self._current_times += 1
|
||||
register_device = DeviceAPI.getAll()
|
||||
if register_device is not None:
|
||||
|
||||
+241
-54
@@ -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 MultiExtMemSpiInterface, ExtMemManager
|
||||
from biopro.impl.ext_mem import ExtMemSpiInterface, MultiExtMemSpiInterface, ExtMemManager
|
||||
from biopro.impl.selector import Selector
|
||||
from biopro.recording import RecordingMetaFile, RecordingFileWriter
|
||||
from biopro.util.address import EMPTY_ADDRESS, address_str
|
||||
@@ -131,6 +131,9 @@ 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()
|
||||
@@ -197,7 +200,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:
|
||||
@@ -221,6 +224,8 @@ 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:
|
||||
@@ -506,6 +511,8 @@ 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)
|
||||
@@ -555,11 +562,28 @@ class DataServer(SocketServer, DataAPI):
|
||||
# self.spi_reset_ram_header(c._device)
|
||||
self._spi.set_wait_flag(c._device, True)
|
||||
|
||||
del self._configurations[d]
|
||||
self._configurations[d] = None
|
||||
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:
|
||||
@@ -639,40 +663,52 @@ 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()
|
||||
|
||||
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 = self._configurations.keys()
|
||||
|
||||
else:
|
||||
data = None
|
||||
devicelist = [4, 5, 7, 6]
|
||||
|
||||
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())
|
||||
for c in devicelist:
|
||||
sync = self._spi
|
||||
sync.select = c
|
||||
|
||||
self._configurations[device].put_rec_queue(data)
|
||||
ret = True
|
||||
# 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')
|
||||
|
||||
return ret
|
||||
|
||||
|
||||
def rec_update(self) -> bool:
|
||||
|
||||
device_id = self._queue_db_error.get()
|
||||
@@ -686,6 +722,165 @@ 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')
|
||||
@@ -1133,6 +1328,12 @@ 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
|
||||
|
||||
@@ -1145,9 +1346,8 @@ class SpiRuntimeThread(ServerThread):
|
||||
# routine period control
|
||||
self._start_time = 0.0
|
||||
self._time_stamp = 0.0
|
||||
self._interval = 0.045
|
||||
self._interval = 0.15
|
||||
self._timer = time()
|
||||
self._read_memory_board_idx = 0
|
||||
|
||||
def setup(self) -> None:
|
||||
super().setup()
|
||||
@@ -1160,40 +1360,27 @@ class SpiRuntimeThread(ServerThread):
|
||||
# self._server.close_cache_client()
|
||||
return True
|
||||
|
||||
def routine(self, event = None) -> None: # routine 50 ms
|
||||
def routine(self, event = None) -> None:
|
||||
server = self._server
|
||||
self._timer = time()
|
||||
|
||||
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
|
||||
ret = server.recv_data_form_spi()
|
||||
|
||||
run_time = time() - self._timer
|
||||
|
||||
if run_time > 0.045:
|
||||
if run_time > self._interval:
|
||||
print('time, recv_data_form_spi_routine_time', time(), run_time)
|
||||
run_time = 0.045
|
||||
|
||||
if run_time > 0.15:
|
||||
run_time = 0.15
|
||||
|
||||
if server.sync_started:
|
||||
event.wait(self._interval - run_time)
|
||||
sync.set_pin_mem_sel(True)
|
||||
sleep(0.005)
|
||||
return
|
||||
event.wait((self._interval - run_time))
|
||||
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)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user