add support for Radxa-X4 via U2IF

This commit is contained in:
Bernhard Bablok 2025-06-14 12:25:55 +02:00
parent 8f45d6cbc5
commit e6c2e68e15
7 changed files with 182 additions and 0 deletions

View file

@ -0,0 +1,117 @@
# SPDX-FileCopyrightText: 2025 Bernhard Bablok
#
# Copied and adapted from pico_u2if.py
# Copyright: 2021 Melissa LeBlanc-Williams for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""Pin definitions for the Raspberry Pi Pico running u2if firmware"""
from adafruit_blinka.microcontroller.rp2040_u2if import pin
# Pico names
GP0 = pin.GP0
GP1 = pin.GP1
GP2 = pin.GP2
GP3 = pin.GP3
GP4 = pin.GP4
GP5 = pin.GP5
GP6 = pin.GP6
GP7 = pin.GP7
GP8 = pin.GP8
GP9 = pin.GP9
GP10 = pin.GP10
GP11 = pin.GP11
GP12 = pin.GP12
GP13 = pin.GP13
GP14 = pin.GP14
GP15 = pin.GP15
GP16 = pin.GP16
GP17 = pin.GP17
GP18 = pin.GP18
GP19 = pin.GP19
GP20 = pin.GP20
GP21 = pin.GP21
GP22 = pin.GP22
GP23 = pin.GP23
GP24 = pin.GP24
GP25 = pin.GP25
GP26 = pin.GP26
GP27 = pin.GP27
GP28 = pin.GP28
GP29 = pin.GP29
# Pi names left side (top down)
GPIO2 = GP28
GPIO3 = GP29
GPIO4 = GP4
GPIO17 = GP5
GPIO27 = GP6
GPIO22 = GP3
GPIO10 = GP11
GPIO9 = GP8
GPIO11 = GP10
GPIO0 = GP16
GPIO5 = GP7
GPIO6 = GP12
GPIO13 = GP13
GPIO19 = GP15
GPIO26 = GP14
# right side (top down)
GPIO14 = GP20
GPIO15 = GP21
GPIO18 = GP23
GPIO23 = GP22
GPIO24 = GP27
GPIO25 = GP24
GPIO8 = GP9
GPIO7 = GP18
GPIO1 = GP17
GPIO12 = GP19
GPIO16 = GP26
GPIO20 = GP2
GPIO21 = GP25
# specials (INT: internal connection to N100-chip, EXT: on GPIO-pins)
UART_TX_INT = GP0
UART_RX_INT = GP1
UART_RX_EXT = GP20 # GPIO14
UART_RX_EXT = GP21 # GPIO15
ADC0 = GP26
ADC1 = GP27
ADC2 = GP28
ADC3 = GP29
PWM0 = GPIO12
PWM1 = GPIO13
# Pi defaults (I2C0 is also mapped to the ID-pins GPIO0/GPIO1 aka GP16/GP17)
SDA = SDA0 = GP28 # GPIO2
SCL = SCL0 = GP29 # GPIO3
# other choices have more conflicts
SDA1 = GP18
SCL1 = GP19
# Pico-SPI0 (Radxa-X4 does not map Pi-SPI1)
SCLK0 = SCK0 = GP6
MOSI0 = GP3
MISO0 = GP4
CE0 = GPIO8
CE1 = GPIO7
# Pi (SPI0) defaults (Radxa-X4 maps Pi-SPI0 to Pico-SPI1)
SCLK = SCK = SCLK1 = SCK1 = GP10
MOSI = MOSI1 = GP11
MISO = MISO1 = GP8
# access u2if via pin instance to open for specifc VID/PID
# pylint:disable = protected-access
pin.GP0._u2if_open_hid(0xCAFF, 0x4005)

View file

@ -70,3 +70,12 @@ class AnalogIn_ItsyBitsy(AnalogIn):
if pin.id not in (26, 27, 28):
raise ValueError("Pin does not support ADC.")
super().__init__(pin)
class AnalogIn_Radxa_X4(AnalogIn):
"""AnalogIn Base Class for Radxa X4 u2if"""
def __init__(self, pin):
if pin.id not in (26, 27, 28, 29):
raise ValueError("Pin does not support ADC.")
super().__init__(pin)

View file

@ -199,3 +199,19 @@ class I2C_KB2040(I2C):
self._index = index
super().__init__(index, frequency=frequency)
class I2C_Radxa_X4(I2C):
"""I2C Class for Radxa X4 u2if"""
def __init__(self, scl, sda, *, frequency=100000):
index = None
if scl.id == 29 and sda.id == 28:
index = 0
if scl.id == 19 and sda.id == 18:
index = 1
if index is None:
raise ValueError("I2C not found on specified pins.")
self._index = index
super().__init__(index, frequency=frequency)

View file

@ -178,3 +178,17 @@ class SPI_KB2040(SPI):
if index is None:
raise ValueError("No SPI port on specified pin.")
super().__init__(index, baudrate=baudrate)
class SPI_Radxa_X4(SPI):
"""SPI Class for Radxa X4 u2if"""
def __init__(self, clock, *, baudrate=100000):
index = None
if clock.id == 6:
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)

View file

@ -66,6 +66,10 @@ elif detector.board.itsybitsy_u2if:
from adafruit_blinka.microcontroller.rp2040_u2if.analogio import (
AnalogIn_ItsyBitsy as AnalogIn,
)
elif detector.board.radxa_x4_u2if:
from adafruit_blinka.microcontroller.rp2040_u2if.analogio import (
AnalogIn_Radxa_X4 as AnalogIn,
)
elif detector.board.OS_AGNOSTIC_BOARD:
from adafruit_blinka.microcontroller.generic_agnostic_board.analogio import AnalogIn
from adafruit_blinka.microcontroller.generic_agnostic_board.analogio import (

View file

@ -440,6 +440,9 @@ elif board_id == ap_board.WALNUT_PI_1B:
elif board_id == ap_board.RP2040_ONE_U2IF:
from adafruit_blinka.board.rp2040_one_u2if import *
elif board_id == ap_board.RADXA_X4_U2IF:
from adafruit_blinka.board.radxa_x4_u2if import *
elif board_id == ap_board.OS_AGNOSTIC_BOARD:
from adafruit_blinka.board.generic_agnostic_board import *

View file

@ -131,6 +131,13 @@ class I2C(Lockable):
I2C_KB2040 as _I2C,
)
self._i2c = _I2C(scl, sda, frequency=frequency)
return
if detector.board.radxa_x4_u2if:
from adafruit_blinka.microcontroller.rp2040_u2if.i2c import (
I2C_Radxa_X4 as _I2C,
)
self._i2c = _I2C(scl, sda, frequency=frequency)
return
if detector.chip.id == ap_chip.RP2040:
@ -341,6 +348,14 @@ class SPI(Lockable):
SPI_KB2040 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.radxa_x4_u2if:
from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
SPI_Radxa_X4 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
@ -442,6 +457,10 @@ class SPI(Lockable):
)
elif detector.board.qtpy_u2if:
from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
elif detector.board.radxa_x4_u2if:
from adafruit_blinka.microcontroller.rp2040_u2if.spi import (
SPI_Radxa_X4 as _SPI,
)
elif detector.chip.id == ap_chip.RP2040:
from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
elif detector.board.any_siemens_iot2000: