28
28
>>> print(sensor.gyro)
29
29
"""
30
30
31
- from typing import List , Union
31
+ import time
32
+ from enum import Enum
33
+ from itertools import zip_longest
34
+ from typing import List , Union , Optional
32
35
33
36
from pslab .bus .i2c import _I2CPrimitive
34
37
from pslab .bus .spi import _SPIPrimitive
38
+ from pslab .bus .uart import _UARTPrimitive
35
39
from pslab .serial_handler import SerialHandler
36
40
37
- __all__ = "I2C"
41
+ __all__ = (
42
+ "I2C" ,
43
+ "SPI" ,
44
+ "UART" ,
45
+ )
38
46
ReadableBuffer = Union [bytes , bytearray , memoryview ]
39
47
WriteableBuffer = Union [bytearray , memoryview ]
40
48
@@ -51,7 +59,7 @@ class I2C(_I2CPrimitive):
51
59
Frequency of SCL in Hz.
52
60
"""
53
61
54
- def __init__ (self , device : SerialHandler = None , frequency : int = 125e3 ):
62
+ def __init__ (self , device : SerialHandler = None , * , frequency : int = 125e3 ):
55
63
# 125 kHz is as low as the PSLab can go.
56
64
super ().__init__ (device )
57
65
self ._init ()
@@ -191,7 +199,7 @@ class SPI(_SPIPrimitive):
191
199
created.
192
200
"""
193
201
194
- def __init__ (self , device : SerialHandler = None , frequency : int = 125e3 ):
202
+ def __init__ (self , device : SerialHandler = None ):
195
203
super ().__init__ (device )
196
204
ppre , spre = self ._get_prescaler (25e4 )
197
205
self ._set_parameters (ppre , spre , 1 , 0 , 1 )
@@ -373,3 +381,207 @@ def write_readinto(
373
381
374
382
for i , v in zip (range (in_start , in_end ), data ):
375
383
buffer_in [i ] = v
384
+
385
+
386
+ class Parity (Enum ):
387
+ EVEN = 1
388
+ ODD = 2
389
+
390
+
391
+ class UART (_UARTPrimitive ):
392
+ """Busio UART Class for CircuitPython Compatibility.
393
+
394
+ Parameters
395
+ ----------
396
+ device : :class:`SerialHandler`, optional
397
+ Serial connection to PSLab device. If not provided, a new one will be
398
+ created.
399
+ baudrate : int, optional
400
+ The transmit and receive speed. Defaults to 9600.
401
+ bits : int, optional
402
+ The number of bits per byte, 8 or 9. Defaults to 8 bits.
403
+ parity : :class:`Parity`, optional
404
+ The parity used for error checking. Defaults to None.
405
+ Only 8 bits per byte supports parity.
406
+ stop : int, optional
407
+ The number of stop bits, 1 or 2. Defaults to 1.
408
+ timeout : float, optional
409
+ The timeout in seconds to wait for the first character and between
410
+ subsequent characters when reading. Defaults to 1.
411
+ """
412
+
413
+ def __init__ (
414
+ self ,
415
+ device : SerialHandler = None ,
416
+ * ,
417
+ baudrate : int = 9600 ,
418
+ bits : int = 8 ,
419
+ parity : Parity = None ,
420
+ stop : int = 1 ,
421
+ timeout : float = 1 ,
422
+ ):
423
+ super ().__init__ (device )
424
+ self ._set_uart_baud (baudrate )
425
+
426
+ if bits == 8 :
427
+ pd = 0
428
+ elif bits == 9 :
429
+ pd = 3
430
+ else :
431
+ raise ValueError ("Invalid number of bits" )
432
+
433
+ if bits == 9 and parity is not None :
434
+ raise ValueError ("Invalid parity" )
435
+ if stop not in (1 , 2 ):
436
+ raise ValueError ("Invalid number of stop bits" )
437
+
438
+ pd += parity .value
439
+
440
+ try :
441
+ self ._set_uart_mode (pd , stop - 1 )
442
+ except RuntimeError :
443
+ pass
444
+
445
+ self ._timeout = timeout
446
+
447
+ @property
448
+ def baudrate (self ):
449
+ """Get the current baudrate."""
450
+ return self ._baudrate
451
+
452
+ @property
453
+ def in_waiting (self ):
454
+ """Get the number of bytes in the input buffer, available to be read.
455
+
456
+ PSLab is limited to check, whether at least one byte in the buffer(1) or not(0).
457
+ """
458
+ return self ._read_uart_status ()
459
+
460
+ @property
461
+ def timeout (self ):
462
+ """Get the current timeout, in seconds (float)."""
463
+ return self ._timeout
464
+
465
+ def deinit (self ) -> None :
466
+ """Just a dummy method."""
467
+ pass
468
+
469
+ def __enter__ (self ):
470
+ """Just a dummy context manager."""
471
+ return self
472
+
473
+ def __exit__ (self , exc_type , exc_val , exc_tb ) -> None :
474
+ """Call :meth:`deinit` on context exit."""
475
+ self .deinit ()
476
+
477
+ def _read_with_timeout (self , nbytes : int = None , * , line = False ):
478
+ if nbytes == 0 :
479
+ return None
480
+
481
+ start_time = time .time ()
482
+ data = bytearray ()
483
+ total_read = 0
484
+
485
+ while (time .time () - start_time ) <= self ._timeout :
486
+ has_char = self ._read_uart_status ()
487
+ if has_char :
488
+ char = self ._read_byte ()
489
+ start_time = time .time ()
490
+
491
+ if line and char == 0xA :
492
+ break
493
+
494
+ data .append (char )
495
+ total_read += 1
496
+
497
+ if nbytes and total_read == nbytes :
498
+ break
499
+
500
+ time .sleep (0.01 )
501
+
502
+ return bytes (data ) if data else None
503
+
504
+ def read (self , nbytes : int = None ) -> Optional [bytes ]:
505
+ """Read characters.
506
+
507
+ If `nbytes` is specified then read at most that many bytes. Otherwise,
508
+ read everything that arrives until the connection times out.
509
+
510
+ Providing the number of bytes expected is highly recommended because
511
+ it will be faster.
512
+
513
+ Parameters
514
+ ----------
515
+ nbytes : int, optional
516
+ Number of bytes to read. Defaults to None.
517
+
518
+ Returns
519
+ -------
520
+ bytes or None
521
+ Data read.
522
+ """
523
+ return self ._read_with_timeout (nbytes )
524
+
525
+ def readinto (self , buf : WriteableBuffer ) -> int :
526
+ """Read bytes into the `buf`. Read at most `len(buf)` bytes.
527
+
528
+ Parameters
529
+ ----------
530
+ buf : bytearray or memoryview
531
+ Read data into this buffer.
532
+
533
+ Returns
534
+ -------
535
+ int
536
+ Number of bytes read and stored into `buf`.
537
+ """
538
+ nbytes = len (buf )
539
+ data = self ._read_with_timeout (nbytes )
540
+
541
+ if data is None :
542
+ return 0
543
+ else :
544
+ nbuf = len (data )
545
+
546
+ for i , c in zip (range (nbuf ), data ):
547
+ buf [i ] = c
548
+
549
+ return nbuf
550
+
551
+ def readline (self ) -> Optional [bytes ]:
552
+ """Read a line, ending in a newline character.
553
+
554
+ return None if a timeout occurs sooner, or return everything readable
555
+ if no newline is found within timeout.
556
+
557
+ Returns
558
+ -------
559
+ bytes or None
560
+ Data read.
561
+ """
562
+ return self ._read_with_timeout (None , line = True )
563
+
564
+ def write (self , buf : ReadableBuffer ) -> int :
565
+ """Write the buffer of bytes to the bus.
566
+
567
+ Parameters
568
+ ----------
569
+ buf : bytes or bytearray or memoryview
570
+ Write out the char in this buffer.
571
+
572
+ Returns
573
+ -------
574
+ int
575
+ Number of bytes written.
576
+ """
577
+ written = 0
578
+
579
+ for msb , lsb in zip_longest (buf [1 ::2 ], buf [::2 ]):
580
+ if msb is not None :
581
+ self ._write_int ((msb << 8 ) | lsb )
582
+ written += 2
583
+ else :
584
+ self ._write_byte (lsb )
585
+ written += 1
586
+
587
+ return written
0 commit comments