]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/adafruit_blinka/microcontroller/generic_linux/spi.py
Merge pull request #897 from Rippanda12/main
[Adafruit_Blinka-hackapet.git] / src / adafruit_blinka / microcontroller / generic_linux / spi.py
1 # SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
2 #
3 # SPDX-License-Identifier: MIT
4 """Generic Linux SPI class using PureIO's SPI class"""
5 from Adafruit_PureIO import spi
6 from adafruit_blinka.agnostic import detector
7
8
9 class SPI:
10     """SPI Class"""
11
12     MSB = 0
13     LSB = 1
14     CPHA = 1
15     CPOL = 2
16
17     baudrate = 100000
18     mode = 0
19     bits = 8
20
21     def __init__(self, portid):
22         if isinstance(portid, tuple):
23             self._spi = spi.SPI(device=portid)
24         else:
25             self._spi = spi.SPI(device=(portid, 0))
26         self.clock_pin = None
27         self.mosi_pin = None
28         self.miso_pin = None
29         self.chip = None
30
31     # pylint: disable=too-many-arguments,unused-argument
32     def init(
33         self,
34         baudrate=100000,
35         polarity=0,
36         phase=0,
37         bits=8,
38         firstbit=MSB,
39         sck=None,
40         mosi=None,
41         miso=None,
42     ):
43         """Initialize SPI"""
44         mode = 0
45         if polarity:
46             mode |= self.CPOL
47         if phase:
48             mode |= self.CPHA
49         self.baudrate = baudrate
50         self.mode = mode
51         self.bits = bits
52         self.chip = detector.chip
53
54         # Pins are not used
55         self.clock_pin = sck
56         self.mosi_pin = mosi
57         self.miso_pin = miso
58
59     # pylint: enable=too-many-arguments,unused-argument
60
61     # pylint: disable=unnecessary-pass
62     def set_no_cs(self):
63         """Setting so that SPI doesn't automatically set the CS pin"""
64         # No kernel seems to support this, so we're just going to pass
65         pass
66
67     # pylint: enable=unnecessary-pass
68
69     @property
70     def frequency(self):
71         """Return the current baudrate"""
72         return self.baudrate
73
74     def write(self, buf, start=0, end=None):
75         """Write data from the buffer to SPI"""
76         if buf is None or len(buf) < 1:
77             return
78         if end is None:
79             end = len(buf)
80         try:
81             # self._spi.open(self._port, 0)
82             self.set_no_cs()
83             self._spi.max_speed_hz = self.baudrate
84             self._spi.mode = self.mode
85             self._spi.bits_per_word = self.bits
86             self._spi.writebytes(buf[start:end])
87             # self._spi.close()
88         except FileNotFoundError:
89             print("Could not open SPI device - check if SPI is enabled in kernel!")
90             raise
91
92     def readinto(self, buf, start=0, end=None, write_value=0):
93         """Read data from SPI and into the buffer"""
94         if buf is None or len(buf) < 1:
95             return
96         if end is None:
97             end = len(buf)
98         try:
99             # self._spi.open(self._port, 0)
100             # self.set_no_cs()
101             self._spi.max_speed_hz = self.baudrate
102             self._spi.mode = self.mode
103             self._spi.bits_per_word = self.bits
104             data = self._spi.transfer([write_value] * (end - start))
105             for i in range(end - start):  # 'readinto' the given buffer
106                 buf[start + i] = data[i]
107             # self._spi.close()
108         except FileNotFoundError:
109             print("Could not open SPI device - check if SPI is enabled in kernel!")
110             raise
111
112     # pylint: disable=too-many-arguments
113     def write_readinto(
114         self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
115     ):
116         """Perform a half-duplex write from buffer_out and then
117         read data into buffer_in
118         """
119         if buffer_out is None or buffer_in is None:
120             return
121         if len(buffer_out) < 1 or len(buffer_in) < 1:
122             return
123         if out_end is None:
124             out_end = len(buffer_out)
125         if in_end is None:
126             in_end = len(buffer_in)
127         if out_end - out_start != in_end - in_start:
128             raise RuntimeError("Buffer slices must be of equal length.")
129         try:
130             # self._spi.open(self._port, 0)
131             # self.set_no_cs()
132             self._spi.max_speed_hz = self.baudrate
133             self._spi.mode = self.mode
134             self._spi.bits_per_word = self.bits
135             data = self._spi.transfer(list(buffer_out[out_start : out_end + 1]))
136             for i in range((in_end - in_start)):
137                 buffer_in[i + in_start] = data[i]
138             # self._spi.close()
139         except FileNotFoundError:
140             print("Could not open SPI device - check if SPI is enabled in kernel!")
141             raise
142
143     # pylint: enable=too-many-arguments