X-Git-Url: https://git.ayoreis.com/Adafruit_Blinka-hackapet.git/blobdiff_plain/f3bc592818f3a69012d99f69d3bbf30b629df012..98f4a4378478d11e514acd7ff22a9c674f3cbca3:/src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py new file mode 100644 index 0000000..37cc6c4 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py @@ -0,0 +1,137 @@ +"""SPI Class for NXP LPC4330""" +from greatfet import GreatFET + +class SPI: + """Custom I2C Class for NXP LPC4330""" + + MSB = 0 + + def __init__(self): + self._gf = GreatFET() + self._frequency = None + self.buffer_size = 255 + self._presets = { + 204000: (100, 9), + 408000: (100, 4), + 680000: (100, 2), + 1020000: (100, 1), + 2040000: (50, 1), + 4250000: (24, 1), + 8500000: (12, 1), + 12750000: (8, 1), + 17000000: (6, 1), + 20400000: (2, 4), + 25500000: (4, 1), + 34000000: (2, 2), + 51000000: (2, 1), + 102000000: (2, 0), + } + + # pylint: disable=too-many-arguments + def init( + self, + baudrate=100000, + polarity=0, + phase=0, + bits=8, + firstbit=MSB, + sck=None, + mosi=None, + miso=None, + ): + """Initialize the Port""" + # Figure out the mode based on phase and polarity + polarity = int(polarity) + phase = int(phase) + self._mode = (polarity << 1) | phase + + # Using API due to possible interface change + self._spi = self._gf.apis.spi + # Check baudrate against presets and adjust to the closest one + if self._frequency is None: + preset = self._find_closest_preset(baudrate) + else: + preset = self._presets[self._frequency] + clock_prescale_rate, serial_clock_rate = preset + self._spi.init(serial_clock_rate, clock_prescale_rate) + + # Set the polarity and phase (the "SPI mode"). + self._spi.set_clock_polarity_and_phase(self._mode) + # pylint: enable=too-many-arguments + + def _find_closest_preset(self, target_frequency): + """Loop through self._frequencies and find the closest + setting. Return the preset values and set the frequency + to the found value + """ + closest_preset = None + for frequency in self._presets: + preset = self._presets[frequency] + if self._frequency is None or abs(frequency - target_frequency) < abs(self._frequency - target_frequency): + self._frequency = frequency + closest_preset = preset + + return closest_preset + + @property + def frequency(self): + """Return the current frequency""" + return self._frequency + + def write(self, buf, start=0, end=None): + """Write data from the buffer to SPI""" + end = end if end else len(buf) + self._transmit(buf[start:end]) + + # pylint: disable=unused-argument + def readinto(self, buf, start=0, end=None, write_value=0): + """Read data from SPI and into the buffer""" + end = end if end else len(buf) + result = self._transmit([], end - start) + for i, b in enumerate(result): + buf[start + i] = b + + # pylint: enable=unused-argument + + # pylint: disable=too-many-arguments + def write_readinto( + self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None + ): + """Perform a half-duplex write from buffer_out and then + read data into buffer_in + """ + out_end = out_end if out_end else len(buffer_out) + in_end = in_end if in_end else len(buffer_in) + + result = self._transmit(buffer_out[out_start:out_end], in_end - in_start) + for i, b in enumerate(result): + buf[start + i] = b + for i, b in enumerate(result): + buffer_in[in_start + i] = b + + # pylint: enable=too-many-arguments + + def _transmit(self, data, receive_length=None): + data_to_transmit = bytearray(data) + data_received = bytearray() + + if receive_length is None: + receive_length = len(data) + + # If we need to receive more than we've transmitted, extend the data out. + if receive_length > len(data): + padding = receive_length - len(data) + data_to_transmit.extend([0] * padding) + + # Transmit our data in chunks of the buffer size. + while data_to_transmit: + # Extract a single data chunk from the transmit buffer. + chunk = data_to_transmit[0:self.buffer_size] + del data_to_transmit[0:self.buffer_size] + + # Finally, exchange the data. + response = self._spi.clock_data(len(chunk), bytes(chunk)) + data_received.extend(response) + + # Once we're done, return the data received. + return bytes(data_received)