1 # SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
 
   3 # SPDX-License-Identifier: MIT
 
   4 """SPI Class for NXP LPC4330"""
 
   5 from greatfet import GreatFET
 
   9     """Custom I2C Class for NXP LPC4330"""
 
  15         self._frequency = None
 
  16         self.buffer_size = 255
 
  36     # pylint: disable=too-many-arguments,unused-argument
 
  48         """Initialize the Port"""
 
  49         # Figure out the mode based on phase and polarity
 
  50         polarity = int(polarity)
 
  52         self._mode = (polarity << 1) | phase
 
  54         # Using API due to possible interface change
 
  55         self._spi = self._gf.apis.spi
 
  56         # Check baudrate against presets and adjust to the closest one
 
  57         if self._frequency is None:
 
  58             preset = self._find_closest_preset(baudrate)
 
  60             preset = self._presets[self._frequency]
 
  61         clock_prescale_rate, serial_clock_rate = preset
 
  62         self._spi.init(serial_clock_rate, clock_prescale_rate)
 
  64         # Set the polarity and phase (the "SPI mode").
 
  65         self._spi.set_clock_polarity_and_phase(self._mode)
 
  67     # pylint: enable=too-many-arguments
 
  69     def _find_closest_preset(self, target_frequency):
 
  70         """Loop through self._frequencies and find the closest
 
  71         setting. Return the preset values and set the frequency
 
  75         for frequency, preset in self._presets.items():
 
  76             if self._frequency is None or abs(frequency - target_frequency) < abs(
 
  77                 self._frequency - target_frequency
 
  79                 self._frequency = frequency
 
  80                 closest_preset = preset
 
  86         """Return the current frequency"""
 
  87         return self._frequency
 
  89     def write(self, buf, start=0, end=None):
 
  90         """Write data from the buffer to SPI"""
 
  91         end = end if end else len(buf)
 
  92         self._transmit(buf[start:end])
 
  94     # pylint: disable=unused-argument
 
  95     def readinto(self, buf, start=0, end=None, write_value=0):
 
  96         """Read data from SPI and into the buffer"""
 
  97         end = end if end else len(buf)
 
  98         result = self._transmit([write_value] * (end - start), end - start)
 
  99         for i, b in enumerate(result):
 
 102     # pylint: enable=unused-argument
 
 104     # pylint: disable=too-many-arguments
 
 106         self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
 
 108         """Perform a half-duplex write from buffer_out and then
 
 109         read data into buffer_in
 
 111         out_end = out_end if out_end else len(buffer_out)
 
 112         in_end = in_end if in_end else len(buffer_in)
 
 114         result = self._transmit(buffer_out[out_start:out_end], in_end - in_start)
 
 115         for i, b in enumerate(result):
 
 116             buffer_in[in_start + i] = b
 
 118     # pylint: enable=too-many-arguments
 
 120     def _transmit(self, data, receive_length=None):
 
 121         data_to_transmit = bytearray(data)
 
 122         data_received = bytearray()
 
 124         if receive_length is None:
 
 125             receive_length = len(data)
 
 127         # If we need to receive more than we've transmitted, extend the data out.
 
 128         if receive_length > len(data):
 
 129             padding = receive_length - len(data)
 
 130             data_to_transmit.extend([0] * padding)
 
 132         # Transmit our data in chunks of the buffer size.
 
 133         while data_to_transmit:
 
 134             # Extract a single data chunk from the transmit buffer.
 
 135             chunk = data_to_transmit[0 : self.buffer_size]
 
 136             del data_to_transmit[0 : self.buffer_size]
 
 138             # Finally, exchange the data.
 
 139             response = self._spi.clock_data(len(chunk), bytes(chunk))
 
 140             data_received.extend(response)
 
 142         # Once we're done, return the data received.
 
 143         return bytes(data_received)