--- /dev/null
+"""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
+pin.GP0._u2if_open_hid(0x239A, 0x80F2)
-"""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
SCLK1 = SCK1 = GP10
MOSI1 = GP11
MISO1 = GP12
+
+# access u2if via pin instance to open for specifc VID/PID
+pin.GP0._u2if_open_hid(0xCAFE, 0x4005)
* Author(s): Carter Nelson
"""
from adafruit_blinka import ContextManaged
-from .pico_u2if import pico_u2if
+from .rp2040_u2if import rp2040_u2if
class AnalogIn(ContextManaged):
- """Analog Input Class"""
+ """AnalogIn Base Class for RP2040 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.")
self.pin_id = pin.id
- pico_u2if.adc_init_pin(self.pin_id)
+ rp2040_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
+ return rp2040_u2if.adc_get_value(self.pin_id) << 4
# pylint: disable=no-self-use
@value.setter
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)
-"""I2C Class for Pico u2if"""
-from .pico_u2if import pico_u2if
+"""I2C Classes for RP2040s with u2if firmware"""
+from .rp2040_u2if import rp2040_u2if
class I2C:
- """Custom I2C Class for Pico u2if"""
+ """I2C Base Class for RP2040 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.")
+ def __init__(self, index, *, frequency=100000):
self._index = index
- pico_u2if.i2c_set_port(self._index)
- pico_u2if.i2c_configure(frequency)
+ rp2040_u2if.i2c_set_port(self._index)
+ rp2040_u2if.i2c_configure(frequency)
def scan(self):
"""Perform an I2C Device Scan"""
- pico_u2if.i2c_set_port(self._index)
- return pico_u2if.i2c_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"""
- pico_u2if.i2c_set_port(self._index)
- pico_u2if.i2c_writeto(address, buffer, start=start, end=end)
+ 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"""
- pico_u2if.i2c_set_port(self._index)
- pico_u2if.i2c_readfrom_into(address, buffer, start=start, end=end)
+ rp2040_u2if.i2c_set_port(self._index)
+ rp2040_u2if.i2c_readfrom_into(address, buffer, start=start, end=end)
def writeto_then_readfrom(
self,
"""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(
+ rp2040_u2if.i2c_set_port(self._index)
+ rp2040_u2if.i2c_writeto_then_readfrom(
address,
buffer_out,
buffer_in,
)
# 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)
+
"""NeoPixel write for Pico u2if."""
-from .pico_u2if import pico_u2if
+from .rp2040_u2if import rp2040_u2if
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)
+
-"""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
self._mode = None
self._pull = None
+ 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
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
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.")
GP20 = Pin(20)
GP21 = Pin(21)
GP22 = Pin(22)
+GP24 = Pin(24)
+GP25 = Pin(25)
GP26 = Pin(26)
GP27 = Pin(27)
GP28 = Pin(28)
+GP29 = Pin(29)
-"""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,
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)
-"""Chip Definition for Pico with u2if firmware"""
+"""Helper class for use with RP2040 running u2if firmware"""
# https://github.com/execuc/u2if
import os
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
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._opened = False
self._i2c_index = None
self._spi_index = None
self._serial = None
self._neopixel_initialized = False
- self._uart_rx_buffer = None
+ # 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._i2c_index = None
+ # self._spi_index = None
+ # self._serial = None
+ # self._neopixel_initialized = False
+ # self._uart_rx_buffer = None
def _hid_xfer(self, report, response=True):
"""Perform HID Transfer"""
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):
+ 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
# ----------------------------------------------------------------
def neopixel_write(self, gpio, buf):
"""NeoPixel write."""
+ print("open serial")
# open serial (data is sent over this)
if self._serial is None:
import serial
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:
raise RuntimeError("Could not find Pico com port.")
+ print("init")
# init
if not self._neopixel_initialized:
# deinit any current setup
self._serial.reset_output_buffer()
+ print("write")
# write
# command is done over HID
remain_bytes = len(buf)
)
else:
raise RuntimeError("Neopixel write error.")
+ print("write 1")
# buffer is sent over serial
self._serial.write(buf)
# hack (see u2if)
+ print("write 2")
if len(buf) % 64 == 0:
self._serial.write([0])
self._serial.flush()
# polling loop to wait for write complete?
+ print("write 3")
+ time.sleep(0.1)
resp = self._hid.read(64)
+ print("write 4")
while resp[0] != self.WS2812B_WRITE:
resp = self._hid.read(64)
+ print("write 5")
if resp[1] != self.RESP_OK:
raise RuntimeError("Neopixel write (flush) error.")
if resp[1] != self.RESP_OK:
raise RuntimeError("PWM set duty cycle error.")
-
-pico_u2if = Pico_u2if()
+rp2040_u2if = RP2040_u2if()
-"""SPI Class for Pico u2if"""
-from .pico_u2if import pico_u2if
+"""SPI Classes for RP2040s with u2if firmware"""
+from .rp2040_u2if import rp2040_u2if
# pylint: disable=protected-access, no-self-use
class SPI:
- """Custom SPI Class for Pico u2if"""
+ """SPI Base Class for RP2040 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.")
+ def __init__(self, index, *, baudrate=100000):
self._index = index
self._frequency = baudrate
- pico_u2if.spi_set_port(self._index)
- pico_u2if.spi_configure(self._frequency)
+ rp2040_u2if.spi_set_port(self._index)
+ rp2040_u2if.spi_configure(self._frequency)
# pylint: disable=too-many-arguments,unused-argument
def init(
):
"""Initialize the Port"""
self._frequency = baudrate
- pico_u2if.spi_set_port(self._index)
- pico_u2if.spi_configure(self._frequency)
+ rp2040_u2if.spi_set_port(self._index)
+ rp2040_u2if.spi_configure(self._frequency)
# pylint: enable=too-many-arguments
def write(self, buf, start=0, end=None):
"""Write data from the buffer to SPI"""
- pico_u2if.spi_write(buf, start=start, end=end)
+ 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"""
- pico_u2if.spi_readinto(buf, start=start, end=end, write_value=write_value)
+ rp2040_u2if.spi_readinto(buf, start=start, end=end, write_value=write_value)
# pylint: disable=too-many-arguments
def write_readinto(
"""Perform a half-duplex write from buffer_out and then
read data into buffer_in
"""
- pico_u2if.spi_write_readinto(
+ rp2040_u2if.spi_write_readinto(
buffer_out,
buffer_in,
out_start=out_start,
)
# pylint: enable=too-many-arguments
+
+class SPI_Pico(SPI):
+
+ 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):
+
+ 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)
\ No newline at end of file
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
else:
raise NotImplementedError("analogio not supported for this board.")
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 "sphinx" in sys.modules:
pass
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
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
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.chip.id == ap_chip.RP2040:
from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
else:
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:
+ from adafruit_blinka.microcontroller.rp2040_u2if.pin import Pin
from adafruit_blinka import Enum, ContextManaged
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
+elif detector.board.pico_u2if or detector.board.feather_u2if:
+ from adafruit_blinka.microcontroller.rp2040_u2if import neopixel as _neopixel
elif "sphinx" in sys.modules:
pass
else:
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:
+ from adafruit_blinka.microcontroller.rp2040_u2if.pwmio import PWMOut
elif "sphinx" in sys.modules:
pass
else: