]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/bitbangio.py
Merge pull request #400 from luxarf/fix/rockpis-pins
[Adafruit_Blinka-hackapet.git] / src / bitbangio.py
1 """
2 `bitbangio` - Bitbanged bus protocols
3 ==============================================================
4
5 See `CircuitPython:bitbangio` in CircuitPython for more details.
6
7 * Author(s): cefn
8 """
9
10 import adafruit_platformdetect.constants.boards as ap_board
11 from adafruit_blinka import Lockable, agnostic
12
13 # pylint: disable=import-outside-toplevel,too-many-arguments
14
15
16 class I2C(Lockable):
17     """Bitbang/Software I2C implementation"""
18
19     def __init__(self, scl, sda, frequency=400000):
20         # TODO: This one is a bit questionable:
21         if agnostic.board_id == ap_board.PYBOARD:
22             raise NotImplementedError("No software I2C on {}".format(agnostic.board_id))
23         if agnostic.detector.board.any_embedded_linux:
24             # TODO: Attempt to load this library automatically
25             raise NotImplementedError(
26                 "For bitbangio on Linux, please use Adafruit_CircuitPython_BitbangIO"
27             )
28         self.init(scl, sda, frequency)
29
30     def init(self, scl, sda, frequency):
31         """Initialization"""
32         from machine import Pin
33         from machine import I2C as _I2C
34
35         self.deinit()
36         id = (  # pylint: disable=redefined-builtin
37             -1
38         )  # force bitbanging implementation - in future
39         # introspect platform if SDA/SCL matches hardware I2C
40         self._i2c = _I2C(id, Pin(scl.id), Pin(sda.id), freq=frequency)
41
42     def deinit(self):
43         """Deinitialization"""
44         try:
45             del self._i2c
46         except AttributeError:
47             pass
48
49     def __enter__(self):
50         return self
51
52     def __exit__(self, exc_type, exc_value, traceback):
53         self.deinit()
54
55     def scan(self):
56         """Scan for attached devices"""
57         return self._i2c.scan()
58
59     def readfrom_into(self, address, buffer, start=0, end=None):
60         """Read from a device at specified address into a buffer"""
61         if start != 0 or end is not None:
62             if end is None:
63                 end = len(buffer)
64             buffer = memoryview(buffer)[start:end]
65         stop = True  # remove for efficiency later
66         return self._i2c.readfrom_into(address, buffer, stop)
67
68     def writeto(self, address, buffer, start=0, end=None, stop=True):
69         """Write to a device at specified address from a buffer"""
70         if start != 0 or end is not None:
71             if end is None:
72                 return self._i2c.writeto(address, memoryview(buffer)[start:], stop)
73             return self._i2c.writeto(address, memoryview(buffer)[start:end], stop)
74         return self._i2c.writeto(address, buffer, stop)
75
76
77 # TODO untested, as actually busio.SPI was on
78 # tasklist https://github.com/adafruit/Adafruit_Micropython_Blinka/issues/2 :(
79 class SPI(Lockable):
80     """Bitbang/Software SPI implementation"""
81
82     def __init__(self, clock, MOSI=None, MISO=None):
83         if agnostic.detector.board.any_embedded_linux:
84             # TODO: Attempt to load this library automatically
85             raise NotImplementedError(
86                 "For bitbangio on Linux, please use Adafruit_CircuitPython_BitbangIO"
87             )
88         from machine import SPI as _SPI
89
90         self._spi = _SPI(-1)
91         self._pins = (clock, MOSI, MISO)
92
93     def configure(self, baudrate=100000, polarity=0, phase=0, bits=8):
94         """Update the configuration"""
95         from machine import Pin
96         from machine import SPI as _SPI
97
98         if self._locked:
99             # TODO verify if _spi obj 'caches' sck, mosi, miso to
100             # avoid storing in _attributeIds (duplicated in busio)
101             # i.e. #init ignores MOSI=None rather than unsetting
102             self._spi.init(
103                 baudrate=baudrate,
104                 polarity=polarity,
105                 phase=phase,
106                 bits=bits,
107                 firstbit=_SPI.MSB,
108                 sck=Pin(self._pins[0].id),
109                 mosi=Pin(self._pins[1].id),
110                 miso=Pin(self._pins[2].id),
111             )
112         else:
113             raise RuntimeError("First call try_lock()")
114
115     def write(self, buf):
116         """Write to the SPI device"""
117         return self._spi.write(buf)
118
119     def readinto(self, buf):
120         """Read from the SPI device into a buffer"""
121         return self.readinto(buf)
122
123     def write_readinto(self, buffer_out, buffer_in):
124         """Write to the SPI device and read from the SPI device into a buffer"""
125         return self.write_readinto(buffer_out, buffer_in)