]> Repositories - Adafruit_Blinka-hackapet.git/blob - src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py
Linted new Pylint checks
[Adafruit_Blinka-hackapet.git] / src / adafruit_blinka / microcontroller / nxp_lpc4330 / spi.py
1 """SPI Class for NXP LPC4330"""
2 from greatfet import GreatFET
3
4
5 class SPI:
6     """Custom I2C Class for NXP LPC4330"""
7
8     MSB = 0
9
10     def __init__(self):
11         self._gf = GreatFET()
12         self._frequency = None
13         self.buffer_size = 255
14         self._mode = 0
15         self._spi = None
16         self._presets = {
17             204000: (100, 9),
18             408000: (100, 4),
19             680000: (100, 2),
20             1020000: (100, 1),
21             2040000: (50, 1),
22             4250000: (24, 1),
23             8500000: (12, 1),
24             12750000: (8, 1),
25             17000000: (6, 1),
26             20400000: (2, 4),
27             25500000: (4, 1),
28             34000000: (2, 2),
29             51000000: (2, 1),
30             102000000: (2, 0),
31         }
32
33     # pylint: disable=too-many-arguments,unused-argument
34     def init(
35         self,
36         baudrate=100000,
37         polarity=0,
38         phase=0,
39         bits=8,
40         firstbit=MSB,
41         sck=None,
42         mosi=None,
43         miso=None,
44     ):
45         """Initialize the Port"""
46         # Figure out the mode based on phase and polarity
47         polarity = int(polarity)
48         phase = int(phase)
49         self._mode = (polarity << 1) | phase
50
51         # Using API due to possible interface change
52         self._spi = self._gf.apis.spi
53         # Check baudrate against presets and adjust to the closest one
54         if self._frequency is None:
55             preset = self._find_closest_preset(baudrate)
56         else:
57             preset = self._presets[self._frequency]
58         clock_prescale_rate, serial_clock_rate = preset
59         self._spi.init(serial_clock_rate, clock_prescale_rate)
60
61         # Set the polarity and phase (the "SPI mode").
62         self._spi.set_clock_polarity_and_phase(self._mode)
63
64     # pylint: enable=too-many-arguments
65
66     def _find_closest_preset(self, target_frequency):
67         """Loop through self._frequencies and find the closest
68         setting. Return the preset values and set the frequency
69         to the found value
70         """
71         closest_preset = None
72         for frequency in self._presets:
73             preset = self._presets[frequency]
74             if self._frequency is None or abs(frequency - target_frequency) < abs(
75                 self._frequency - target_frequency
76             ):
77                 self._frequency = frequency
78                 closest_preset = preset
79
80         return closest_preset
81
82     @property
83     def frequency(self):
84         """Return the current frequency"""
85         return self._frequency
86
87     def write(self, buf, start=0, end=None):
88         """Write data from the buffer to SPI"""
89         end = end if end else len(buf)
90         self._transmit(buf[start:end])
91
92     # pylint: disable=unused-argument
93     def readinto(self, buf, start=0, end=None, write_value=0):
94         """Read data from SPI and into the buffer"""
95         end = end if end else len(buf)
96         result = self._transmit([], end - start)
97         for i, b in enumerate(result):
98             buf[start + i] = b
99
100     # pylint: enable=unused-argument
101
102     # pylint: disable=too-many-arguments
103     def write_readinto(
104         self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
105     ):
106         """Perform a half-duplex write from buffer_out and then
107         read data into buffer_in
108         """
109         out_end = out_end if out_end else len(buffer_out)
110         in_end = in_end if in_end else len(buffer_in)
111
112         result = self._transmit(buffer_out[out_start:out_end], in_end - in_start)
113         for i, b in enumerate(result):
114             buffer_in[in_start + i] = b
115
116     # pylint: enable=too-many-arguments
117
118     def _transmit(self, data, receive_length=None):
119         data_to_transmit = bytearray(data)
120         data_received = bytearray()
121
122         if receive_length is None:
123             receive_length = len(data)
124
125         # If we need to receive more than we've transmitted, extend the data out.
126         if receive_length > len(data):
127             padding = receive_length - len(data)
128             data_to_transmit.extend([0] * padding)
129
130         # Transmit our data in chunks of the buffer size.
131         while data_to_transmit:
132             # Extract a single data chunk from the transmit buffer.
133             chunk = data_to_transmit[0 : self.buffer_size]
134             del data_to_transmit[0 : self.buffer_size]
135
136             # Finally, exchange the data.
137             response = self._spi.clock_data(len(chunk), bytes(chunk))
138             data_received.extend(response)
139
140         # Once we're done, return the data received.
141         return bytes(data_received)