From: Melissa LeBlanc-Williams Date: Wed, 10 Jul 2024 16:00:28 +0000 (-0700) Subject: Merge pull request #867 from DarkMechanikum/main X-Git-Tag: 8.46.0~2 X-Git-Url: https://git.ayoreis.com/Adafruit_Blinka-hackapet.git/commitdiff_plain/e95562eae7a3b5120b069fbee42c8e61a017628d?hp=322e03f883e36912f9ee6fa7c6559d622f9e7db0 Merge pull request #867 from DarkMechanikum/main Added support of Starfive JH7110 chip and Starfive VisionFive2 board --- diff --git a/src/adafruit_blinka/board/starfive/__init__.py b/src/adafruit_blinka/board/starfive/__init__.py new file mode 100644 index 0000000..19e236a --- /dev/null +++ b/src/adafruit_blinka/board/starfive/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research +# +# SPDX-License-Identifier: MIT +"""Starfive boards defenition""" diff --git a/src/adafruit_blinka/board/starfive/visionfive2.py b/src/adafruit_blinka/board/starfive/visionfive2.py new file mode 100644 index 0000000..feafb3b --- /dev/null +++ b/src/adafruit_blinka/board/starfive/visionfive2.py @@ -0,0 +1,42 @@ +# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research +# +# SPDX-License-Identifier: MIT +"""Starfive VisionFive2 board config""" +from adafruit_blinka.microcontroller.starfive.JH7110 import pin + + +D7 = pin.D7 +D11 = pin.D11 +D12 = pin.D12 +D13 = pin.D13 +D15 = pin.D15 +D16 = pin.D16 +D18 = pin.D18 +D22 = pin.D22 +D24 = pin.D24 +D26 = pin.D26 +D27 = pin.D27 +D28 = pin.D28 +D29 = pin.D29 +D31 = pin.D31 +D35 = pin.D35 +D36 = pin.D36 +D37 = pin.D37 +D38 = pin.D38 +D40 = pin.D40 +# I2C +SDA = pin.I2C_SDA +SCL = pin.I2C_SCL + +# SPI +MISO = pin.SPI_MISO +MOSI = pin.SPI_MOSI +SCLK = pin.SPI_SCLK + +# UART +UART_TX = pin.UART_TX +UART_RX = pin.UART_RX + +# PWM +PWM1 = pin.PWM1 +PWM2 = pin.PWM2 diff --git a/src/adafruit_blinka/microcontroller/starfive/JH7110/__init__.py b/src/adafruit_blinka/microcontroller/starfive/JH7110/__init__.py new file mode 100644 index 0000000..952d217 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/starfive/JH7110/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research +# +# SPDX-License-Identifier: MIT +"""Definition for the StarFive JH7110 chip""" diff --git a/src/adafruit_blinka/microcontroller/starfive/JH7110/pin.py b/src/adafruit_blinka/microcontroller/starfive/JH7110/pin.py new file mode 100644 index 0000000..023a40e --- /dev/null +++ b/src/adafruit_blinka/microcontroller/starfive/JH7110/pin.py @@ -0,0 +1,115 @@ +# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research +# +# SPDX-License-Identifier: MIT +"""A Pin class for use with StarFive JH7110.""" + +import VisionFive.gpio as GPIO + +GPIO.setmode(GPIO.BOARD) + + +class Pin: + """Pins don't exist in CPython so...lets make our own!""" + + IN = 0 + OUT = 1 + LOW = 0 + HIGH = 1 + PULL_NONE = 0 + PULL_UP = 1 + PULL_DOWN = 2 + + id = None + _value = LOW + _mode = IN + + def __init__(self, number): + self.id = number + + def __repr__(self): + return str(self.id) + + def __eq__(self, other): + return self.id == other + + def init(self, mode=IN, pull=None): + """Initialize the Pin""" + print(self.id) + if mode is not None: + if mode == self.IN: + self._mode = self.IN + GPIO.setup(self.id, GPIO.IN) + elif mode == self.OUT: + self._mode = self.OUT + GPIO.setup(self.id, GPIO.OUT) + else: + raise RuntimeError("Invalid mode for pin: %s" % self.id) + if pull is not None: + if self._mode != self.IN: + raise RuntimeError("Cannot set pull resistor on output") + if pull == self.PULL_UP: + GPIO.setup(self.id, GPIO.IN, pull_up_down=GPIO.PUD_UP) + elif pull == self.PULL_DOWN: + GPIO.setup(self.id, GPIO.IN, pull_up_down=GPIO.PUD_DOWN) + else: + raise RuntimeError("Invalid pull for pin: %s" % self.id) + + def value(self, val=None): + """Set or return the Pin Value""" + if val is not None: + if val == self.LOW: + self._value = val + GPIO.output(self.id, val) + elif val == self.HIGH: + self._value = val + GPIO.output(self.id, val) + else: + raise RuntimeError("Invalid value for pin") + return None + return GPIO.input(self.id) + + +D7 = Pin(7) +D11 = Pin(11) +D12 = Pin(12) +D13 = Pin(13) +D15 = Pin(15) +D16 = Pin(16) +D18 = Pin(18) +D22 = Pin(22) +D24 = Pin(24) +D26 = Pin(26) +D27 = Pin(27) +D28 = Pin(28) +D29 = Pin(29) +D31 = Pin(31) +D35 = Pin(35) +D36 = Pin(36) +D37 = Pin(37) +D38 = Pin(38) +D40 = Pin(40) +# I2C +I2C_SDA = Pin(3) +I2C_SCL = Pin(5) + +# SPI +SPI_MISO = Pin(21) +SPI_MOSI = Pin(19) +SPI_SCLK = Pin(23) + +# UART +UART_TX = Pin(8) +UART_RX = Pin(10) + +# PWM, does not support pwmio +PWM1 = Pin(32) +PWM2 = Pin(33) + +# ordered as i2cId, SCL, SDA +i2cPorts = ((0, I2C_SCL, I2C_SDA),) + +# ordered as spiId, sckId, mosiId, misoId +spiPorts = ((0, SPI_SCLK, SPI_MOSI, SPI_MISO),) + +# ordered as uartId, txId, rxId +uartPorts = ((0, UART_TX, UART_RX),) diff --git a/src/adafruit_blinka/microcontroller/starfive/JH7110/pwmio/PWMOut.py b/src/adafruit_blinka/microcontroller/starfive/JH7110/pwmio/PWMOut.py new file mode 100644 index 0000000..efd1d40 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/starfive/JH7110/pwmio/PWMOut.py @@ -0,0 +1,164 @@ +# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research +# +# SPDX-License-Identifier: MIT +"""Custom PWMOut Wrapper for VisionFive.GPIO PWM Class""" + +import VisionFive.gpio as GPIO + +GPIO.setmode(GPIO.BOARD) +GPIO.setwarnings(False) + + +# pylint: disable=unnecessary-pass +class PWMError(IOError): + """Base class for PWM errors.""" + + pass + + +# pylint: enable=unnecessary-pass + + +class PWMOut: + """Pulse Width Modulation Output Class""" + + def __init__(self, pin, *, frequency=500, duty_cycle=0, variable_frequency=False): + self._pwmpin = None + self._period = 0 + self._open(pin, duty_cycle, frequency, variable_frequency) + + def __del__(self): + self.deinit() + + def __enter__(self): + return self + + def __exit__(self, t, value, traceback): + self.deinit() + + def _open(self, pin, duty=0, freq=500, variable_frequency=True): + self._pin = pin + GPIO.setup(pin.id, GPIO.OUT) + self._pwmpin = GPIO.PWM(pin.id, freq) + + if variable_frequency: + print("Variable Frequency is not supported, continuing without it...") + + # set frequency + self.frequency = freq + # set duty + self.duty_cycle = duty + + self.enabled = True + + def deinit(self): + """Deinit the PWM.""" + if self._pwmpin is not None: + self._pwmpin.stop() + GPIO.cleanup(self._pin.id) + self._pwmpin = None + + def _is_deinited(self): + if self._pwmpin is None: + raise ValueError( + "Object has been deinitialize and can no longer " + "be used. Create a new object." + ) + + @property + def period(self): + """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 + """ + return 1.0 / self.frequency + + @period.setter + def period(self, period): + if not isinstance(period, (int, float)): + raise TypeError("Invalid period type, should be int or float.") + + self.frequency = 1.0 / period + + @property + def duty_cycle(self): + """Get or set the PWM's output duty cycle which is the fraction of + each pulse which is high. 16-bit + + 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 int(self._duty_cycle * 65535) + + @duty_cycle.setter + def duty_cycle(self, duty_cycle): + if not isinstance(duty_cycle, (int, float)): + raise TypeError("Invalid duty cycle type, should be int or float.") + + if not 0 <= duty_cycle <= 65535: + raise ValueError("Invalid duty cycle value, should be between 0 and 65535") + + duty_cycle = duty_cycle / 655.35 + self._duty_cycle = duty_cycle + self._pwmpin.ChangeDutyCycle(round(self._duty_cycle)) + + @property + def frequency(self): + """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 + """ + + return self._frequency + + @frequency.setter + def frequency(self, frequency): + if not isinstance(frequency, (int, float)): + raise TypeError("Invalid frequency type, should be int or float.") + + self._pwmpin.ChangeFrequency(round(frequency)) + self._frequency = frequency + + @property + def enabled(self): + """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 + """ + return self._enabled + + @enabled.setter + def enabled(self, value): + if not isinstance(value, bool): + raise TypeError("Invalid enabled type, should be string.") + + if value: + self._pwmpin.start(round(self._duty_cycle * 100)) + else: + self._pwmpin.stop() + + self._enabled = value + + # String representation + def __str__(self): + return "pin %s (freq=%f Hz, duty_cycle=%f%%)" % ( + self._pin, + self.frequency, + self.duty_cycle, + ) diff --git a/src/adafruit_blinka/microcontroller/starfive/JH7110/pwmio/__init__.py b/src/adafruit_blinka/microcontroller/starfive/JH7110/pwmio/__init__.py new file mode 100644 index 0000000..a041352 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/starfive/JH7110/pwmio/__init__.py @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research +# +# SPDX-License-Identifier: MIT +"""Custom PWMOut Wrapper for VisionFive.GPIO PWM Class""" diff --git a/src/board.py b/src/board.py index 667a234..599979b 100644 --- a/src/board.py +++ b/src/board.py @@ -26,6 +26,9 @@ from adafruit_blinka.agnostic import board_id, detector if board_id == ap_board.FEATHER_HUZZAH: from adafruit_blinka.board.feather_huzzah import * +elif board_id == ap_board.VISIONFIVE2: + from adafruit_blinka.board.starfive.visionfive2 import * + elif board_id == ap_board.OLIMEX_LIME2: from adafruit_blinka.board.OLIMEX_LIME2 import * diff --git a/src/digitalio.py b/src/digitalio.py index e215047..46f23a6 100644 --- a/src/digitalio.py +++ b/src/digitalio.py @@ -29,6 +29,8 @@ elif detector.chip.AM33XX: from adafruit_blinka.microcontroller.am335x.pin import Pin elif detector.chip.AM65XX: from adafruit_blinka.microcontroller.am65xx.pin import Pin +elif detector.chip.JH7110: + from adafruit_blinka.microcontroller.starfive.JH7110.pin import Pin elif detector.chip.JH71X0: from adafruit_blinka.microcontroller.starfive.JH71x0.pin import Pin elif detector.chip.DRA74X: diff --git a/src/microcontroller/__init__.py b/src/microcontroller/__init__.py index 0baf43d..036fbc9 100644 --- a/src/microcontroller/__init__.py +++ b/src/microcontroller/__init__.py @@ -49,6 +49,8 @@ elif chip_id == ap_chip.AM65XX: from adafruit_blinka.microcontroller.am65xx import * elif chip_id == ap_chip.JH71X0: from adafruit_blinka.microcontroller.starfive.JH71x0 import * +elif chip_id == ap_chip.JH7110: + from adafruit_blinka.microcontroller.starfive.JH7110 import * elif chip_id == ap_chip.SUN4I: from adafruit_blinka.microcontroller.allwinner.a20 import * elif chip_id == ap_chip.SUN7I: diff --git a/src/microcontroller/pin.py b/src/microcontroller/pin.py index adf92db..5872271 100644 --- a/src/microcontroller/pin.py +++ b/src/microcontroller/pin.py @@ -34,6 +34,8 @@ elif chip_id == ap_chip.AM65XX: from adafruit_blinka.microcontroller.am65xx.pin import * elif chip_id == ap_chip.JH71X0: from adafruit_blinka.microcontroller.starfive.JH71x0.pin import * +elif chip_id == ap_chip.JH7110: + from adafruit_blinka.microcontroller.starfive.JH7110.pin import * elif chip_id == ap_chip.SUN4I: from adafruit_blinka.microcontroller.allwinner.a20.pin import * elif chip_id == ap_chip.SUN7I: diff --git a/src/pwmio.py b/src/pwmio.py index 54d0091..6935ac1 100644 --- a/src/pwmio.py +++ b/src/pwmio.py @@ -46,6 +46,8 @@ elif detector.board.any_jetson_board: from adafruit_blinka.microcontroller.tegra.PWMOut import PWMOut elif detector.board.any_luckfox_pico_board: from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut +elif detector.board.any_starfive_id: + from adafruit_blinka.microcontroller.starfive.JH7110.pwmio import PWMOut elif detector.board.OS_AGNOSTIC_BOARD: from adafruit_blinka.microcontroller.generic_agnostic_board.PWMOut import PWMOut elif (