]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/busio.py
Handle also CircuitPython error from missing pull capability.
[Adafruit_Blinka-hackapet.git] / src / busio.py
1 from adafruit_blinka import Enum, Lockable, agnostic
2
3 class I2C(Lockable):
4     def __init__(self, scl, sda, frequency=400000):
5         self.init(scl, sda, frequency)
6
7     def init(self, scl, sda, frequency):
8         self.deinit()
9         from machine import I2C as _I2C
10         from microcontroller.pin import i2cPorts
11         for portId, portScl, portSda in i2cPorts:
12             if scl == portScl and sda == portSda:
13                 self._i2c = I2C(portId, mode=_I2C.MASTER, baudrate=frequency)
14                 break
15         else:
16             raise NotImplementedError("No Hardware I2C on (scl,sda)={}\nValid UART ports".format(
17         (scl, sda), i2cPorts))
18
19     def deinit(self):
20         try:
21             del self._i2c
22         except AttributeError:
23             pass
24
25     def __enter__(self):
26         return self
27
28     def __exit__(self, exc_type, exc_value, traceback):
29         self.deinit()
30
31     def scan(self):
32         return self._i2c.scan()
33
34     def readfrom_into(self, address, buffer, start=0, end=None):
35         if start is not 0 or end is not None:
36             if end is None:
37                 end = len(buffer)
38             buffer = memoryview(buffer)[start:end]
39         stop = True  # remove for efficiency later
40         return self._i2c.readfrom_into(address, buffer, stop)
41
42     def writeto(self, address, buffer, start=0, end=None, stop=True):
43         if start is not 0 or end is not None:
44             if end is None:
45                 return self._i2c.writeto(address, memoryview(buffer)[start:], stop)
46             else:
47                 return self._i2c.writeto(address, memoryview(buffer)[start:end], stop)
48         return self._i2c.writeto(address, buffer, stop)
49
50
51 class SPI(Lockable):
52     def __init__(self, clock, MOSI=None, MISO=None):
53         from microcontroller.pin import spiPorts
54         for portId, portSck, portMosi, portMiso in spiPorts:
55             if clock == portSck and MOSI == portMosi and MISO == portMiso:
56                 self._spi = SPI(portId)
57                 self._pins = (portSck, portMosi, portMiso)
58                 break
59         else:
60             raise NotImplementedError(
61                 "No Hardware SPI on (clock, MOSI, MISO)={}\nValid SPI ports:{}".
62                 format((clock, MOSI, MISO), spiPorts))
63
64     def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
65         if self._locked:
66             from machine import Pin
67             # TODO check if #init ignores MOSI=None rather than unsetting, to save _pinIds attribute
68             self._spi.init(
69                 baudrate=baudrate,
70                 polarity=polarity,
71                 phase=phase,
72                 bits=bits,
73                 firstbit=SPI.MSB,
74                 sck=Pin(self._pins[0].id),
75                 mosi=Pin(self._pins[1].id),
76                 miso=Pin(self._pins[2].id)
77             )
78         else:
79             raise RuntimeError("First call try_lock()")
80
81     def deinit(self):
82         self._spi = None
83         self._pinIds = None
84
85     def write(self, buf):
86         return self._spi.write(buf)
87
88     def readinto(self, buf):
89         return self.readinto(buf)
90
91     def write_readinto(self, buffer_out, buffer_in):
92         return self.write_readinto(buffer_out, buffer_in)
93
94
95 class UART(Lockable):
96     class Parity(Enum):
97         pass
98
99     Parity.ODD = Parity()
100     Parity.EVEN = Parity()
101
102     # TODO investigate UART receiver_buffer_size as e.g. read_buf_len in https://github.com/micropython/micropython/blob/3eb0694b97c6a8f0e93b874549aac40d8b78b0e5/ports/stm32/uart.c
103     def __init__(self,
104                  tx,
105                  rx,
106                  baudrate=9600,
107                  bits=8,
108                  parity=None,
109                  stop=1,
110                  timeout=1000,
111                  receiver_buffer_size=64,
112                  flow=None):
113         from machine import UART as _UART
114         from microcontroller.pin import uartPorts
115
116         self.baudrate = baudrate
117
118         if flow is not None:  # default 0
119             raise NotImplementedError(
120                 "Parameter '{}' unsupported on {}".format(
121                     "flow", agnostic.board))
122
123         # translate parity flag for Micropython
124         if parity is UART.Parity.ODD:
125             parity = 1
126         elif parity is UART.Parity.EVEN:
127             parity = 0
128         elif parity is None:
129             pass
130         else:
131             raise ValueError("Invalid parity")
132
133         # check tx and rx have hardware support
134         for portId, portTx, portRx in uartPorts:  #
135             if portTx == tx and portRx == rx:
136                 self._uart = _UART(
137                     portId,
138                     baudrate,
139                     bits=bits,
140                     parity=parity,
141                     stop=stop,
142                     timeout=timeout,
143                     read_buf_len=receiver_buffer_size
144                 )
145                 break
146         else:
147             raise NotImplementedError(
148                 "No Hardware UART on (tx,rx)={}\nValid UART ports".format(
149                     (tx, rx), uartPorts))
150
151     def deinit(self):
152         self._uart = None
153
154     def read(self, nbytes=None):
155         return self._uart.read(nbytes)
156
157     def readinto(self, buf, nbytes=None):
158         return self._uart.readinto(buf, nbytes)
159
160     def readline(self):
161         return self._uart.readline()
162
163     def write(self, buf):
164         return self._uart.write(buf)