Skip to content

Commit e95562e

Browse files
authored
Merge pull request #867 from DarkMechanikum/main
Added support of Starfive JH7110 chip and Starfive VisionFive2 board
2 parents 322e03f + 363cea8 commit e95562e

File tree

11 files changed

+344
-0
lines changed

11 files changed

+344
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""Starfive boards defenition"""
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""Starfive VisionFive2 board config"""
5+
from adafruit_blinka.microcontroller.starfive.JH7110 import pin
6+
7+
8+
D7 = pin.D7
9+
D11 = pin.D11
10+
D12 = pin.D12
11+
D13 = pin.D13
12+
D15 = pin.D15
13+
D16 = pin.D16
14+
D18 = pin.D18
15+
D22 = pin.D22
16+
D24 = pin.D24
17+
D26 = pin.D26
18+
D27 = pin.D27
19+
D28 = pin.D28
20+
D29 = pin.D29
21+
D31 = pin.D31
22+
D35 = pin.D35
23+
D36 = pin.D36
24+
D37 = pin.D37
25+
D38 = pin.D38
26+
D40 = pin.D40
27+
# I2C
28+
SDA = pin.I2C_SDA
29+
SCL = pin.I2C_SCL
30+
31+
# SPI
32+
MISO = pin.SPI_MISO
33+
MOSI = pin.SPI_MOSI
34+
SCLK = pin.SPI_SCLK
35+
36+
# UART
37+
UART_TX = pin.UART_TX
38+
UART_RX = pin.UART_RX
39+
40+
# PWM
41+
PWM1 = pin.PWM1
42+
PWM2 = pin.PWM2
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""Definition for the StarFive JH7110 chip"""
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""A Pin class for use with StarFive JH7110."""
5+
6+
import VisionFive.gpio as GPIO
7+
8+
GPIO.setmode(GPIO.BOARD)
9+
10+
11+
class Pin:
12+
"""Pins don't exist in CPython so...lets make our own!"""
13+
14+
IN = 0
15+
OUT = 1
16+
LOW = 0
17+
HIGH = 1
18+
PULL_NONE = 0
19+
PULL_UP = 1
20+
PULL_DOWN = 2
21+
22+
id = None
23+
_value = LOW
24+
_mode = IN
25+
26+
def __init__(self, number):
27+
self.id = number
28+
29+
def __repr__(self):
30+
return str(self.id)
31+
32+
def __eq__(self, other):
33+
return self.id == other
34+
35+
def init(self, mode=IN, pull=None):
36+
"""Initialize the Pin"""
37+
print(self.id)
38+
if mode is not None:
39+
if mode == self.IN:
40+
self._mode = self.IN
41+
GPIO.setup(self.id, GPIO.IN)
42+
elif mode == self.OUT:
43+
self._mode = self.OUT
44+
GPIO.setup(self.id, GPIO.OUT)
45+
else:
46+
raise RuntimeError("Invalid mode for pin: %s" % self.id)
47+
if pull is not None:
48+
if self._mode != self.IN:
49+
raise RuntimeError("Cannot set pull resistor on output")
50+
if pull == self.PULL_UP:
51+
GPIO.setup(self.id, GPIO.IN, pull_up_down=GPIO.PUD_UP)
52+
elif pull == self.PULL_DOWN:
53+
GPIO.setup(self.id, GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
54+
else:
55+
raise RuntimeError("Invalid pull for pin: %s" % self.id)
56+
57+
def value(self, val=None):
58+
"""Set or return the Pin Value"""
59+
if val is not None:
60+
if val == self.LOW:
61+
self._value = val
62+
GPIO.output(self.id, val)
63+
elif val == self.HIGH:
64+
self._value = val
65+
GPIO.output(self.id, val)
66+
else:
67+
raise RuntimeError("Invalid value for pin")
68+
return None
69+
return GPIO.input(self.id)
70+
71+
72+
D7 = Pin(7)
73+
D11 = Pin(11)
74+
D12 = Pin(12)
75+
D13 = Pin(13)
76+
D15 = Pin(15)
77+
D16 = Pin(16)
78+
D18 = Pin(18)
79+
D22 = Pin(22)
80+
D24 = Pin(24)
81+
D26 = Pin(26)
82+
D27 = Pin(27)
83+
D28 = Pin(28)
84+
D29 = Pin(29)
85+
D31 = Pin(31)
86+
D35 = Pin(35)
87+
D36 = Pin(36)
88+
D37 = Pin(37)
89+
D38 = Pin(38)
90+
D40 = Pin(40)
91+
# I2C
92+
I2C_SDA = Pin(3)
93+
I2C_SCL = Pin(5)
94+
95+
# SPI
96+
SPI_MISO = Pin(21)
97+
SPI_MOSI = Pin(19)
98+
SPI_SCLK = Pin(23)
99+
100+
# UART
101+
UART_TX = Pin(8)
102+
UART_RX = Pin(10)
103+
104+
# PWM, does not support pwmio
105+
PWM1 = Pin(32)
106+
PWM2 = Pin(33)
107+
108+
# ordered as i2cId, SCL, SDA
109+
i2cPorts = ((0, I2C_SCL, I2C_SDA),)
110+
111+
# ordered as spiId, sckId, mosiId, misoId
112+
spiPorts = ((0, SPI_SCLK, SPI_MOSI, SPI_MISO),)
113+
114+
# ordered as uartId, txId, rxId
115+
uartPorts = ((0, UART_TX, UART_RX),)
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""Custom PWMOut Wrapper for VisionFive.GPIO PWM Class"""
5+
6+
import VisionFive.gpio as GPIO
7+
8+
GPIO.setmode(GPIO.BOARD)
9+
GPIO.setwarnings(False)
10+
11+
12+
# pylint: disable=unnecessary-pass
13+
class PWMError(IOError):
14+
"""Base class for PWM errors."""
15+
16+
pass
17+
18+
19+
# pylint: enable=unnecessary-pass
20+
21+
22+
class PWMOut:
23+
"""Pulse Width Modulation Output Class"""
24+
25+
def __init__(self, pin, *, frequency=500, duty_cycle=0, variable_frequency=False):
26+
self._pwmpin = None
27+
self._period = 0
28+
self._open(pin, duty_cycle, frequency, variable_frequency)
29+
30+
def __del__(self):
31+
self.deinit()
32+
33+
def __enter__(self):
34+
return self
35+
36+
def __exit__(self, t, value, traceback):
37+
self.deinit()
38+
39+
def _open(self, pin, duty=0, freq=500, variable_frequency=True):
40+
self._pin = pin
41+
GPIO.setup(pin.id, GPIO.OUT)
42+
self._pwmpin = GPIO.PWM(pin.id, freq)
43+
44+
if variable_frequency:
45+
print("Variable Frequency is not supported, continuing without it...")
46+
47+
# set frequency
48+
self.frequency = freq
49+
# set duty
50+
self.duty_cycle = duty
51+
52+
self.enabled = True
53+
54+
def deinit(self):
55+
"""Deinit the PWM."""
56+
if self._pwmpin is not None:
57+
self._pwmpin.stop()
58+
GPIO.cleanup(self._pin.id)
59+
self._pwmpin = None
60+
61+
def _is_deinited(self):
62+
if self._pwmpin is None:
63+
raise ValueError(
64+
"Object has been deinitialize and can no longer "
65+
"be used. Create a new object."
66+
)
67+
68+
@property
69+
def period(self):
70+
"""Get or set the PWM's output period in seconds.
71+
72+
Raises:
73+
PWMError: if an I/O or OS error occurs.
74+
TypeError: if value type is not int or float.
75+
76+
:type: int, float
77+
"""
78+
return 1.0 / self.frequency
79+
80+
@period.setter
81+
def period(self, period):
82+
if not isinstance(period, (int, float)):
83+
raise TypeError("Invalid period type, should be int or float.")
84+
85+
self.frequency = 1.0 / period
86+
87+
@property
88+
def duty_cycle(self):
89+
"""Get or set the PWM's output duty cycle which is the fraction of
90+
each pulse which is high. 16-bit
91+
92+
Raises:
93+
PWMError: if an I/O or OS error occurs.
94+
TypeError: if value type is not int or float.
95+
ValueError: if value is out of bounds of 0.0 to 1.0.
96+
97+
:type: int, float
98+
"""
99+
return int(self._duty_cycle * 65535)
100+
101+
@duty_cycle.setter
102+
def duty_cycle(self, duty_cycle):
103+
if not isinstance(duty_cycle, (int, float)):
104+
raise TypeError("Invalid duty cycle type, should be int or float.")
105+
106+
if not 0 <= duty_cycle <= 65535:
107+
raise ValueError("Invalid duty cycle value, should be between 0 and 65535")
108+
109+
duty_cycle = duty_cycle / 655.35
110+
self._duty_cycle = duty_cycle
111+
self._pwmpin.ChangeDutyCycle(round(self._duty_cycle))
112+
113+
@property
114+
def frequency(self):
115+
"""Get or set the PWM's output frequency in Hertz.
116+
117+
Raises:
118+
PWMError: if an I/O or OS error occurs.
119+
TypeError: if value type is not int or float.
120+
121+
:type: int, float
122+
"""
123+
124+
return self._frequency
125+
126+
@frequency.setter
127+
def frequency(self, frequency):
128+
if not isinstance(frequency, (int, float)):
129+
raise TypeError("Invalid frequency type, should be int or float.")
130+
131+
self._pwmpin.ChangeFrequency(round(frequency))
132+
self._frequency = frequency
133+
134+
@property
135+
def enabled(self):
136+
"""Get or set the PWM's output enabled state.
137+
138+
Raises:
139+
PWMError: if an I/O or OS error occurs.
140+
TypeError: if value type is not bool.
141+
142+
:type: bool
143+
"""
144+
return self._enabled
145+
146+
@enabled.setter
147+
def enabled(self, value):
148+
if not isinstance(value, bool):
149+
raise TypeError("Invalid enabled type, should be string.")
150+
151+
if value:
152+
self._pwmpin.start(round(self._duty_cycle * 100))
153+
else:
154+
self._pwmpin.stop()
155+
156+
self._enabled = value
157+
158+
# String representation
159+
def __str__(self):
160+
return "pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
161+
self._pin,
162+
self.frequency,
163+
self.duty_cycle,
164+
)
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# SPDX-FileCopyrightText: 2024 Vladimir Shtarev, Jetbrains Research
2+
#
3+
# SPDX-License-Identifier: MIT
4+
"""Custom PWMOut Wrapper for VisionFive.GPIO PWM Class"""

src/board.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
if board_id == ap_board.FEATHER_HUZZAH:
2727
from adafruit_blinka.board.feather_huzzah import *
2828

29+
elif board_id == ap_board.VISIONFIVE2:
30+
from adafruit_blinka.board.starfive.visionfive2 import *
31+
2932
elif board_id == ap_board.OLIMEX_LIME2:
3033
from adafruit_blinka.board.OLIMEX_LIME2 import *
3134

src/digitalio.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
from adafruit_blinka.microcontroller.am335x.pin import Pin
3030
elif detector.chip.AM65XX:
3131
from adafruit_blinka.microcontroller.am65xx.pin import Pin
32+
elif detector.chip.JH7110:
33+
from adafruit_blinka.microcontroller.starfive.JH7110.pin import Pin
3234
elif detector.chip.JH71X0:
3335
from adafruit_blinka.microcontroller.starfive.JH71x0.pin import Pin
3436
elif detector.chip.DRA74X:

src/microcontroller/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@ def delay_us(delay):
4949
from adafruit_blinka.microcontroller.am65xx import *
5050
elif chip_id == ap_chip.JH71X0:
5151
from adafruit_blinka.microcontroller.starfive.JH71x0 import *
52+
elif chip_id == ap_chip.JH7110:
53+
from adafruit_blinka.microcontroller.starfive.JH7110 import *
5254
elif chip_id == ap_chip.SUN4I:
5355
from adafruit_blinka.microcontroller.allwinner.a20 import *
5456
elif chip_id == ap_chip.SUN7I:

src/microcontroller/pin.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
from adafruit_blinka.microcontroller.am65xx.pin import *
3535
elif chip_id == ap_chip.JH71X0:
3636
from adafruit_blinka.microcontroller.starfive.JH71x0.pin import *
37+
elif chip_id == ap_chip.JH7110:
38+
from adafruit_blinka.microcontroller.starfive.JH7110.pin import *
3739
elif chip_id == ap_chip.SUN4I:
3840
from adafruit_blinka.microcontroller.allwinner.a20.pin import *
3941
elif chip_id == ap_chip.SUN7I:

0 commit comments

Comments
 (0)