33import time
44from typing import Optional , Union
55
6+ from pylabrobot .io .ftdi import FTDI
7+
68from .backend import CentrifugeBackend , LoaderBackend
79from .standard import LoaderNoPlateError
810
9- try :
10- from pylibftdi import Device
11-
12- USE_FTDI = True
13- except ImportError :
14- USE_FTDI = False
15-
16-
17- logger = logging .getLogger ("pylabrobot.centrifuge.vspin" )
11+ logger = logging .getLogger (__name__ )
1812
1913
2014class Access2Backend (LoaderBackend ):
@@ -28,15 +22,15 @@ def __init__(
2822 device_id: The libftdi id for the loader. Find using
2923 `python3 -m pylibftdi.examples.list_devices`
3024 """
31- self .dev = Device ( lazy_open = True , device_id = device_id )
25+ self .io = FTDI ( device_id = device_id )
3226 self .timeout = timeout
3327
3428 async def _read (self ) -> bytes :
3529 x = b""
3630 r = None
3731 start = time .time ()
3832 while r != b"" or x == b"" :
39- r = self .dev .read (1 )
33+ r = self .io .read (1 )
4034 x += r
4135 if r == b"" :
4236 await asyncio .sleep (0.1 )
@@ -46,17 +40,16 @@ async def _read(self) -> bytes:
4640
4741 async def send_command (self , command : bytes ) -> bytes :
4842 logger .debug ("[loader] Sending %s" , command .hex ())
49- self .dev .write (command )
43+ self .io .write (command )
5044 return await self ._read ()
5145
5246 async def setup (self ):
5347 logger .debug ("[loader] setup" )
5448
55- self .dev . open ()
56- self .dev . baudrate = 115384
49+ await self .io . setup ()
50+ self .io . set_baudrate ( 115384 )
5751
5852 status = await self .get_status ()
59- print ("status" , status )
6053 if not status .startswith (bytes .fromhex ("1105" )):
6154 raise RuntimeError ("Failed to get status" )
6255
@@ -75,10 +68,10 @@ async def setup(self):
7568
7669 async def stop (self ):
7770 logger .debug ("[loader] stop" )
78- self .dev . close ()
71+ await self .io . stop ()
7972
8073 def serialize (self ):
81- return {"device_id " : self .dev . device_id , "timeout" : self .timeout }
74+ return {"io " : self .io . serialize () , "timeout" : self .timeout }
8275
8376 async def get_status (self ) -> bytes :
8477 logger .debug ("[loader] get_status" )
@@ -145,16 +138,12 @@ def __init__(self, bucket_1_position: int, device_id: Optional[str] = None):
145138 an arbitrary value, move to the bucket, and call get_position() to get the position. Then
146139 use this value for future runs.
147140 """
148- if not USE_FTDI :
149- raise RuntimeError ("pylibftdi is not installed." )
150- self .dev = Device (lazy_open = True , device_id = device_id )
141+ self .io = FTDI (device_id = device_id )
151142 self .bucket_1_position = bucket_1_position
152143 self .homing_position = 0
153- self .device_id = device_id
154144
155145 async def setup (self ):
156- self .dev .open ()
157- logger .debug ("open" )
146+ await self .io .setup ()
158147 # TODO: add functionality where if robot has been intialized before nothing needs to happen
159148 for _ in range (3 ):
160149 await self .configure_and_initialize ()
@@ -166,9 +155,9 @@ async def setup(self):
166155 await self .send (b"\xaa \x00 \x21 \x03 \xff \x23 " )
167156 await self .send (b"\xaa \xff \x1a \x14 \x2d " )
168157
169- self .dev . baudrate = 57600
170- self .dev . ftdi_fn . ftdi_setrts ( 1 )
171- self .dev . ftdi_fn . ftdi_setdtr ( 1 )
158+ self .io . set_baudrate ( 57600 )
159+ self .io . set_rts ( True )
160+ self .io . set_dtr ( True )
172161
173162 await self .send (b"\xaa \x01 \x0e \x0f " )
174163 await self .send (b"\xaa \x01 \x12 \x1f \x32 " )
@@ -264,7 +253,7 @@ async def setup(self):
264253 async def stop (self ):
265254 await self .send (b"\xaa \x02 \x0e \x10 " )
266255 await self .configure_and_initialize ()
267- self .dev . close ()
256+ await self .io . stop ()
268257
269258 async def get_status (self ):
270259 """Returns 14 bytes
@@ -296,15 +285,12 @@ async def get_position(self):
296285 async def read_resp (self , timeout = 20 ) -> bytes :
297286 """Read a response from the centrifuge. If the timeout is reached, return the data that has
298287 been read so far."""
299- if not self .dev :
300- raise RuntimeError ("Device not initialized" )
301-
302288 data = b""
303289 end_byte_found = False
304290 start_time = time .time ()
305291
306292 while True :
307- chunk = self .dev .read (25 )
293+ chunk = self .io .read (25 )
308294 if chunk :
309295 data += chunk
310296 end_byte_found = data [- 1 ] == 0x0D
@@ -320,9 +306,7 @@ async def read_resp(self, timeout=20) -> bytes:
320306 return data
321307
322308 async def send (self , cmd : Union [bytearray , bytes ], read_timeout = 0.2 ) -> bytes :
323- logger .debug ("Sending %s" , cmd .hex ())
324- written = self .dev .write (cmd .decode ("latin-1" ))
325- logger .debug ("Wrote %s bytes" , written )
309+ written = self .io .write (bytes (cmd )) # TODO: why decode? .decode("latin-1")
326310
327311 if written != len (cmd ):
328312 raise RuntimeError ("Failed to write all bytes" )
@@ -343,18 +327,17 @@ async def configure_and_initialize(self):
343327
344328 async def set_configuration_data (self ):
345329 """Set the device configuration data."""
346- self .dev . ftdi_fn . ftdi_set_latency_timer (16 )
347- self .dev . ftdi_fn . ftdi_set_line_property ( 8 , 1 , 0 )
348- self .dev . ftdi_fn . ftdi_setflowctrl (0 )
349- self .dev . baudrate = 19200
330+ self .io . set_latency_timer (16 )
331+ self .io . set_line_property ( bits = 8 , stopbits = 1 , parity = 0 )
332+ self .io . set_flowctrl (0 )
333+ self .io . set_baudrate ( 19200 )
350334
351335 async def initialize (self ):
352- if self .dev :
353- self .dev .write (b"\x00 " * 20 )
354- for i in range (33 ):
355- packet = b"\xaa " + bytes ([i & 0xFF , 0x0E , 0x0E + (i & 0xFF )]) + b"\x00 " * 8
356- self .dev .write (packet )
357- await self .send (b"\xaa \xff \x0f \x0e " )
336+ self .io .write (b"\x00 " * 20 )
337+ for i in range (33 ):
338+ packet = b"\xaa " + bytes ([i & 0xFF , 0x0E , 0x0E + (i & 0xFF )]) + b"\x00 " * 8
339+ self .io .write (packet )
340+ await self .send (b"\xaa \xff \x0f \x0e " )
358341
359342 # Centrifuge operations
360343
0 commit comments