Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,5 @@ dmypy.json

# Pyre type checker
.pyre/

.DS_Store
4 changes: 2 additions & 2 deletions rockpi-quad/DEBIAN/control
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Package: rockpi-quad
Version: 0.3.1
Version: 0.4.0
Architecture: all
Maintainer: Radxa <[email protected]>
Depends: python3, python3-libgpiod, python3-pillow, python3-pip
Depends: python3, python3-dev, python3-libgpiod (>=2.0.0), python3-pillow, python3-pip, raspi-config, build-essential
Section: utils
Priority: optional
Homepage: https://github.com/radxa/rockpi-quad
Expand Down
4 changes: 2 additions & 2 deletions rockpi-quad/DEBIAN/postinst
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ model=$(tr -d '\0' </proc/device-tree/model)
case "$model" in
*"Raspberry Pi 4"*)
raspi-config nonint do_i2c 0
if ! grep -q "dtoverlay=pwm,pin=13,func=4" /boot/firmware/config.txt; then
echo "dtoverlay=pwm,pin=13,func=4" >> /boot/firmware/config.txt
if ! grep -q "dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4" /boot/config.txt; then
echo "dtoverlay=pwm-2chan,pin=12,func=4,pin2=13,func2=4" >> /boot/config.txt
fi
mv /usr/bin/rockpi-quad/env/rpi4.env /etc/rockpi-quad.env
checkReboot
Expand Down
10 changes: 5 additions & 5 deletions rockpi-quad/etc/rockpi-quad.conf
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
# and lv1 at 50% power, lv2 at 75% power, lv3 at 100% power.
# When the temperature is below lv0, the fan is turned off.
# You can change these values if necessary.
lv0 = 35
lv1 = 40
lv2 = 45
lv3 = 50
lv0 = 45
lv1 = 50
lv2 = 55
lv3 = 60

[key]
# You can customize the function of the key, currently available functions are
Expand All @@ -32,5 +32,5 @@ time = 10

[oled]
# Whether rotate the text of oled 180 degrees, whether use Fahrenheit
rotate = false
rotate = true
f-temp = false
6 changes: 3 additions & 3 deletions rockpi-quad/usr/bin/rockpi-quad/env/rpi4.env
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
SDA=SDA
SCL=SCL
OLED_RESET=D23
BUTTON_CHIP=0
BUTTON_CHIP=/dev/gpiochip0
BUTTON_LINE=17
PWMCHIP=0
PWM_FUN=1
PWM_FUN=0,1
HARDWARE_PWM=1
POLARITY=inversed
SATA_CHIP=0
SATA_CHIP=/dev/gpiochip0
SATA_LINE_1=25
SATA_LINE_2=26
30 changes: 17 additions & 13 deletions rockpi-quad/usr/bin/rockpi-quad/fan.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,13 @@


class Pwm:
def __init__(self, chip):
def __init__(self, chip, fun):
self.period_value = None
try:
int(chip)
chip = f'pwmchip{chip}'
except ValueError:
pass
fun = os.environ.get('PWM_FUN', '0')
self.filepath = f"/sys/class/pwm/{chip}/pwm{fun}/"
try:
with open(f"/sys/class/pwm/{chip}/export", 'w') as f:
Expand Down Expand Up @@ -51,17 +50,20 @@ def write(self, duty: float):


class Gpio:

def tr(self):
while True:
self.line.set_value(1)
self.request.set_value(1)
time.sleep(self.value[0])
self.line.set_value(0)
self.request.set_value(0)
time.sleep(self.value[1])

def __init__(self, period_s):
self.line = gpiod.Chip(os.environ['FAN_CHIP']).get_line(int(os.environ['FAN_LINE']))
self.line.request(consumer='fan', type=gpiod.LINE_REQ_DIR_OUT)
chip = gpiod.Chip(os.environ['FAN_CHIP'])
line = chip.get_line(int(os.environ['FAN_LINE']))
config = gpiod.LineRequest()
config.consumer = 'fan'
config.request_type = gpiod.LineRequest.DIRECTION_OUTPUT
self.request = line.request(config, default_vals=[0])
self.value = [period_s / 2, period_s / 2]
self.period_s = period_s
self.thread = threading.Thread(target=self.tr, daemon=True)
Expand Down Expand Up @@ -92,18 +94,20 @@ def get_dc(cache={}):
def change_dc(dc, cache={}):
if dc != cache.get('dc'):
cache['dc'] = dc
pin.write(dc)
for pin in pins:
pin.write(dc)


def running():
global pin
global pins
if os.environ['HARDWARE_PWM'] == '1':
chip = os.environ['PWMCHIP']
pin = Pwm(chip)
pin.period_us(40)
pin.enable(True)
pins = [Pwm(chip, fun) for fun in os.environ.get('PWM_FUN', '0').split(',')]
for pin in pins:
pin.period_us(40)
pin.enable(True)
else:
pin = Gpio(0.025)
pins = [Gpio(0.025)]
while True:
change_dc(get_dc())
time.sleep(1)
Expand Down
53 changes: 41 additions & 12 deletions rockpi-quad/usr/bin/rockpi-quad/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import traceback

import gpiod
from gpiod.line import Direction, Value
from configparser import ConfigParser
from collections import defaultdict, OrderedDict

Expand Down Expand Up @@ -53,7 +54,7 @@ def read_conf():

try:
cfg = ConfigParser()
cfg.read('/etc/rockpi-penta.conf')
cfg.read('/etc/rockpi-quad.conf')
# fan
conf['fan']['lv0'] = cfg.getfloat('fan', 'lv0')
conf['fan']['lv1'] = cfg.getfloat('fan', 'lv1')
Expand Down Expand Up @@ -99,15 +100,25 @@ def read_key(pattern, size):
LINE_NUMBER = os.environ['BUTTON_LINE']

s = ''
chip = gpiod.Chip(str(CHIP_NAME))
line = chip.get_line(int(LINE_NUMBER))
line.request(consumer='hat_button', type=gpiod.LINE_REQ_DIR_OUT)
line.set_value(1)
chip_path = str(CHIP_NAME)
line_num = int(LINE_NUMBER)

config = {
line_num: gpiod.LineSettings(
direction=Direction.INPUT # Corrected to INPUT for button reading
)
}
request = gpiod.request_lines(
chip_path,
consumer='hat_button',
config=config
)

while True:
s = s[-size:] + str(line.get_value())
s = s[-size:] + str(request.get_value(line_num).value) # Use .value to get 0 or 1
for t, p in pattern.items():
if p.match(s):
request.release()
return t
time.sleep(0.1)

Expand All @@ -130,6 +141,8 @@ def get_disk_info(cache={}):
info = {}
cmd = "df -h | awk '$NF==\"/\"{printf \"%s\", $5}'"
info['root'] = check_output(cmd)
cmd = "df -h | awk '$1==\"/dev/md0\"{printf \"%s\", $5}'"
info['raid'] = check_output(cmd)
for x in conf['disk']:
cmd = "df -Bg | awk '$1==\"/dev/{}\" {{printf \"%s\", $5}}'".format(x)
info[x] = check_output(cmd)
Expand Down Expand Up @@ -164,12 +177,28 @@ def get_func(key):


def disk_turn_on():
line1 = gpiod.Chip(os.environ['SATA_CHIP']).get_line(int(os.environ['SATA_LINE_1']))
line1.request(consumer='SATA_LINE_1', type=gpiod.LINE_REQ_DIR_OUT)
line1.set_value(1)
line2 = gpiod.Chip(os.environ['SATA_CHIP']).get_line(int(os.environ['SATA_LINE_2']))
line2.request(consumer='SATA_LINE_2', type=gpiod.LINE_REQ_DIR_OUT)
line2.set_value(1)
chip_path = os.environ['SATA_CHIP']
line1_num = int(os.environ['SATA_LINE_1'])
line2_num = int(os.environ['SATA_LINE_2'])

config = {
line1_num: gpiod.LineSettings(
direction=Direction.OUTPUT,
output_value=Value(1)
),
line2_num: gpiod.LineSettings(
direction=Direction.OUTPUT,
output_value=Value(1)
)
}

global sata_request # Keep request alive globally if needed for the service lifetime
sata_request = gpiod.request_lines(
chip_path,
consumer='disk_turn_on',
config=config
)
# Do not release, as this is persistent power-on


conf = {'disk': [], 'idx': mp.Value('d', -1), 'run': mp.Value('d', 1)}
Expand Down
6 changes: 6 additions & 0 deletions rockpi-quad/usr/bin/rockpi-quad/oled.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ def put_disk_info():
{'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['12']},
{'xy': (0, 18), 'text': text2, 'fill': 255, 'font': font['12']},
]
elif len(k) == 2:
text2 = 'Disk: {} {}'.format(k[1], v[1])
page = [
{'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['12']},
{'xy': (0, 18), 'text': text2, 'fill': 255, 'font': font['12']},
]
else:
page = [{'xy': (0, 2), 'text': text1, 'fill': 255, 'font': font['14']}]

Expand Down
23 changes: 12 additions & 11 deletions rockpi-quad/usr/bin/rockpi-quad/requirements.txt
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
Adafruit-Blinka==8.39.0
adafruit-circuitpython-busdevice==5.2.9
adafruit-circuitpython-connectionmanager==3.1.1
adafruit-circuitpython-framebuf==1.6.5
adafruit-circuitpython-requests==4.1.4
adafruit-circuitpython-ssd1306==2.12.17
adafruit-circuitpython-typing==1.10.3
Adafruit-PlatformDetect==3.72.1
Adafruit-Blinka==8.66.0
adafruit-circuitpython-busdevice==5.2.13
adafruit-circuitpython-connectionmanager==3.1.5
adafruit-circuitpython-framebuf==1.6.9
adafruit-circuitpython-requests==4.1.13
adafruit-circuitpython-ssd1306==2.12.21
adafruit-circuitpython-typing==1.12.2
Adafruit-PlatformDetect==3.83.1
Adafruit-PureIO==1.1.11
pyftdi==0.55.4
pyftdi==0.57.1
pyserial==3.5
pyusb==1.2.1
typing-extensions==4.12.2
pyusb==1.3.1
typing-extensions==4.15.0
RPi.GPIO==0.7.1
54 changes: 54 additions & 0 deletions rockpi-quad/usr/bin/rockpi-quad/test_fan.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import os
from pathlib import Path

def load_env():
env_path = Path(__file__).parent / "env" / "rpi4.env"
with open(env_path) as f:
for line in f:
if line.strip() and not line.startswith('#'):
key, _, value = line.strip().partition('=')
os.environ[key] = value


def cleanup_pwm(chip, fun):
try:
with open(f"/sys/class/pwm/pwmchip{chip}/unexport", "w") as f:
f.write(str(fun))
print(f"Unexported PWM channel {fun} on chip {chip}.")
except Exception as e:
print(f"Failed to unexport PWM: {e}")

def test_fan():
import fan
import time
chip = os.environ.get("PWMCHIP", "0")
funs = os.environ.get("PWM_FUN", "0").split(",")
pins = []
try:
for fun in funs:
pin = fan.Pwm(chip, fun)
pin.period_us(40)
pin.enable(True)
print(f"Switching PWM fan ON (chip={chip}, fun={fun}) at 40% power...")
pin.write(0.4)
pins.append((pin, fun))
time.sleep(2)
for pin, fun in pins:
print(f"Switching PWM fan OFF (chip={chip}, fun={fun})...")
pin.write(0.0)
pin.enable(False)
print("Waiting for fans to stop...")
time.sleep(1)
print("Hardware PWM fan test complete.")
except Exception as e:
print(f"fan test failed: {e}")
finally:
for _, fun in pins:
cleanup_pwm(chip, fun)

if __name__ == "__main__":
print("Loading rpi4.env...")
load_env()
print("Environment loaded.")
test_fan()
36 changes: 36 additions & 0 deletions rockpi-quad/usr/bin/rockpi-quad/test_misc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#!/usr/bin/env python3
import os
from pathlib import Path

def load_env():
env_path = Path(__file__).parent / "env" / "rpi4.env"
with open(env_path) as f:
for line in f:
if line.strip() and not line.startswith('#'):
key, _, value = line.strip().partition('=')
os.environ[key] = value

def test_misc():
import misc
print("Testing misc.py:")
try:
print("Turning on SATA lines...")
misc.disk_turn_on()
print("SATA lines turned on.")
except Exception as e:
print(f"misc.disk_turn_on test failed: {e}")

try:
print("Testing read_key (will block, press button to continue)...")
import re
pattern = {'click': re.compile(r'1+0+1{3,}')} # simple pattern
result = misc.read_key(pattern, 10)
print(f"read_key result: {result}")
except Exception as e:
print(f"misc.read_key test failed: {e}")

if __name__ == "__main__":
print("Loading rpi4.env...")
load_env()
print("Environment loaded.")
test_misc()
Loading