]> Repositories - Adafruit_Blinka-hackapet.git/commitdiff
Added GreatFET One Support
authorMelissa LeBlanc-Williams <melissa@adafruit.com>
Thu, 14 May 2020 16:58:38 +0000 (09:58 -0700)
committerMelissa LeBlanc-Williams <melissa@adafruit.com>
Thu, 14 May 2020 16:58:38 +0000 (09:58 -0700)
15 files changed:
src/adafruit_blinka/board/greatfet_one.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_lpc4330/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_lpc4330/analogio.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_lpc4330/i2c.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_lpc4330/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_lpc4330/pwmout.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/nxp_lpc4330/uart.py [new file with mode: 0644]
src/analogio.py
src/board.py
src/busio.py
src/digitalio.py
src/microcontroller/__init__.py
src/microcontroller/pin.py
src/pulseio.py

diff --git a/src/adafruit_blinka/board/greatfet_one.py b/src/adafruit_blinka/board/greatfet_one.py
new file mode 100644 (file)
index 0000000..87a5173
--- /dev/null
@@ -0,0 +1,94 @@
+"""Pin definitions for the GreatFET One"""
+from adafruit_blinka.microcontroller.nxp_lpc4330 import pin
+
+J1_P3 = pin.J1_P3
+J1_P4 = pin.J1_P4
+J1_P5 = pin.J1_P5
+J1_P6 = pin.J1_P6
+J1_P7 = pin.J1_P7
+J1_P8 = pin.J1_P8
+J1_P9 = pin.J1_P9
+J1_P10 = pin.J1_P10
+J1_P12 = pin.J1_P12
+J1_P13 = pin.J1_P13
+J1_P14 = pin.J1_P14
+J1_P15 = pin.J1_P15
+J1_P16 = pin.J1_P16
+J1_P17 = pin.J1_P17
+J1_P18 = pin.J1_P18
+J1_P19 = pin.J1_P19
+J1_P20 = pin.J1_P20
+J1_P21 = pin.J1_P21
+J1_P22 = pin.J1_P22
+J1_P23 = pin.J1_P23
+J1_P24 = pin.J1_P24
+J1_P25 = pin.J1_P25
+J1_P26 = pin.J1_P26
+J1_P27 = pin.J1_P27
+J1_P28 = pin.J1_P28
+J1_P29 = pin.J1_P29
+J1_P30 = pin.J1_P30
+J1_P31 = pin.J1_P31
+J1_P32 = pin.J1_P32
+J1_P33 = pin.J1_P33
+J1_P34 = pin.J1_P34
+J1_P35 = pin.J1_P35
+J1_P37 = pin.J1_P37
+J1_P39 = pin.J1_P39
+J1_P40 = pin.J1_P40
+
+# J2 Header Pins
+J2_P3 = pin.J2_P3
+J2_P4 = pin.J2_P4
+J2_P5 = pin.J2_P5
+J2_P6 = pin.J2_P6
+J2_P7 = pin.J2_P7
+J2_P8 = pin.J2_P8
+J2_P9 = pin.J2_P9
+J2_P10 = pin.J2_P10
+J2_P13 = pin.J2_P13
+J2_P14 = pin.J2_P14
+J2_P15 = pin.J2_P15
+J2_P16 = pin.J2_P16
+J2_P18 = pin.J2_P18
+J2_P19 = pin.J2_P19
+J2_P20 = pin.J2_P20
+J2_P22 = pin.J2_P22
+J2_P23 = pin.J2_P23
+J2_P24 = pin.J2_P24
+J2_P25 = pin.J2_P25
+J2_P27 = pin.J2_P27
+J2_P28 = pin.J2_P28
+J2_P29 = pin.J2_P29
+J2_P30 = pin.J2_P30
+J2_P31 = pin.J2_P31
+J2_P33 = pin.J2_P33
+J2_P34 = pin.J2_P34
+J2_P35 = pin.J2_P35
+J2_P36 = pin.J2_P36
+J2_P37 = pin.J2_P37
+J2_P38 = pin.J2_P38
+
+# Bonus Row Pins
+J7_P2 = pin.J7_P2
+J7_P3 = pin.J7_P3
+J7_P6 = pin.J7_P6
+J7_P7 = pin.J7_P7
+J7_P8 = pin.J7_P8
+J7_P13 = pin.J7_P13
+J7_P14 = pin.J7_P14
+J7_P15 = pin.J7_P15
+J7_P16 = pin.J7_P16
+J7_P17 = pin.J7_P17
+J7_P18 = pin.J7_P18
+
+SDA = pin.SDA
+SCL = pin.SCL
+
+SCK = pin.SCK
+SCLK = SCK
+MOSI = pin.MOSI
+MISO = pin.MISO
+
+TX = pin.TX
+RX = pin.RX
diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/__init__.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/analogio.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/analogio.py
new file mode 100644 (file)
index 0000000..e45e8d2
--- /dev/null
@@ -0,0 +1,54 @@
+"""
+`analogio` - Analog input and output control
+=================================================
+See `CircuitPython:analogio` in CircuitPython for more details.
+* Author(s): Carter Nelson
+"""
+
+from adafruit_blinka.microcontroller.nxp_lpc4330.pin import Pin
+from adafruit_blinka import ContextManaged
+
+
+class AnalogIn(ContextManaged):
+    """Analog Input Class"""
+
+    def __init__(self, pin):
+        self._pin = Pin(pin.id)
+        self._pin.init(mode=Pin.ADC)
+
+    @property
+    def value(self):
+        """Read the ADC and return the value"""
+        return self._pin.value()
+
+    # pylint: disable=no-self-use
+    @value.setter
+    def value(self, value):
+        # emulate what CircuitPython does
+        raise AttributeError("'AnalogIn' object has no attribute 'value'")
+
+    # pylint: enable=no-self-use
+
+    def deinit(self):
+        del self._pin
+
+
+class AnalogOut(ContextManaged):
+    """Analog Output Class"""
+
+    def __init__(self, pin):
+        self._pin = Pin(pin.id)
+        self._pin.init(mode=Pin.DAC)
+
+    @property
+    def value(self):
+        """Return an error. This is output only."""
+        # emulate what CircuitPython does
+        raise AttributeError("unreadable attribute")
+
+    @value.setter
+    def value(self, value):
+        self._pin.value(value)
+
+    def deinit(self):
+        del self._pin
diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/i2c.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/i2c.py
new file mode 100644 (file)
index 0000000..e37fae1
--- /dev/null
@@ -0,0 +1,47 @@
+"""I2C Class for NXP LPC4330"""
+from greatfet import GreatFET
+
+
+class I2C:
+    """Custom I2C Class for NXP LPC4330"""
+
+    def __init__(self, *, frequency=100000):
+        self._gf = GreatFET()
+
+    def scan(self):
+        """Perform an I2C Device Scan"""
+        return [index for index, dev in enumerate(self._gf.i2c.scan()) if dev[0]]
+
+    # pylint: disable=unused-argument
+    def writeto(self, address, buffer, *, start=0, end=None, stop=True):
+        """Write data from the buffer to an address"""
+        if end is None:
+            end = len(buffer)
+        self._gf.i2c.write(address, buffer[start: end])
+
+    def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
+        """Read data from an address and into the buffer"""
+        if end is None:
+            end = len(buffer)
+        readin = self._gf.i2c.read(address, end - start)
+        for i in range(end - start):
+            buffer[i + start] = readin[i]
+    # pylint: enable=unused-argument
+
+    def writeto_then_readfrom(
+        self,
+        address,
+        buffer_out,
+        buffer_in,
+        *,
+        out_start=0,
+        out_end=None,
+        in_start=0,
+        in_end=None,
+        stop=False
+    ):
+        """Write data from buffer_out to an address and then
+        read data from an address and into buffer_in
+        """
+        self.writeto(address, buffer_out, start=out_start, end=out_end, stop=stop)
+        self.readfrom_into(address, buffer_in, start=in_start, end=in_end, stop=stop)
diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/pin.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/pin.py
new file mode 100644 (file)
index 0000000..a67032e
--- /dev/null
@@ -0,0 +1,204 @@
+"""NXP LPC4330 pin names"""
+try:
+    from greatfet import GreatFET
+    from greatfet.interfaces.adc import ADC
+
+    gf = GreatFET()
+except:
+    raise RuntimeError("Unable to create GreatFET object. Make sure library is installed and the device is connected.")
+
+class Pin:
+    """A basic Pin class for the NXP LPC4330 that acts as a wrapper for the GreatFET api."""
+
+    # pin modes
+    OUT = gf.gpio.DIRECTION_OUT
+    IN = gf.gpio.DIRECTION_IN
+    ADC = 2
+    DAC = 3
+
+    # pin values
+    LOW = 0
+    HIGH = 1
+
+    def __init__(self, pin_id=None):
+        self.id = pin_id
+        self._mode = None
+        self._pin = None
+
+    def init(self, mode=IN, pull=None):
+        """Initialize the Pin"""
+        if self.id is None:
+            raise RuntimeError("Can not init a None type pin.")
+        if mode in (Pin.IN, Pin.OUT):
+            if self.id not in gf.GPIO_MAPPINGS:
+                raise ValueError("Pin does not have GPIO capabilities")
+            self._pin = gf.gpio.get_pin(self.id)
+            self._pin.set_direction(mode)
+        elif mode == Pin.ADC:
+            # ADC only available on these pins
+            if self.id not in gf.ADC_MAPPINGS:
+                raise ValueError("Pin does not have ADC capabilities")
+            gf.ADC_MAPPINGS[self.id]
+            # TODO: figure out a way to pass the ADC number without breaking the interface
+            self._pin = ADC(gf, self.id)
+        elif mode == Pin.DAC:
+            # DAC only available on these pins
+            if self.id not in ("J2_P5"):
+                raise ValueError("Pin does not have DAC capabilities")
+            self._pin = gf.apis.dac
+            self._pin.initialize()
+        else:
+            raise ValueError("Incorrect pin mode: {}".format(mode))
+        self._mode = mode
+
+    def value(self, val=None):
+        """Set or return the Pin Value"""
+        # Digital In / Out
+        if self._mode in (Pin.IN, Pin.OUT):
+            # digital read
+            if val is None:
+                return self._pin.get_state()
+            # digital write
+            if val in (Pin.LOW, Pin.HIGH):
+                self._pin.set_state(val)
+                return None
+            # nope
+            raise ValueError("Invalid value for pin.")
+        # Analog In
+        if self._mode == Pin.ADC:
+            if val is None:
+                # Read ADC here
+                return self._pin.read_samples()[0]
+            # read only
+            raise AttributeError("'AnalogIn' object has no attribute 'value'")
+        # Analog Out
+        if self._mode == Pin.DAC:
+            if val is None:
+                # write only
+                raise AttributeError("unreadable attribute")
+            # Set DAC Here
+            self._pin.set_value(int(val))
+            return None
+        raise RuntimeError(
+            "No action for mode {} with value {}".format(self._mode, val)
+        )
+
+# create pin instances for each pin
+# J1 Header Pins
+J1_P3 = Pin("J1_P3")
+J1_P4 = Pin("J1_P4")
+J1_P5 = Pin("J1_P5")
+J1_P6 = Pin("J1_P6")
+J1_P7 = Pin("J1_P7")
+J1_P8 = Pin("J1_P8")
+J1_P9 = Pin("J1_P9")
+J1_P10 = Pin("J1_P10")
+J1_P12 = Pin("J1_P12")
+J1_P13 = Pin("J1_P13")
+J1_P14 = Pin("J1_P14")
+J1_P15 = Pin("J1_P15")
+J1_P16 = Pin("J1_P16")
+J1_P17 = Pin("J1_P17")
+J1_P18 = Pin("J1_P18")
+J1_P19 = Pin("J1_P19")
+J1_P20 = Pin("J1_P20")
+J1_P21 = Pin("J1_P21")
+J1_P22 = Pin("J1_P22")
+J1_P23 = Pin("J1_P23")
+J1_P24 = Pin("J1_P24")
+J1_P25 = Pin("J1_P25")
+J1_P26 = Pin("J1_P26")
+J1_P27 = Pin("J1_P27")
+J1_P28 = Pin("J1_P28")
+J1_P29 = Pin("J1_P29")
+J1_P30 = Pin("J1_P30")
+J1_P31 = Pin("J1_P31")
+J1_P32 = Pin("J1_P32")
+J1_P33 = Pin("J1_P33")
+J1_P34 = Pin("J1_P34")
+J1_P35 = Pin("J1_P35")
+J1_P37 = Pin("J1_P37")
+J1_P39 = Pin("J1_P39")  # MOSI
+J1_P40 = Pin("J1_P40")  # MISO
+
+
+
+# J2 Header Pins
+J2_P3 = Pin("J2_P3")
+J2_P4 = Pin("J2_P4")
+J2_P5 = Pin("J2_P5")    # ADC, ADC, DAC
+J2_P6 = Pin("J2_P6")
+J2_P7 = Pin("J2_P7")
+J2_P8 = Pin("J2_P8")
+J2_P9 = Pin("J2_P9")    # ADC, GPIO
+J2_P10 = Pin("J2_P10")
+J2_P13 = Pin("J2_P13")
+J2_P14 = Pin("J2_P14")
+J2_P15 = Pin("J2_P15")
+J2_P16 = Pin("J2_P16")  # GPIO, ADC
+J2_P18 = Pin("J2_P18")
+J2_P19 = Pin("J2_P19")
+J2_P20 = Pin("J2_P20")
+J2_P22 = Pin("J2_P22")
+J2_P23 = Pin("J2_P23")
+J2_P24 = Pin("J2_P24")
+J2_P25 = Pin("J2_P25")
+J2_P27 = Pin("J2_P27")
+J2_P28 = Pin("J2_P28")
+J2_P29 = Pin("J2_P29")
+J2_P30 = Pin("J2_P30")
+J2_P31 = Pin("J2_P31")
+J2_P33 = Pin("J2_P33")
+J2_P34 = Pin("J2_P34")
+J2_P35 = Pin("J2_P35")
+J2_P36 = Pin("J2_P36")
+J2_P37 = Pin("J2_P37")
+J2_P38 = Pin("J2_P38")
+
+# Bonus Row Pins
+J7_P2 = Pin("J7_P2")
+J7_P3 = Pin("J7_P3")
+J7_P4 = Pin("J7_P4")    # ADC, ADC
+J7_P5 = Pin("J7_P5")    # ADC, ADC
+J7_P6 = Pin("J7_P6")
+J7_P7 = Pin("J7_P7")
+J7_P8 = Pin("J7_P8")
+J7_P13 = Pin("J7_P13")
+J7_P14 = Pin("J7_P14")
+J7_P15 = Pin("J7_P15")
+J7_P16 = Pin("J7_P16")
+J7_P17 = Pin("J7_P17")
+J7_P18 = Pin("J7_P18")
+
+SCL = Pin()
+SDA = Pin()
+
+SCK = Pin()
+MOSI = J1_P39
+MISO = J1_P40
+
+TX = J1_P33
+RX = J1_P34
+
+# ordered as uartId, txId, rxId
+uartPorts = ((0, TX, RX),)
+
+# pwm outputs: pwm channel and pin
+pwmOuts = (
+    (0, J1_P4),
+    (1, J1_P6),
+    (2, J1_P28),
+    (3, J1_P30),
+    (4, J2_P36),
+    (5, J2_P34),
+    (6, J2_P33),
+    (7, J1_P34),
+    (8, J2_P9),
+    (9, J1_P6),
+    (10, J1_P25),
+    (11, J1_P32),
+    (12, J1_P31),
+    (13, J2_P3),
+    (14, J1_P3),
+    (15, J1_P5),
+)
diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/pwmout.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/pwmout.py
new file mode 100644 (file)
index 0000000..08a31b7
--- /dev/null
@@ -0,0 +1,209 @@
+"""PWMOut Class for NXP LPC4330"""
+
+from greatfet import GreatFET
+from greatfet.interfaces.pattern_generator import PatternGenerator
+
+try:
+    from microcontroller.pin import pwmOuts
+except ImportError:
+    raise RuntimeError("No PWM outputs defined for this board")
+
+from microcontroller.pin import Pin
+
+
+# pylint: disable=unnecessary-pass
+class PWMError(IOError):
+    """Base class for PWM errors."""
+    pass
+
+
+# pylint: enable=unnecessary-pass
+class PWMOut:
+    """Pulse Width Modulation Output Class"""
+
+    MAX_CYCLE_LEVEL = 1024
+
+    def __init__(self, pin, *, frequency=750, duty_cycle=0, variable_frequency=False):
+        """This class makes use of the GreatFET One's Pattern Generator to create a
+        Simulated Pulse width modulation. The way that the Pattern Generator works is that
+        takes a pattern in the form of bytes and will repeat the output. The trick to simulate
+        PWM is to generate the correct byte pattern for the correct channel.
+
+        Args:
+            pin (Pin): CircuitPython Pin object to output to
+            duty_cycle (int) : The fraction of each pulse which is high. 16-bit
+            frequency (int) : target frequency in Hertz (32-bit)
+
+        Returns:
+            PWMOut: PWMOut object.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if `channel` or `pin` types are invalid.
+            ValueError: if PWM channel does not exist.
+        """
+        self._gf = GreatFET()
+
+        if variable_frequency:
+            raise NotImplemented("Variable Frequency is not currently supported.")
+
+        self._pattern = None
+        self._channel = None
+        self._enable = False
+        self._open(pin, duty_cycle, frequency)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, t, value, traceback):
+        self.deinit()
+
+    def _open(self, pin, duty=0, freq=500):
+        self._channel = None
+        for pwmpair in pwmOuts:
+            if pwmpair[1] == pin:
+                self._channel = pwmpair[0]
+
+        self._pin = pin
+        if self._channel is None:
+            raise RuntimeError("No PWM channel found for this Pin")
+
+        # set duty
+        self.duty_cycle = duty
+
+        # set frequency
+        self.frequency = freq
+
+        self._set_enabled(True)
+
+    def deinit(self):
+        """Deinit the GreatFET One PWM."""
+        # pylint: disable=broad-except
+        try:
+            if self._channel is not None:
+                # self.duty_cycle = 0
+                self._set_enabled(False)
+        except Exception as e:
+            # due to a race condition for which I have not yet been
+            # able to find the root cause, deinit() often fails
+            # but it does not effect future usage of the pwm pin
+            print(
+                "warning: failed to deinitialize pwm pin {0} due to: {1}\n".format(
+                    self._channel, type(e).__name__
+                )
+            )
+        finally:
+            self._pattern = None
+            self._channel = None
+        # pylint: enable=broad-except
+
+    def _is_deinited(self):
+        if self._pattern is None:
+            raise ValueError(
+                "Object has been deinitialize and can no longer "
+                "be used. Create a new object."
+            )
+
+    # Mutable properties
+
+    def _get_period(self):
+        return 1.0 / self._get_frequency()
+
+    def _set_period(self, period):
+        """Get or set the PWM's output period in seconds.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not int or float.
+
+        :type: int, float
+        """
+        if not isinstance(period, (int, float)):
+            raise TypeError("Invalid period type, should be int or float.")
+
+        self._set_frequency(1.0 / period)
+
+    period = property(_get_period, _set_period)
+
+
+    def _get_duty_cycle(self):
+        """Get or set the PWM's output duty cycle as a ratio from 0.0 to 1.0.
+
+        Raises:
+           PWMError: if an I/O or OS error occurs.
+           TypeError: if value type is not int or float.
+           ValueError: if value is out of bounds of 0.0 to 1.0.
+
+        :type: int, float
+        """
+        return self._duty_cycle
+
+    def _set_duty_cycle(self, duty_cycle):
+        if not isinstance(duty_cycle, (int, float)):
+            raise TypeError("Invalid duty cycle type, should be int or float.")
+
+        # convert from 16-bit
+        if isinstance(duty_cycle, int):
+            duty_cycle /= 65535.0
+        if not 0.0 <= duty_cycle <= 1.0:
+           raise ValueError("Invalid duty cycle value, should be between 0.0 and 1.0.")
+       
+        # Generate a pattern for 1024 samples of the duty cycle
+        pattern = [(1 << self._channel)] * round(PWMOut.MAX_CYCLE_LEVEL * duty_cycle)
+        pattern += [(0 << self._channel)] * round(PWMOut.MAX_CYCLE_LEVEL * (1.0 - duty_cycle))
+        
+        self._pattern = pattern
+        self._duty_cycle = duty_cycle
+        if self._enable:
+            self._set_enabled(True)
+
+    duty_cycle = property(_get_duty_cycle, _set_duty_cycle)
+
+    def _get_frequency(self):
+        return int(PWMOut._nova.getIOpinPWMFreq(self._pwmpin).split("PWMFREQ ")[1])
+
+    def _set_frequency(self, frequency):
+        """Get or set the PWM's output frequency in Hertz.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not int or float.
+
+        :type: int, float
+        """
+        if not isinstance(frequency, (int, float)):
+            raise TypeError("Invalid frequency type, should be int or float.")
+
+        # We are sending 1024 samples per second already
+        self._gf.pattern_generator.set_sample_rate(frequency * len(self._pattern))
+
+    frequency = property(_get_frequency, _set_frequency)
+
+    def _get_enabled(self):
+        enabled = self._enable
+
+        if enabled == "1":
+            return True
+        if enabled == "0":
+            return False
+
+        raise PWMError(None, 'Unknown enabled value: "%s"' % enabled)
+
+    def _set_enabled(self, value):
+        """Get or set the PWM's output enabled state.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not bool.
+
+        :type: bool
+        """
+        if not isinstance(value, bool):
+            raise TypeError("Invalid enabled type, should be string.")
+        self._enable = value
+        if self._gf:
+            if self._enable:
+                if self._pattern:
+                    self._gf.pattern_generator.scan_out_pattern(self._pattern)
+            else:
+                self._gf.pattern_generator.stop()
diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/spi.py
new file mode 100644 (file)
index 0000000..37cc6c4
--- /dev/null
@@ -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)
diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/uart.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/uart.py
new file mode 100644 (file)
index 0000000..b791269
--- /dev/null
@@ -0,0 +1,66 @@
+"""UART Class for NXP LPC4330"""
+from greatfet import GreatFET
+from greatfet.interfaces.uart import UART as _UART
+
+class UART:
+    """Custom UART Class for NXP LPC4330"""
+
+    PARITY_NONE          = 0
+    PARITY_ODD           = 1
+    PARITY_EVEN          = 2
+    PARITY_STUCK_AT_ONE  = 3
+    PARITY_STUCK_AT_ZERO = 4
+
+    # pylint: disable=too-many-arguments
+    def __init__(
+        self,
+        portid,
+        baudrate=9600,
+        bits=8,
+        parity=None,
+        stop=1,
+        timeout=1000,
+        read_buf_len=None,
+        flow=None,
+    ):
+        self._gf = GreatFET()
+        self._uart = _UART(self._gf, baud=baudrate, data_bits=bits, stop_bits=stop, parity=parity, uart_number=portid)
+        
+        if flow is not None:  # default None
+            raise NotImplementedError(
+                "Parameter '{}' unsupported on GreatFET One".format("flow")
+            )
+
+    # pylint: enable=too-many-arguments
+
+    def deinit(self):
+        """Deinitialize"""
+        self._uart.initialized = False
+
+    def read(self, nbytes=None):
+        """Read data from UART and return it"""
+        if nbytes is None:
+            return None
+        return self._uart.read(nbytes)
+
+    def readinto(self, buf, nbytes=None):
+        """Read data from UART and into the buffer"""
+        if nbytes is None:
+            return None
+        result = self.read(nbytes)
+        for _ in range(nbytes):
+            buf.append(result)
+        return buf
+
+    def readline(self):
+        """Read a single line of data from UART"""
+        out = self.read(nbytes=1)
+        line = out
+        while out != "\r":
+            out = self.read(nbytes=1)
+            line += out
+        return line
+
+    def write(self, buf):
+        """Write data from the buffer to UART"""
+        return self._uart.write(buf)
index 4bfcb36543aaa2c10cfdaf13b683f5f82fe7474d..bde4441e783af0d4b8e2502832617d27b6a0c255 100644 (file)
@@ -12,6 +12,9 @@ from adafruit_blinka.agnostic import board_id, detector
 if detector.board.microchip_mcp2221:
     from adafruit_blinka.microcontroller.mcp2221.analogio import AnalogIn
     from adafruit_blinka.microcontroller.mcp2221.analogio import AnalogOut
 if detector.board.microchip_mcp2221:
     from adafruit_blinka.microcontroller.mcp2221.analogio import AnalogIn
     from adafruit_blinka.microcontroller.mcp2221.analogio import AnalogOut
+elif detector.board.greatfet_one:
+    from adafruit_blinka.microcontroller.nxp_lpc4330.analogio import AnalogIn
+    from adafruit_blinka.microcontroller.nxp_lpc4330.analogio import AnalogOut
 elif detector.chip.RK3308:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_analogin import AnalogIn
 else:
 elif detector.chip.RK3308:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_analogin import AnalogIn
 else:
index 0c02cda07bb4d4d16414662a8f46abe66f07e0cc..e9b7da10756bd910e1adc39bc0a6618c81495a03 100755 (executable)
@@ -137,6 +137,9 @@ elif board_id == ap_board.BINHO_NOVA:
 elif board_id == ap_board.MICROCHIP_MCP2221:
     from adafruit_blinka.board.microchip_mcp2221 import *
 
 elif board_id == ap_board.MICROCHIP_MCP2221:
     from adafruit_blinka.board.microchip_mcp2221 import *
 
+elif board_id == ap_board.GREATFET_ONE:
+    from adafruit_blinka.board.greatfet_one import *
+
 elif board_id == ap_board.SIFIVE_UNLEASHED:
     from adafruit_blinka.board.hifive_unleashed import *
 
 elif board_id == ap_board.SIFIVE_UNLEASHED:
     from adafruit_blinka.board.hifive_unleashed import *
 
index a5dc856afb841ed191ed9a1f7e3aa546231f2aa2..4786ee4676a77a2342aca88d41f1b9b57aaae360 100755 (executable)
@@ -34,6 +34,11 @@ class I2C(Lockable):
         elif detector.board.microchip_mcp2221:
             from adafruit_blinka.microcontroller.mcp2221.i2c import I2C
 
         elif detector.board.microchip_mcp2221:
             from adafruit_blinka.microcontroller.mcp2221.i2c import I2C
 
+            self._i2c = I2C(frequency=frequency)
+            return
+        elif detector.board.greatfet_one:
+            from adafruit_blinka.microcontroller.nxp_lpc4330.i2c import I2C
+
             self._i2c = I2C(frequency=frequency)
             return
         elif detector.board.any_embedded_linux:
             self._i2c = I2C(frequency=frequency)
             return
         elif detector.board.any_embedded_linux:
@@ -136,6 +141,13 @@ class SPI(Lockable):
             self._spi = _SPI(clock)
             self._pins = (SCK, MOSI, MISO)
             return
             self._spi = _SPI(clock)
             self._pins = (SCK, MOSI, MISO)
             return
+        elif detector.board.greatfet_one:
+            from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
+            from adafruit_blinka.microcontroller.nxp_lpc4330.pin import SCK, MOSI, MISO
+
+            self._spi = _SPI()
+            self._pins = (SCK, MOSI, MISO)
+            return
         elif detector.board.any_embedded_linux:
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
         else:
         elif detector.board.any_embedded_linux:
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
         else:
@@ -210,6 +222,9 @@ class SPI(Lockable):
         elif detector.board.binho_nova:
             from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
             from adafruit_blinka.microcontroller.nova.pin import Pin
         elif detector.board.binho_nova:
             from adafruit_blinka.microcontroller.nova.spi import SPI as _SPI
             from adafruit_blinka.microcontroller.nova.pin import Pin
+        elif detector.board.greatfet_one:
+            from adafruit_blinka.microcontroller.nxp_lpc4330.spi import SPI as _SPI
+            from adafruit_blinka.microcontroller.nxp_lpc4330.pin import Pin
         elif (
             board_id == ap_board.PINE64
             or board_id == ap_board.PINEBOOK
         elif (
             board_id == ap_board.PINE64
             or board_id == ap_board.PINEBOOK
@@ -294,6 +309,8 @@ class UART(Lockable):
             )
         elif detector.board.binho_nova:
             from adafruit_blinka.microcontroller.nova.uart import UART as _UART
             )
         elif detector.board.binho_nova:
             from adafruit_blinka.microcontroller.nova.uart import UART as _UART
+        elif detector.board.greatfet_one:
+            from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART
         else:
             from machine import UART as _UART
 
         else:
             from machine import UART as _UART
 
index 73f93cf39e252e04efa48963344de24bad87cbca..6a372607c8c0f19920ef7ffd202af8c30a96d2b2 100755 (executable)
@@ -49,6 +49,8 @@ elif detector.board.ftdi_ft232h:
     from adafruit_blinka.microcontroller.ft232h.pin import Pin
 elif detector.board.binho_nova:
     from adafruit_blinka.microcontroller.nova.pin import Pin
     from adafruit_blinka.microcontroller.ft232h.pin import Pin
 elif detector.board.binho_nova:
     from adafruit_blinka.microcontroller.nova.pin import Pin
+elif detector.board.greatfet_one:
+    from adafruit_blinka.microcontroller.nxp_lpc4330.pin import Pin
 elif detector.chip.STM32:
     from machine import Pin
 elif detector.board.microchip_mcp2221:
 elif detector.chip.STM32:
     from machine import Pin
 elif detector.board.microchip_mcp2221:
index 29b25f8f37ceeb02280fd7f334d4d73dde944d17..5064b7a40dcbd94b2bea1f351ac8a93d2c99317c 100755 (executable)
@@ -70,6 +70,8 @@ elif chip_id == ap_chip.HFU540:
     from adafruit_blinka.microcontroller.hfu540.pin import *
 elif chip_id == ap_chip.BINHO:
     from adafruit_blinka.microcontroller.nova import *
     from adafruit_blinka.microcontroller.hfu540.pin import *
 elif chip_id == ap_chip.BINHO:
     from adafruit_blinka.microcontroller.nova import *
+elif chip_id == ap_chip.LPC4330:
+    from adafruit_blinka.microcontroller.nxp_lpc4330 import *
 elif chip_id == ap_chip.MIPS24KC:
     from adafruit_blinka.microcontroller.atheros.ar9331.pin import *
 elif chip_id == ap_chip.MIPS24KEC:
 elif chip_id == ap_chip.MIPS24KC:
     from adafruit_blinka.microcontroller.atheros.ar9331.pin import *
 elif chip_id == ap_chip.MIPS24KEC:
index cad4bfac1496e296c19498bba8a213fc1015b515..458f20c016bb2312144d661766437f99cd0fa7c5 100755 (executable)
@@ -40,6 +40,8 @@ elif chip_id == ap_chip.FT232H:
     from adafruit_blinka.microcontroller.ft232h.pin import *
 elif chip_id == ap_chip.BINHO:
     from adafruit_blinka.microcontroller.nova.pin import *
     from adafruit_blinka.microcontroller.ft232h.pin import *
 elif chip_id == ap_chip.BINHO:
     from adafruit_blinka.microcontroller.nova.pin import *
+elif chip_id == ap_chip.LPC4330:
+    from adafruit_blinka.microcontroller.nxp_lpc4330.pin import *
 elif chip_id == ap_chip.MCP2221:
     from adafruit_blinka.microcontroller.mcp2221.pin import *
 elif chip_id == ap_chip.A64:
 elif chip_id == ap_chip.MCP2221:
     from adafruit_blinka.microcontroller.mcp2221.pin import *
 elif chip_id == ap_chip.A64:
index e1f7aab09257dba7c03ddf576dcd87ad7eeaf214..7db0b6a36727d49765838d3ed95497ca3a27381d 100644 (file)
@@ -12,3 +12,5 @@ if detector.board.any_rock_pi_board:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
 if detector.board.binho_nova:
     from adafruit_blinka.microcontroller.nova.pwmout import PWMOut
     from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
 if detector.board.binho_nova:
     from adafruit_blinka.microcontroller.nova.pwmout import PWMOut
+if detector.board.greatfet_one:
+    from adafruit_blinka.microcontroller.nxp_lpc4330.pwmout import PWMOut