From: Limor "Ladyada" Fried Date: Sat, 22 May 2021 14:00:43 +0000 (-0400) Subject: Merge pull request #476 from caternuson/feather_u2if X-Git-Tag: 6.10.0~1 X-Git-Url: https://git.ayoreis.com/Adafruit_Blinka-hackapet.git/commitdiff_plain/4320a101dd8a5f27dc528101d9a9f22c72005355?hp=712df061cb765817fa1a81fe2f118458b7af8375 Merge pull request #476 from caternuson/feather_u2if Adding more u2if firmware boards --- diff --git a/src/adafruit_blinka/board/feather_u2if.py b/src/adafruit_blinka/board/feather_u2if.py new file mode 100644 index 0000000..a6ba759 --- /dev/null +++ b/src/adafruit_blinka/board/feather_u2if.py @@ -0,0 +1,45 @@ +""" +Pin definitions for the Feather RP2040 with u2if firmware. + +Adafruit CircuitPython 6.2.0 on 2021-04-05; Adafruit Feather RP2040 with rp2040 +>>> import board +>>> board. +A0 A1 A2 A3 +D0 D1 D10 D11 +D12 D13 D24 D25 +D4 D5 D6 D9 +I2C LED MISO MOSI +NEOPIXEL RX SCK SCL +SDA SPI TX UART +""" + +from adafruit_blinka.microcontroller.rp2040_u2if import pin + +D0 = pin.GP0 +D1 = pin.GP1 +D4 = pin.GP6 +D5 = pin.GP7 +D6 = pin.GP8 +D9 = pin.GP9 +D10 = pin.GP10 +D11 = pin.GP11 +D12 = pin.GP12 +D13 = pin.GP13 +D24 = pin.GP24 +D25 = pin.GP25 + +A0 = pin.GP26 +A1 = pin.GP27 +A2 = pin.GP28 +# A3 = pin.GP29 # not currently supported in firmware + +SCL = pin.GP3 +SDA = pin.GP2 + +SCLK = SCK = pin.GP18 +MOSI = pin.GP19 +MISO = pin.GP20 + +# access u2if via pin instance to open for specifc VID/PID +# pylint:disable = protected-access +pin.GP0._u2if_open_hid(0x239A, 0x00F1) diff --git a/src/adafruit_blinka/board/itsybitsy_u2if.py b/src/adafruit_blinka/board/itsybitsy_u2if.py new file mode 100644 index 0000000..c13d24c --- /dev/null +++ b/src/adafruit_blinka/board/itsybitsy_u2if.py @@ -0,0 +1,54 @@ +""" +Pin definitions for the ItsyBitsy RP2040 with u2if firmware. + +Adafruit CircuitPython 6.2.0 on 2021-04-05; Adafruit ItsyBitsy RP2040 with rp2040 +>>> import board +>>> board. +A0 A1 A2 A3 +BUTTON D0 D1 D10 +D11 D12 D13 D2 +D24 D25 D3 D4 +D5 D7 D9 I2C +LED MISO MOSI NEOPIXEL +NEOPIXEL_POWER RX SCK SCL +SDA SPI TX UART +""" + + +from adafruit_blinka.microcontroller.rp2040_u2if import pin + +D0 = pin.GP1 +D1 = pin.GP0 +D2 = pin.GP12 +D3 = pin.GP5 +D4 = pin.GP4 +D5 = pin.GP14 +D7 = pin.GP6 +D9 = pin.GP7 +D10 = pin.GP8 +D11 = pin.GP9 +D12 = pin.GP10 +D13 = pin.GP11 +D24 = pin.GP24 +D25 = pin.GP25 + +A0 = pin.GP26 +A1 = pin.GP27 +A2 = pin.GP28 +# A3 = pin.GP29 # not currently supported in firmware + +SCL = pin.GP3 +SDA = pin.GP2 + +SCLK = SCK = pin.GP18 +MOSI = pin.GP19 +MISO = pin.GP20 + +NEOPIXEL = pin.GP17 +NEOPIXEL_POWER = pin.GP16 + +BUTTON = pin.GP13 + +# access u2if via pin instance to open for specifc VID/PID +# pylint:disable = protected-access +pin.GP0._u2if_open_hid(0x239A, 0x00FD) diff --git a/src/adafruit_blinka/board/pico_u2if.py b/src/adafruit_blinka/board/pico_u2if.py index bcdfe47..6564ed3 100644 --- a/src/adafruit_blinka/board/pico_u2if.py +++ b/src/adafruit_blinka/board/pico_u2if.py @@ -1,5 +1,5 @@ -"""Pin definitions for the MicroChip MCP2221""" -from adafruit_blinka.microcontroller.pico_u2if import pin +"""Pin definitions for the Raspberry Pi Pico running u2if firmware""" +from adafruit_blinka.microcontroller.rp2040_u2if import pin GP0 = pin.GP0 GP1 = pin.GP1 @@ -44,3 +44,7 @@ MISO = MISO0 = GP12 SCLK1 = SCK1 = GP10 MOSI1 = GP11 MISO1 = GP12 + +# access u2if via pin instance to open for specifc VID/PID +# pylint:disable = protected-access +pin.GP0._u2if_open_hid(0xCAFE, 0x4005) diff --git a/src/adafruit_blinka/board/qt2040_trinkey_u2if.py b/src/adafruit_blinka/board/qt2040_trinkey_u2if.py new file mode 100644 index 0000000..d71bea8 --- /dev/null +++ b/src/adafruit_blinka/board/qt2040_trinkey_u2if.py @@ -0,0 +1,14 @@ +"""Pin definitions for the QT2040 Trinkey with u2if firmware.""" + +from adafruit_blinka.microcontroller.rp2040_u2if import pin + +BUTTON = pin.GP12 + +SCL = pin.GP17 +SDA = pin.GP16 + +NEOPIXEL = pin.GP27 + +# access u2if via pin instance to open for specifc VID/PID +# pylint:disable = protected-access +pin.GP0._u2if_open_hid(0x239A, 0x0109) diff --git a/src/adafruit_blinka/board/qtpy_u2if.py b/src/adafruit_blinka/board/qtpy_u2if.py new file mode 100644 index 0000000..569ace2 --- /dev/null +++ b/src/adafruit_blinka/board/qtpy_u2if.py @@ -0,0 +1,54 @@ +""" +Pin definitions for the QT Py RP2040 with u2if firmware. + +Adafruit CircuitPython 6.2.0 on 2021-04-05; Adafruit QTPy RP2040 with rp2040 +>>> import board +>>> board. +A0 A1 A2 A3 +BUTTON D0 D1 D10 +D2 D3 D4 D5 +D6 D7 D8 D9 +I2C MISO MOSI NEOPIXEL +NEOPIXEL_POWER RX SCK SCL +SCL1 SDA SDA1 SPI +TX UART +""" + + +from adafruit_blinka.microcontroller.rp2040_u2if import pin + +D0 = pin.GP29 +D1 = pin.GP28 +D2 = pin.GP27 +D3 = pin.GP26 +D4 = pin.GP24 +D5 = pin.GP25 +D6 = pin.GP20 +D7 = pin.GP5 +D8 = pin.GP6 +D9 = pin.GP4 +D10 = pin.GP3 + +# A0 = pin.GP29 # not currently supported in firmware +A1 = pin.GP28 +A2 = pin.GP27 +A3 = pin.GP26 + +SCL = pin.GP25 +SDA = pin.GP24 + +SCL1 = pin.GP23 +SDA1 = pin.GP22 + +SCLK = SCK = pin.GP6 +MOSI = pin.GP3 +MISO = pin.GP4 + +NEOPIXEL = pin.GP12 +NEOPIXEL_POWER = pin.GP11 + +BUTTON = pin.GP21 + +# access u2if via pin instance to open for specifc VID/PID +# pylint:disable = protected-access +pin.GP0._u2if_open_hid(0x239A, 0x00F7) diff --git a/src/adafruit_blinka/microcontroller/pico_u2if/analogio.py b/src/adafruit_blinka/microcontroller/pico_u2if/analogio.py deleted file mode 100644 index 2ae480f..0000000 --- a/src/adafruit_blinka/microcontroller/pico_u2if/analogio.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -`analogio` - Analog input and output control -================================================= -See `CircuitPython:analogio` in CircuitPython for more details. -* Author(s): Carter Nelson -""" -from adafruit_blinka import ContextManaged -from .pico_u2if import pico_u2if - - -class AnalogIn(ContextManaged): - """Analog Input Class""" - - def __init__(self, pin): - # per their pinout, why only two? - if pin.id not in (26, 27): - raise ValueError("Pin does not support ADC.") - self.pin_id = pin.id - pico_u2if.adc_init_pin(self.pin_id) - - @property - def value(self): - """Read the ADC and return the value""" - return pico_u2if.adc_get_value(self.pin_id) << 4 - - # 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): - pass diff --git a/src/adafruit_blinka/microcontroller/pico_u2if/i2c.py b/src/adafruit_blinka/microcontroller/pico_u2if/i2c.py deleted file mode 100644 index ee393bb..0000000 --- a/src/adafruit_blinka/microcontroller/pico_u2if/i2c.py +++ /dev/null @@ -1,62 +0,0 @@ -"""I2C Class for Pico u2if""" -from .pico_u2if import pico_u2if - - -class I2C: - """Custom I2C Class for Pico u2if""" - - def __init__(self, scl, sda, *, frequency=100000): - index = None - if scl.id == 5 and sda.id == 4: - index = 0 - if scl.id == 15 and sda.id == 14: - index = 1 - if index is None: - raise ValueError("I2C not found on specified pins.") - self._index = index - pico_u2if.i2c_set_port(self._index) - pico_u2if.i2c_configure(frequency) - - def scan(self): - """Perform an I2C Device Scan""" - pico_u2if.i2c_set_port(self._index) - return pico_u2if.i2c_scan() - - # pylint: disable=unused-argument - def writeto(self, address, buffer, *, start=0, end=None, stop=True): - """Write data from the buffer to an address""" - pico_u2if.i2c_set_port(self._index) - pico_u2if.i2c_writeto(address, buffer, start=start, end=end) - - def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True): - """Read data from an address and into the buffer""" - pico_u2if.i2c_set_port(self._index) - pico_u2if.i2c_readfrom_into(address, buffer, start=start, end=end) - - 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 - """ - pico_u2if.i2c_set_port(self._index) - pico_u2if.i2c_writeto_then_readfrom( - address, - buffer_out, - buffer_in, - out_start=out_start, - out_end=out_end, - in_start=in_start, - in_end=in_end, - ) - - # pylint: enable=unused-argument diff --git a/src/adafruit_blinka/microcontroller/pico_u2if/spi.py b/src/adafruit_blinka/microcontroller/pico_u2if/spi.py deleted file mode 100644 index e4d7202..0000000 --- a/src/adafruit_blinka/microcontroller/pico_u2if/spi.py +++ /dev/null @@ -1,71 +0,0 @@ -"""SPI Class for Pico u2if""" -from .pico_u2if import pico_u2if - -# pylint: disable=protected-access, no-self-use -class SPI: - """Custom SPI Class for Pico u2if""" - - MSB = 0 - - def __init__(self, clock, *, baudrate=100000): - index = None - if clock.id == 18: - index = 0 - if clock.id == 10: - index = 1 - if index is None: - raise ValueError("No SPI port on specified pin.") - self._index = index - self._frequency = baudrate - pico_u2if.spi_set_port(self._index) - pico_u2if.spi_configure(self._frequency) - - # pylint: disable=too-many-arguments,unused-argument - def init( - self, - baudrate=1000000, - polarity=0, - phase=0, - bits=8, - firstbit=MSB, - sck=None, - mosi=None, - miso=None, - ): - """Initialize the Port""" - self._frequency = baudrate - pico_u2if.spi_set_port(self._index) - pico_u2if.spi_configure(self._frequency) - - # pylint: enable=too-many-arguments - - @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""" - pico_u2if.spi_write(buf, start=start, end=end) - - def readinto(self, buf, start=0, end=None, write_value=0): - """Read data from SPI and into the buffer""" - pico_u2if.spi_readinto(buf, start=start, end=end, write_value=write_value) - - # 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 - """ - pico_u2if.spi_write_readinto( - buffer_out, - buffer_in, - out_start=out_start, - out_end=out_end, - in_start=in_start, - in_end=in_end, - ) - - # pylint: enable=too-many-arguments diff --git a/src/adafruit_blinka/microcontroller/pico_u2if/__init__.py b/src/adafruit_blinka/microcontroller/rp2040_u2if/__init__.py similarity index 100% rename from src/adafruit_blinka/microcontroller/pico_u2if/__init__.py rename to src/adafruit_blinka/microcontroller/rp2040_u2if/__init__.py diff --git a/src/adafruit_blinka/microcontroller/rp2040_u2if/analogio.py b/src/adafruit_blinka/microcontroller/rp2040_u2if/analogio.py new file mode 100644 index 0000000..e4db746 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/rp2040_u2if/analogio.py @@ -0,0 +1,69 @@ +""" +`analogio` - Analog input and output control +================================================= +See `CircuitPython:analogio` in CircuitPython for more details. +* Author(s): Carter Nelson +""" +from adafruit_blinka import ContextManaged +from .rp2040_u2if import rp2040_u2if + + +class AnalogIn(ContextManaged): + """AnalogIn Base Class for RP2040 u2if""" + + def __init__(self, pin): + self.pin_id = pin.id + rp2040_u2if.adc_init_pin(self.pin_id) + + @property + def value(self): + """Read the ADC and return the value""" + return rp2040_u2if.adc_get_value(self.pin_id) << 4 + + # 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): + pass + + +class AnalogIn_Pico(AnalogIn): + """AnalogIn Base Class for Pico u2if""" + + def __init__(self, pin): + # per their pinout, why only two? + if pin.id not in (26, 27): + raise ValueError("Pin does not support ADC.") + super().__init__(pin) + + +class AnalogIn_Feather(AnalogIn): + """AnalogIn Base Class for Feather u2if""" + + def __init__(self, pin): + if pin.id not in (26, 27, 28): + raise ValueError("Pin does not support ADC.") + super().__init__(pin) + + +class AnalogIn_QTPY(AnalogIn): + """AnalogIn Base Class for QT Py 2040 u2if""" + + def __init__(self, pin): + if pin.id not in (26, 27, 28): + raise ValueError("Pin does not support ADC.") + super().__init__(pin) + + +class AnalogIn_ItsyBitsy(AnalogIn): + """AnalogIn Base Class for ItsyBitsy 2040 u2if""" + + def __init__(self, pin): + if pin.id not in (26, 27, 28): + raise ValueError("Pin does not support ADC.") + super().__init__(pin) diff --git a/src/adafruit_blinka/microcontroller/rp2040_u2if/i2c.py b/src/adafruit_blinka/microcontroller/rp2040_u2if/i2c.py new file mode 100644 index 0000000..f12764a --- /dev/null +++ b/src/adafruit_blinka/microcontroller/rp2040_u2if/i2c.py @@ -0,0 +1,129 @@ +"""I2C Classes for RP2040s with u2if firmware""" +from .rp2040_u2if import rp2040_u2if + + +class I2C: + """I2C Base Class for RP2040 u2if""" + + def __init__(self, index, *, frequency=100000): + self._index = index + rp2040_u2if.i2c_set_port(self._index) + rp2040_u2if.i2c_configure(frequency) + + def scan(self): + """Perform an I2C Device Scan""" + rp2040_u2if.i2c_set_port(self._index) + return rp2040_u2if.i2c_scan() + + # pylint: disable=unused-argument + def writeto(self, address, buffer, *, start=0, end=None, stop=True): + """Write data from the buffer to an address""" + rp2040_u2if.i2c_set_port(self._index) + rp2040_u2if.i2c_writeto(address, buffer, start=start, end=end) + + def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True): + """Read data from an address and into the buffer""" + rp2040_u2if.i2c_set_port(self._index) + rp2040_u2if.i2c_readfrom_into(address, buffer, start=start, end=end) + + 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 + """ + rp2040_u2if.i2c_set_port(self._index) + rp2040_u2if.i2c_writeto_then_readfrom( + address, + buffer_out, + buffer_in, + out_start=out_start, + out_end=out_end, + in_start=in_start, + in_end=in_end, + ) + + # pylint: enable=unused-argument + + +class I2C_Pico(I2C): + """I2C Class for Pico u2if""" + + def __init__(self, scl, sda, *, frequency=100000): + index = None + if scl.id == 5 and sda.id == 4: + index = 0 + if scl.id == 15 and sda.id == 14: + index = 1 + if index is None: + raise ValueError("I2C not found on specified pins.") + self._index = index + + super().__init__(index, frequency=frequency) + + +class I2C_Feather(I2C): + """I2C Class for Feather u2if""" + + def __init__(self, scl, sda, *, frequency=100000): + index = None + if scl.id == 3 and sda.id == 2: + index = 1 + if index is None: + raise ValueError("I2C not found on specified pins.") + self._index = index + + super().__init__(index, frequency=frequency) + + +class I2C_QTPY(I2C): + """I2C Class for QT Py 2if""" + + def __init__(self, scl, sda, *, frequency=100000): + index = None + if scl.id == 25 and sda.id == 24: + index = 0 + if scl.id == 23 and sda.id == 22: + index = 1 + if index is None: + raise ValueError("I2C not found on specified pins.") + self._index = index + + super().__init__(index, frequency=frequency) + + +class I2C_ItsyBitsy(I2C): + """I2C Class for ItsyBitsy u2if""" + + def __init__(self, scl, sda, *, frequency=100000): + index = None + if scl.id == 3 and sda.id == 2: + index = 1 + if index is None: + raise ValueError("I2C not found on specified pins.") + self._index = index + + super().__init__(index, frequency=frequency) + + +class I2C_QT2040_Trinkey(I2C): + """I2C Class for QT2040 Trinkey u2if""" + + def __init__(self, scl, sda, *, frequency=100000): + index = None + if scl.id == 17 and sda.id == 16: + index = 0 + if index is None: + raise ValueError("I2C not found on specified pins.") + self._index = index + + super().__init__(index, frequency=frequency) diff --git a/src/adafruit_blinka/microcontroller/pico_u2if/neopixel.py b/src/adafruit_blinka/microcontroller/rp2040_u2if/neopixel.py similarity index 79% rename from src/adafruit_blinka/microcontroller/pico_u2if/neopixel.py rename to src/adafruit_blinka/microcontroller/rp2040_u2if/neopixel.py index 4953c2d..f0177ae 100644 --- a/src/adafruit_blinka/microcontroller/pico_u2if/neopixel.py +++ b/src/adafruit_blinka/microcontroller/rp2040_u2if/neopixel.py @@ -1,6 +1,6 @@ """NeoPixel write for Pico u2if.""" -from .pico_u2if import pico_u2if +from .rp2040_u2if import rp2040_u2if def neopixel_write(gpio, buf): @@ -14,4 +14,4 @@ def neopixel_write(gpio, buf): buffer.append(buf[i + 1]) buffer.append(buf[i]) - pico_u2if.neopixel_write(gpio, buffer) + rp2040_u2if.neopixel_write(gpio, buffer) diff --git a/src/adafruit_blinka/microcontroller/pico_u2if/pin.py b/src/adafruit_blinka/microcontroller/rp2040_u2if/pin.py similarity index 77% rename from src/adafruit_blinka/microcontroller/pico_u2if/pin.py rename to src/adafruit_blinka/microcontroller/rp2040_u2if/pin.py index ef22587..37a5ed5 100644 --- a/src/adafruit_blinka/microcontroller/pico_u2if/pin.py +++ b/src/adafruit_blinka/microcontroller/rp2040_u2if/pin.py @@ -1,9 +1,9 @@ -"""PICO pin names""" -from .pico_u2if import pico_u2if +"""Generic RP2040 pin names""" +from .rp2040_u2if import rp2040_u2if class Pin: - """A basic Pin class for use with MCP2221.""" + """A basic Pin class for use with RP2040 with u2if firmware.""" # pin modes IN = 0 @@ -21,6 +21,10 @@ class Pin: self._mode = None self._pull = None + # pylint:disable = no-self-use + def _u2if_open_hid(self, vid, pid): + rp2040_u2if.open(vid, pid) + def init(self, mode=IN, pull=PULL_NONE): """Initialize the Pin""" pull = Pin.PULL_NONE if pull is None else pull @@ -31,7 +35,7 @@ class Pin: if pull not in (Pin.PULL_NONE, Pin.PULL_UP, Pin.PULL_DOWN): raise ValueError("Incorrect pull value.") - pico_u2if.gpio_init_pin(self.id, mode, pull) + rp2040_u2if.gpio_init_pin(self.id, mode, pull) self._mode = mode self._pull = pull @@ -42,10 +46,10 @@ class Pin: if self._mode in (Pin.IN, Pin.OUT): # digital read if val is None: - return pico_u2if.gpio_get_pin(self.id) + return rp2040_u2if.gpio_get_pin(self.id) # digital write if val in (Pin.LOW, Pin.HIGH): - pico_u2if.gpio_set_pin(self.id, val) + rp2040_u2if.gpio_set_pin(self.id, val) return None # nope raise ValueError("Invalid value for pin.") @@ -79,6 +83,10 @@ GP19 = Pin(19) GP20 = Pin(20) GP21 = Pin(21) GP22 = Pin(22) +GP23 = Pin(23) +GP24 = Pin(24) +GP25 = Pin(25) GP26 = Pin(26) GP27 = Pin(27) GP28 = Pin(28) +GP29 = Pin(29) diff --git a/src/adafruit_blinka/microcontroller/pico_u2if/pwmio.py b/src/adafruit_blinka/microcontroller/rp2040_u2if/pwmio.py similarity index 64% rename from src/adafruit_blinka/microcontroller/pico_u2if/pwmio.py rename to src/adafruit_blinka/microcontroller/rp2040_u2if/pwmio.py index f69d28e..3cbf5e4 100644 --- a/src/adafruit_blinka/microcontroller/pico_u2if/pwmio.py +++ b/src/adafruit_blinka/microcontroller/rp2040_u2if/pwmio.py @@ -1,12 +1,12 @@ -"""PWMOut Class for Pico u2if""" -from .pico_u2if import pico_u2if +"""PWMOut Class for RP2040s with u2if""" +from .rp2040_u2if import rp2040_u2if class PWMOut: - """Pulse Width Modulation Output Class""" + """Base Pulse Width Modulation Output Class""" def __init__(self, pin, *, frequency=500, duty_cycle=0, variable_frequency=False): - pico_u2if.pwm_configure( + rp2040_u2if.pwm_configure( pin, frequency=frequency, duty_cycle=duty_cycle, @@ -26,22 +26,22 @@ class PWMOut: def deinit(self): """Deinit PWM.""" - pico_u2if.pwm_deinit(self._pin) + rp2040_u2if.pwm_deinit(self._pin) @property def duty_cycle(self): """The PWM's output duty cycle, 16-bit.""" - return pico_u2if.pwm_get_duty_cycle(self._pin) + return rp2040_u2if.pwm_get_duty_cycle(self._pin) @duty_cycle.setter def duty_cycle(self, duty_cycle): - pico_u2if.pwm_set_duty_cycle(self._pin, duty_cycle) + rp2040_u2if.pwm_set_duty_cycle(self._pin, duty_cycle) @property def frequency(self): """The PWM's output frequency in Hertz.""" - return pico_u2if.pwm_get_frequency(self._pin) + return rp2040_u2if.pwm_get_frequency(self._pin) @frequency.setter def frequency(self, frequency): - pico_u2if.pwm_set_frequency(self._pin, frequency) + rp2040_u2if.pwm_set_frequency(self._pin, frequency) diff --git a/src/adafruit_blinka/microcontroller/pico_u2if/pico_u2if.py b/src/adafruit_blinka/microcontroller/rp2040_u2if/rp2040_u2if.py similarity index 93% rename from src/adafruit_blinka/microcontroller/pico_u2if/pico_u2if.py rename to src/adafruit_blinka/microcontroller/rp2040_u2if/rp2040_u2if.py index 687bfc0..6431f94 100644 --- a/src/adafruit_blinka/microcontroller/pico_u2if/pico_u2if.py +++ b/src/adafruit_blinka/microcontroller/rp2040_u2if/rp2040_u2if.py @@ -1,4 +1,4 @@ -"""Chip Definition for Pico with u2if firmware""" +"""Helper class for use with RP2040 running u2if firmware""" # https://github.com/execuc/u2if import os @@ -6,17 +6,14 @@ import time import hid # Use to set delay between reset and device reopen. if negative, don't reset at all -PICO_U2IF_RESET_DELAY = float(os.environ.get("PICO_U2IF_RESET_DELAY", 1)) +RP2040_U2IF_RESET_DELAY = float(os.environ.get("RP2040_U2IF_RESET_DELAY", 1)) # pylint: disable=import-outside-toplevel,too-many-branches,too-many-statements # pylint: disable=too-many-arguments,too-many-function-args, too-many-public-methods -class Pico_u2if: - """MCP2221 Device Class Definition""" - - VID = 0xCAFE - PID = 0x4005 +class RP2040_u2if: + """Helper class for use with RP2040 running u2if firmware""" # MISC RESP_OK = 0x01 @@ -71,10 +68,10 @@ class Pico_u2if: PWM_GET_DUTY_NS = 0x37 def __init__(self): - self._hid = hid.device() - self._hid.open(Pico_u2if.VID, Pico_u2if.PID) - if PICO_U2IF_RESET_DELAY >= 0: - self._reset() + self._vid = None + self._pid = None + self._hid = None + self._opened = False self._i2c_index = None self._spi_index = None self._serial = None @@ -94,16 +91,32 @@ class Pico_u2if: def _reset(self): self._hid_xfer(bytes([self.SYS_RESET]), False) - time.sleep(PICO_U2IF_RESET_DELAY) + time.sleep(RP2040_U2IF_RESET_DELAY) start = time.monotonic() while time.monotonic() - start < 5: try: - self._hid.open(Pico_u2if.VID, Pico_u2if.PID) + self._hid.open(self._vid, self._pid) except OSError: time.sleep(0.1) continue return - raise OSError("Pico open error.") + raise OSError("RP2040 u2if open error.") + + # ---------------------------------------------------------------- + # MISC + # ---------------------------------------------------------------- + def open(self, vid, pid): + """Open HID interface for given USB VID and PID.""" + + if self._opened: + return + self._vid = vid + self._pid = pid + self._hid = hid.device() + self._hid.open(self._vid, self._pid) + if RP2040_U2IF_RESET_DELAY >= 0: + self._reset() + self._opened = True # ---------------------------------------------------------------- # GPIO @@ -369,7 +382,7 @@ class Pico_u2if: ports = serial.tools.list_ports.comports() for port in ports: - if port.vid == self.VID and port.pid == self.PID: + if port.vid == self._vid and port.pid == self._pid: self._serial = serial.Serial(port.device) break if self._serial is None: @@ -409,7 +422,6 @@ class Pico_u2if: "Neopixel write error : too many pixel for the firmware." ) elif resp[2] == 0x02: - print(resp[0:10]) raise RuntimeError( "Neopixel write error : transfer already in progress." ) @@ -422,6 +434,7 @@ class Pico_u2if: self._serial.write([0]) self._serial.flush() # polling loop to wait for write complete? + time.sleep(0.1) resp = self._hid.read(64) while resp[0] != self.WS2812B_WRITE: resp = self._hid.read(64) @@ -489,4 +502,4 @@ class Pico_u2if: raise RuntimeError("PWM set duty cycle error.") -pico_u2if = Pico_u2if() +rp2040_u2if = RP2040_u2if() diff --git a/src/adafruit_blinka/microcontroller/rp2040_u2if/spi.py b/src/adafruit_blinka/microcontroller/rp2040_u2if/spi.py new file mode 100644 index 0000000..9e025f9 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/rp2040_u2if/spi.py @@ -0,0 +1,114 @@ +"""SPI Classes for RP2040s with u2if firmware""" +from .rp2040_u2if import rp2040_u2if + +# pylint: disable=protected-access, no-self-use +class SPI: + """SPI Base Class for RP2040 u2if""" + + MSB = 0 + + def __init__(self, index, *, baudrate=100000): + self._index = index + self._frequency = baudrate + rp2040_u2if.spi_set_port(self._index) + rp2040_u2if.spi_configure(self._frequency) + + # pylint: disable=too-many-arguments,unused-argument + def init( + self, + baudrate=1000000, + polarity=0, + phase=0, + bits=8, + firstbit=MSB, + sck=None, + mosi=None, + miso=None, + ): + """Initialize the Port""" + self._frequency = baudrate + rp2040_u2if.spi_set_port(self._index) + rp2040_u2if.spi_configure(self._frequency) + + # pylint: enable=too-many-arguments + + @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""" + rp2040_u2if.spi_write(buf, start=start, end=end) + + def readinto(self, buf, start=0, end=None, write_value=0): + """Read data from SPI and into the buffer""" + rp2040_u2if.spi_readinto(buf, start=start, end=end, write_value=write_value) + + # 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 + """ + rp2040_u2if.spi_write_readinto( + buffer_out, + buffer_in, + out_start=out_start, + out_end=out_end, + in_start=in_start, + in_end=in_end, + ) + + # pylint: enable=too-many-arguments + + +class SPI_Pico(SPI): + """SPI Class for Pico u2if""" + + def __init__(self, clock, *, baudrate=100000): + index = None + if clock.id == 18: + index = 0 + if clock.id == 10: + index = 1 + if index is None: + raise ValueError("No SPI port on specified pin.") + super().__init__(index, baudrate=baudrate) + + +class SPI_Feather(SPI): + """SPI Class for Feather u2if""" + + def __init__(self, clock, *, baudrate=100000): + index = None + if clock.id == 18: + index = 0 + if index is None: + raise ValueError("No SPI port on specified pin.") + super().__init__(index, baudrate=baudrate) + + +class SPI_QTPY(SPI): + """SPI Class for QT Py u2if""" + + def __init__(self, clock, *, baudrate=100000): + index = None + if clock.id == 6: + index = 0 + if index is None: + raise ValueError("No SPI port on specified pin.") + super().__init__(index, baudrate=baudrate) + + +class SPI_ItsyBitsy(SPI): + """SPI Class for ItsyBitsy u2if""" + + def __init__(self, clock, *, baudrate=100000): + index = None + if clock.id == 18: + index = 0 + if index is None: + raise ValueError("No SPI port on specified pin.") + super().__init__(index, baudrate=baudrate) diff --git a/src/analogio.py b/src/analogio.py index 04d3afc..0016505 100644 --- a/src/analogio.py +++ b/src/analogio.py @@ -30,6 +30,20 @@ elif detector.chip.STM32MP157: elif "sphinx" in sys.modules: pass elif detector.board.pico_u2if: - from adafruit_blinka.microcontroller.pico_u2if.analogio import AnalogIn + from adafruit_blinka.microcontroller.rp2040_u2if.analogio import ( + AnalogIn_Pico as AnalogIn, + ) +elif detector.board.feather_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.analogio import ( + AnalogIn_Feather as AnalogIn, + ) +elif detector.board.qtpy_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.analogio import ( + AnalogIn_QTPY as AnalogIn, + ) +elif detector.board.itsybitsy_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.analogio import ( + AnalogIn_ItsyBitsy as AnalogIn, + ) else: raise NotImplementedError("analogio not supported for this board.") diff --git a/src/board.py b/src/board.py index 0c8a645..eb5e7d9 100755 --- a/src/board.py +++ b/src/board.py @@ -227,6 +227,18 @@ elif board_id == ap_board.NANOPI_DUO2: elif board_id == ap_board.PICO_U2IF: from adafruit_blinka.board.pico_u2if import * +elif board_id == ap_board.FEATHER_U2IF: + from adafruit_blinka.board.feather_u2if import * + +elif board_id == ap_board.QTPY_U2IF: + from adafruit_blinka.board.qtpy_u2if import * + +elif board_id == ap_board.ITSYBITSY_U2IF: + from adafruit_blinka.board.itsybitsy_u2if import * + +elif board_id == ap_board.QT2040_TRINKEY_U2IF: + from adafruit_blinka.board.qt2040_trinkey_u2if import * + elif "sphinx" in sys.modules: pass diff --git a/src/busio.py b/src/busio.py index 11c6341..3057e52 100755 --- a/src/busio.py +++ b/src/busio.py @@ -18,7 +18,7 @@ from adafruit_blinka import Enum, Lockable, agnostic from adafruit_blinka.agnostic import board_id, detector # pylint: disable=import-outside-toplevel,too-many-branches,too-many-statements -# pylint: disable=too-many-arguments,too-many-function-args,consider-using-with +# pylint: disable=too-many-arguments,too-many-function-args,consider-using-with,too-many-return-statements class I2C(Lockable): @@ -54,7 +54,33 @@ class I2C(Lockable): self._i2c = _I2C(frequency=frequency) return if detector.board.pico_u2if: - from adafruit_blinka.microcontroller.pico_u2if.i2c import I2C as _I2C + from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_Pico as _I2C + + self._i2c = _I2C(scl, sda, frequency=frequency) + return + if detector.board.feather_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.i2c import ( + I2C_Feather as _I2C, + ) + + self._i2c = _I2C(scl, sda, frequency=frequency) + return + if detector.board.qtpy_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.i2c import I2C_QTPY as _I2C + + self._i2c = _I2C(scl, sda, frequency=frequency) + return + if detector.board.itsybitsy_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.i2c import ( + I2C_ItsyBitsy as _I2C, + ) + + self._i2c = _I2C(scl, sda, frequency=frequency) + return + if detector.board.qt2040_trinkey_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.i2c import ( + I2C_QT2040_Trinkey as _I2C, + ) self._i2c = _I2C(scl, sda, frequency=frequency) return @@ -192,7 +218,29 @@ class SPI(Lockable): self._pins = (SCK, MOSI, MISO) return if detector.board.pico_u2if: - from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI + from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI + + self._spi = _SPI(clock) # this is really all that's needed + self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock + return + if detector.board.feather_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.spi import ( + SPI_Feather as _SPI, + ) + + self._spi = _SPI(clock) # this is really all that's needed + self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock + return + if detector.board.itsybitsy_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.spi import ( + SPI_ItsyBitsy as _SPI, + ) + + self._spi = _SPI(clock) # this is really all that's needed + self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock + return + if detector.board.qtpy_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI self._spi = _SPI(clock) # this is really all that's needed self._pins = (clock, clock, clock) # will determine MOSI/MISO from clock @@ -301,7 +349,17 @@ class SPI(Lockable): elif detector.board.any_lubancat and detector.chip.id == ap_chip.IMX6ULL: from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI elif detector.board.pico_u2if: - from adafruit_blinka.microcontroller.pico_u2if.spi import SPI as _SPI + from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_Pico as _SPI + elif detector.board.feather_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.spi import ( + SPI_Feather as _SPI, + ) + elif detector.board.itsybitsy_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.spi import ( + SPI_ItsyBitsy as _SPI, + ) + elif detector.board.qtpy_u2if: + from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI elif detector.chip.id == ap_chip.RP2040: from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI else: diff --git a/src/digitalio.py b/src/digitalio.py index eef0015..4237bac 100755 --- a/src/digitalio.py +++ b/src/digitalio.py @@ -82,7 +82,14 @@ elif detector.chip.H6: elif detector.chip.H616: from adafruit_blinka.microcontroller.allwinner.h616.pin import Pin elif detector.board.pico_u2if: - from adafruit_blinka.microcontroller.pico_u2if.pin import Pin + from adafruit_blinka.microcontroller.rp2040_u2if.pin import Pin +elif ( + detector.board.feather_u2if + or detector.board.qtpy_u2if + or detector.board.itsybitsy_u2if + or detector.board.qt2040_trinkey_u2if +): + from adafruit_blinka.microcontroller.rp2040_u2if.pin import Pin from adafruit_blinka import Enum, ContextManaged diff --git a/src/microcontroller/pin.py b/src/microcontroller/pin.py index 34f7b4a..7b945a0 100755 --- a/src/microcontroller/pin.py +++ b/src/microcontroller/pin.py @@ -81,6 +81,6 @@ elif chip_id == ap_chip.STM32MP157: elif chip_id == ap_chip.MT8167: from adafruit_blinka.microcontroller.mt8167.pin import * elif chip_id == ap_chip.PICO_U2IF: - from adafruit_blinka.microcontroller.pico_u2if.pin import * + from adafruit_blinka.microcontroller.rp2040_u2if.pin import * else: raise NotImplementedError("Microcontroller not supported: ", chip_id) diff --git a/src/neopixel_write.py b/src/neopixel_write.py index 00ffa0b..2097c84 100644 --- a/src/neopixel_write.py +++ b/src/neopixel_write.py @@ -15,7 +15,14 @@ from adafruit_blinka.agnostic import detector if detector.board.any_raspberry_pi: from adafruit_blinka.microcontroller.bcm283x import neopixel as _neopixel elif detector.board.pico_u2if: - from adafruit_blinka.microcontroller.pico_u2if import neopixel as _neopixel + from adafruit_blinka.microcontroller.rp2040_u2if import neopixel as _neopixel +elif ( + detector.board.feather_u2if + or detector.board.qtpy_u2if + or detector.board.itsybitsy_u2if + or detector.board.qt2040_trinkey_u2if +): + from adafruit_blinka.microcontroller.rp2040_u2if import neopixel as _neopixel elif "sphinx" in sys.modules: pass else: diff --git a/src/pwmio.py b/src/pwmio.py index dbb8bb7..f598058 100644 --- a/src/pwmio.py +++ b/src/pwmio.py @@ -30,7 +30,14 @@ elif detector.board.greatfet_one: elif detector.board.any_lubancat: from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut elif detector.board.pico_u2if: - from adafruit_blinka.microcontroller.pico_u2if.pwmio import PWMOut + from adafruit_blinka.microcontroller.rp2040_u2if.pwmio import PWMOut +elif ( + detector.board.feather_u2if + or detector.board.qtpy_u2if + or detector.board.itsybitsy_u2if + or detector.board.qt2040_trinkey_u2if +): + from adafruit_blinka.microcontroller.rp2040_u2if.pwmio import PWMOut elif "sphinx" in sys.modules: pass else: