From: Melissa LeBlanc-Williams Date: Thu, 14 May 2020 16:58:38 +0000 (-0700) Subject: Added GreatFET One Support X-Git-Tag: 4.9.0~1^2~1 X-Git-Url: https://git.ayoreis.com/Adafruit_Blinka-hackapet.git/commitdiff_plain/98f4a4378478d11e514acd7ff22a9c674f3cbca3 Added GreatFET One Support --- diff --git a/src/adafruit_blinka/board/greatfet_one.py b/src/adafruit_blinka/board/greatfet_one.py new file mode 100644 index 0000000..87a5173 --- /dev/null +++ b/src/adafruit_blinka/board/greatfet_one.py @@ -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 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 index 0000000..e45e8d2 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/nxp_lpc4330/analogio.py @@ -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 index 0000000..e37fae1 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/nxp_lpc4330/i2c.py @@ -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 index 0000000..a67032e --- /dev/null +++ b/src/adafruit_blinka/microcontroller/nxp_lpc4330/pin.py @@ -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 index 0000000..08a31b7 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/nxp_lpc4330/pwmout.py @@ -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 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) diff --git a/src/adafruit_blinka/microcontroller/nxp_lpc4330/uart.py b/src/adafruit_blinka/microcontroller/nxp_lpc4330/uart.py new file mode 100644 index 0000000..b791269 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/nxp_lpc4330/uart.py @@ -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) diff --git a/src/analogio.py b/src/analogio.py index 4bfcb36..bde4441 100644 --- a/src/analogio.py +++ b/src/analogio.py @@ -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 +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: diff --git a/src/board.py b/src/board.py index 0c02cda..e9b7da1 100755 --- a/src/board.py +++ b/src/board.py @@ -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.GREATFET_ONE: + from adafruit_blinka.board.greatfet_one import * + elif board_id == ap_board.SIFIVE_UNLEASHED: from adafruit_blinka.board.hifive_unleashed import * diff --git a/src/busio.py b/src/busio.py index a5dc856..4786ee4 100755 --- a/src/busio.py +++ b/src/busio.py @@ -34,6 +34,11 @@ class I2C(Lockable): 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: @@ -136,6 +141,13 @@ class SPI(Lockable): 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: @@ -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.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 @@ -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.greatfet_one: + from adafruit_blinka.microcontroller.nxp_lpc4330.uart import UART as _UART else: from machine import UART as _UART diff --git a/src/digitalio.py b/src/digitalio.py index 73f93cf..6a37260 100755 --- a/src/digitalio.py +++ b/src/digitalio.py @@ -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 +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: diff --git a/src/microcontroller/__init__.py b/src/microcontroller/__init__.py index 29b25f8..5064b7a 100755 --- a/src/microcontroller/__init__.py +++ b/src/microcontroller/__init__.py @@ -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 * +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: diff --git a/src/microcontroller/pin.py b/src/microcontroller/pin.py index cad4bfa..458f20c 100755 --- a/src/microcontroller/pin.py +++ b/src/microcontroller/pin.py @@ -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 * +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: diff --git a/src/pulseio.py b/src/pulseio.py index e1f7aab..7db0b6a 100644 --- a/src/pulseio.py +++ b/src/pulseio.py @@ -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 +if detector.board.greatfet_one: + from adafruit_blinka.microcontroller.nxp_lpc4330.pwmout import PWMOut