55except ImportError :
66 print ("Could not import module: serial" )
77
8-
98from .com_util import (
109 clTbt_dp ,
1110 clTbt_sp ,
1716import numpy as np
1817from pyftdi .ftdi import Ftdi
1918
20-
2119msg_dict = {
2220 "0x01" : "No message inside the message buffer" ,
2321 "0x02" : "Timeout: Communication-timeout (less data than expected)" ,
3129}
3230
3331from .sciopy_dataclasses import EitMeasurementSetup
32+ from sciopydev .sciopy .usb_message_parser import MessageParser , make_eitframes_hex , get_data_as_matrix
3433
3534
3635class EIT_16_32_64_128 :
@@ -51,6 +50,8 @@ def __init__(self, n_el: int) -> None:
5150 self .channel_group = self .init_channel_group ()
5251 self .print_msg = True
5352 self .ret_hex_int = None
53+ self .cMessageParser = None
54+ self .setup = None
5455
5556 def init_channel_group (self ):
5657 """
@@ -107,6 +108,7 @@ def connect_device_HS(self, url: str = "ftdi://ftdi:232h/1", baudrate: int = 900
107108 serial .STOP_BIT_1
108109 serial .set_baudrate (baudrate )
109110 self .device = serial
111+ self .cMessageParser = MessageParser (self .device , devicetype = "HS" )
110112
111113 def connect_device_FS (self , port : str , baudrate : int = 9600 , timeout : int = 1 ):
112114 """
@@ -139,6 +141,7 @@ def connect_device_FS(self, port: str, baudrate: int = 9600, timeout: int = 1):
139141 )
140142
141143 print ("Connection to" , self .device .name , "is established." )
144+ self .cMessageParser = MessageParser (self .device , devicetype = "FS" )
142145
143146 def disconnect_device (self ):
144147 """
@@ -148,86 +151,58 @@ def disconnect_device(self):
148151 """
149152 self .device .close ()
150153
151- def SystemMessageCallback_usb_fs (self ):
152- """
153- Reads data from a USB device, processes received messages, and returns the data in the specified format.
154-
155- The method continuously reads from the device until no more data is received, then processes the received bytes.
156- It converts the received data to hexadecimal format and attempts to identify a specific message index.
157- Depending on the value of `self.ret_hex_int`, it returns the data as hexadecimal, integer, or both.
158154
159- Prints diagnostic messages if `self.print_msg` is True.
155+ def send_message (self , message ):
156+ """
157+ Wrapper function to send a byte array to the device. Communication method is based on the defined serial
158+ protocol.
160159
161- Returns:
162- list[str]: List of received data in hexadecimal format if `self.ret_hex_int == "hex"`.
163- list[int]: List of received data as integers if `self.ret_hex_int == "int"`.
164- tuple: Both integer and hexadecimal lists if `self.ret_hex_int == "both"`.
165- None: If `self.ret_hex_int` is None.
160+ Args:
161+ message (bytearray): A byte array to be sent to the device.
166162 """
167- timeout_count = 0
168- received = []
169- received_hex = []
170- data_count = 0
163+ if self . serial_protocol == "HS" :
164+ self . device . write_data ( message )
165+ elif self . serial_protocol == "FS" :
166+ self . device . write ( message )
171167
172- while True :
173- buffer = self .device .read ()
174- if buffer :
175- received .extend (buffer )
176- data_count += len (buffer )
177- timeout_count = 0
178- continue
179- timeout_count += 1
180- if timeout_count >= 1 :
181- # Break if we haven't received any data
182- break
183168
184- received = "" .join (str (received )) # If you need all the data
185- received_hex = [hex (receive ) for receive in received ]
186- try :
187- msg_idx = received_hex .index ("0x18" )
188- if self .print_msg :
189- print (msg_dict [received_hex [msg_idx + 2 ]])
190- except BaseException :
191- if self .print_msg :
192- print (msg_dict ["0x01" ])
193- # self.print_msg = False
194- if self .print_msg :
195- print ("message buffer:\n " , received_hex )
196- print ("message length:\t " , data_count )
169+ def read_message (self ):
170+ """
171+ Wrapper function to read single bytes from the device. Communication method is based on the defined serial
172+ protocol.
197173
198- if self .ret_hex_int is None :
199- return
200- elif self .ret_hex_int == "hex" :
201- return received_hex
202- elif self .ret_hex_int == "int" :
203- return received
204- elif self .ret_hex_int == "both" :
205- return received , received_hex
174+ Return:
175+ A single byte read from the device.
176+ """
177+ if self .serial_protocol == "HS" :
178+ return self .device .read_data_bytes (size = 1024 , attempt = 150 )
179+ elif self .serial_protocol == "FS" :
180+ return self .device .read ()
206181
207- def SystemMessageCallback_usb_hs (self ):
182+ def SystemMessageCallback (self ):
208183 """
209- Reads data from a USB high-speed device, processes received messages, and returns the data in various formats.
184+ Handles system messages based on the selected serial protocol.
185+ Reads data from a USB device, processes received messages, and returns the data in the specified format.
210186
211- The method continuously reads data from the device until no more data is received. It converts the received bytes to hexadecimal format,
212- searches for a specific message index, and prints corresponding messages if enabled. The returned data format depends on the value of
213- `self.ret_hex_int` ("hex", "int", "both", or None).
187+ The method continuously reads from the device until no more data is received, then processes the received bytes.
188+ It converts the received data to hexadecimal format and attempts to identify a specific message index.
189+ Depending on the value of `self.ret_hex_int`, it returns the data as hexadecimal, integer, or both.
190+
191+ Prints diagnostic messages if `self.print_msg` is True.
214192
215193 Returns:
216194 list[str]: List of received data in hexadecimal format if `self.ret_hex_int == "hex"`.
217195 list[int]: List of received data as integers if `self.ret_hex_int == "int"`.
218- tuple[list[int], list[str]] : Both integer and hexadecimal lists if `self.ret_hex_int == "both"`.
196+ tuple: Both integer and hexadecimal lists if `self.ret_hex_int == "both"`.
219197 None: If `self.ret_hex_int` is None.
220-
221- Raises:
222- BaseException: If message index is not found in the received data.
223198 """
224199 timeout_count = 0
225200 received = []
226201 received_hex = []
227202 data_count = 0
228203
229204 while True :
230- buffer = self .device . read_data_bytes ( size = 1024 , attempt = 150 )
205+ buffer = self .read_message ( )
231206 if buffer :
232207 received .extend (buffer )
233208 data_count += len (buffer )
@@ -261,23 +236,6 @@ def SystemMessageCallback_usb_hs(self):
261236 elif self .ret_hex_int == "both" :
262237 return received , received_hex
263238
264- def SystemMessageCallback (self ):
265- """
266- Handles system messages based on the selected serial protocol.
267-
268- Depending on the value of `self.serial_protocol`, this method delegates
269- the handling of system messages to the appropriate callback:
270- - If `self.serial_protocol` is "HS", calls `SystemMessageCallback_usb_hs()`.
271- - If `self.serial_protocol` is "FS", calls `SystemMessageCallback_usb_fs()`.
272-
273- Raises:
274- AttributeError: If the required callback methods are not defined.
275- """
276- if self .serial_protocol == "HS" :
277- self .SystemMessageCallback_usb_hs ()
278- elif self .serial_protocol == "FS" :
279- self .SystemMessageCallback_usb_fs ()
280-
281239 def write_command_string (self , command ):
282240 """
283241 Sends a command string to the device using the appropriate serial protocol.
@@ -292,11 +250,9 @@ def write_command_string(self, command):
292250 Raises:
293251 AttributeError: If `self.device` does not have the required method for the selected protocol.
294252 """
295- if self .serial_protocol == "HS" :
296- self .device .write_data (command )
297- elif self .serial_protocol == "FS" :
298- self .device .write (command )
299- self .SystemMessageCallback ()
253+ self .cMessageParser .bPrintMessages = self .print_msg
254+ self .send_message (command )
255+ self .cMessageParser .read_usb_till_timeout (bSaveData = False , bDeleteDataFrame = True )
300256
301257 # --- sciospec device commands
302258
@@ -325,6 +281,7 @@ def update_BurstCount(self, burst_count):
325281
326282 """
327283 self .setup .burst_count = burst_count
284+ self .print_msg = True
328285 self .write_command_string (
329286 bytearray ([0xB0 , 0x03 , 0x02 , 0x00 , self .setup .burst_count , 0xB0 ])
330287 )
@@ -410,6 +367,7 @@ def SetMeasurementSetup(self, setup: EitMeasurementSetup):
410367 """
411368
412369 self .setup = setup
370+ self .cMessageParser .set_measurement_setup (self .setup )
413371 self .print_msg = False
414372 self .ResetMeasurementSetup ()
415373
@@ -523,8 +481,18 @@ def ResetMeasurementSetup(self):
523481 self .write_command_string (bytearray ([0xB0 , 0x01 , 0x01 , 0xB0 ]))
524482 self .print_msg = False
525483
526- def update_measurement_mode (self , meamode = "skip4" , boundary = "external" ):
484+
485+ def update_measurement_mode (self , meamode : str = "skip4" , boundary : str = "external" ):
486+ """
487+ Updates the measurement modes out of the options "singleended", "skip0", "skip2" or "skip4"
488+
489+ Args:
490+ meamode (str): Measurement mode "singleended", "skip0", "skip2" or "skip4"
491+ boundary (str): Return if the boundary for skip patterns is internal of a channel group or external for all
492+ optional channels
493+ """
527494 meamodeoptions = {"singleended" : 0x01 , "skip0" : 0x02 , "skip2" : 0x03 , "skip4" : 0x04 }
495+ self .print_msg = True
528496 try :
529497 cmd = meamodeoptions [meamode ]
530498 except :
@@ -534,10 +502,10 @@ def update_measurement_mode(self, meamode="skip4", boundary="external"):
534502 bnd = "0x02"
535503 else :
536504 bnd = "0x01"
537- self .write_command_string (bytearray ([0xB0 , 0x03 , 0x08 ,cmd , bnd , 0xB0 ]))
505+ self .write_command_string (bytearray ([0xB0 , 0x03 , 0x08 , cmd , bnd , 0xB0 ]))
506+ self .print_msg = False
538507 #todo read out ACK messages
539508
540-
541509 def GetMeasurementSetup (self , setup_of : str ):
542510 """
543511 Retrieves and configures the measurement setup for the device based on the specified setup option.
@@ -573,7 +541,8 @@ def GetMeasurementSetup(self, setup_of: str):
573541 print ("TBD: Translation" )
574542 self .print_msg = False
575543
576- def StartStopMeasurement (self , return_as = "pot_mat" ):
544+ #todo
545+ def StartStopMeasurementFast (self , return_as = "pot_mat" ):
577546 """
578547 Starts and stops a measurement process using the configured serial protocol (HS or FS).
579548 Sends appropriate commands to the device to initiate and terminate measurement.
@@ -589,27 +558,18 @@ def StartStopMeasurement(self, return_as="pot_mat"):
589558 Returns:
590559 list or matrix: The measurement data in the format specified by `return_as`.
591560 """
592- if self .serial_protocol == "HS" :
593- self .device .write_data (bytearray ([0xB4 , 0x01 , 0x01 , 0xB4 ]))
594- self .ret_hex_int = "hex"
595- self .print_msg = False
596-
597- data = self .SystemMessageCallback_usb_hs ()
598-
599- self .device .write_data (bytearray ([0xB4 , 0x01 , 0x00 , 0xB4 ]))
600- self .ret_hex_int = None
601- self .SystemMessageCallback ()
602-
603- elif self .serial_protocol == "FS" :
604- self .device .write (bytearray ([0xB4 , 0x01 , 0x01 , 0xB4 ]))
605- self .ret_hex_int = "hex"
606- self .print_msg = False
561+ if self .setup .burst_count == 0 :
562+ print ("Burst count for this setup needs to be >=1" )
563+ return
564+ self .send_message (bytearray ([0xB4 , 0x01 , 0x01 , 0xB4 ]))
565+ self .ret_hex_int = "hex"
566+ self .print_msg = False
607567
608- data = self .SystemMessageCallback_usb_fs ()
568+ data = self .SystemMessageCallback ()
609569
610- self .device . write (bytearray ([0xB4 , 0x01 , 0x00 , 0xB4 ]))
611- self .ret_hex_int = None
612- self .SystemMessageCallback ()
570+ self .send_message (bytearray ([0xB4 , 0x01 , 0x00 , 0xB4 ]))
571+ self .ret_hex_int = None
572+ self .SystemMessageCallback ()
613573
614574 data = del_hex_in_list (data )
615575 data = reshape_full_message_in_bursts (data , self .setup )
@@ -619,7 +579,59 @@ def StartStopMeasurement(self, return_as="pot_mat"):
619579 if return_as == "hex" :
620580 return self .data
621581 elif return_as == "pot_mat" :
622- return self .get_data_as_matrix ()
582+ return self .get_data_as_matrix (self .data )
583+
584+ #todo check
585+ def StartStopMeasurementNew (self , timeout :int = 0 , return_as = "pot_mat" , bSaveData :bool = False , bDeleteData :bool = False ,
586+ sSavepath :str = "C/" ):
587+ """
588+ Starts and stops a measurement process using the configured serial protocol (HS or FS).
589+ Sends appropriate commands to the device to initiate and terminate measurement.
590+ If a timeout is specified, data is measrued for timeout seconds (burst_count==0). Else, a burst count needs to
591+ be specified, and all measured data is received.
592+ Processes the received data by removing hexadecimal values, reshaping messages into bursts,
593+ and splitting bursts into frames. Stores the processed data in NPZ format at sSavepath
594+
595+ Args:
596+ timeout (int): Specifies the timeout in seconds.
597+ return_as (str, optional): Specifies the format of the returned data.
598+ - "hex": Returns the processed data as a list of hexadecimal values.
599+ - "pot_mat": Returns the processed data as a matrix using `get_data_as_matrix()`.
600+ Default is "pot_mat".
601+ - else: data is only stored
602+ bSaveData (bool): Specifies if a the measured data is saved in NPZ format
603+ bDeleteData (bool): Specifies if a the measured data is deleted out of memory after each EITframe, with
604+ bSaveData=True, measured data is saved and then removed from RAM
605+ sSavepath (str): Specifies the sPath where the measured data is saved.
606+
607+ Returns:
608+ list or matrix: The measurement data in the format specified by `return_as`.
609+ """
610+
611+ # Start measurement
612+ self .send_message (bytearray ([0xB4 , 0x01 , 0x01 , 0xB4 ]))
613+ self .cMessageParser .bPrintMessages = False
614+ if timeout != 0 :
615+ data = self .cMessageParser .read_usb_for_seconds (timeout , bSaveData = bSaveData , bDeleteDataFrame = bDeleteData ,
616+ sSavepath = sSavepath )
617+ else :
618+ if self .setup .burst_count == 0 :
619+ print ("Burst count for this setup needs to be >=1" )
620+ return
621+ data = self .cMessageParser .read_usb_till_timeout (bSaveData = bSaveData , bDeleteDataFrame = bDeleteData ,
622+ sSavepath = sSavepath )
623+
624+ # Stop measurement
625+ self .send_message (bytearray ([0xB4 , 0x01 , 0x00 , 0xB4 ]))
626+ data2 = self .cMessageParser .read_usb_till_timeout (bSaveData = bSaveData , bDeleteDataFrame = bDeleteData ,
627+ sSavepath = sSavepath )
628+ data = data + data2
629+ if bDeleteData :
630+ return
631+ if return_as == "hex" :
632+ return make_eitframes_hex (data )
633+ elif return_as == "pot_mat" :
634+ return get_data_as_matrix (data )
623635
624636 def get_data_as_matrix (self ):
625637 """
@@ -650,7 +662,7 @@ def get_data_as_matrix(self):
650662 row += 1
651663 el_signs = list ()
652664 for ch in range (16 ):
653- el_signs .append (frame .__dict__ [f"ch_{ ch + 1 } " ])
665+ el_signs .append (frame .__dict__ [f"ch_{ ch + 1 } " ])
654666
655667 el_signs = np .array (el_signs )
656668 start_idx = (curr_grp - 1 ) * 16
0 commit comments