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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ _[OPTIONAL]_
## Usage:
### COMMAND LINE

- ```sudo``` is required in order to access the Super I/O EC registers and apply undervolt offsets.
- ```sudo``` is required to access the Super I/O EC registers and apply undervolt offsets.
- From the command line run the main script as root:
```sh
sudo -E python3 main.py
Expand Down Expand Up @@ -86,7 +86,7 @@ Packages:

##

Hey! I'm an undergraduate student and would be awesome if you could support me!
Hey! I'm an undergraduate student, and it would be awesome if you could support me!

[![ko-fi](https://ko-fi.com/img/githubbutton_sm.svg)](https://ko-fi.com/R6R71GROZE)

Expand Down
26 changes: 26 additions & 0 deletions core/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
from PyQt6.QtCore import QObject, QProcess, pyqtSignal

class CommandRunner(QObject):
finished = pyqtSignal(str)

def __init__(self):
super().__init__()
self.process = QProcess()
self.process.readyReadStandardOutput.connect(self._handle_output)
self.process.finished.connect(self._on_finished)
self.output = ""

def run(self, cmd, args):
self.output = "" # Reset output
self.process.start(cmd, args)
self.process.waitForFinished()

def _handle_output(self):
new_output = self.process.readAllStandardOutput().data().decode()
self.output += new_output

def _on_finished(self):
self.finished.emit(self.output)

def close(self):
self.process.close()
48 changes: 6 additions & 42 deletions core/amdctl.py
Original file line number Diff line number Diff line change
@@ -1,49 +1,18 @@
from PyQt6.QtCore import QObject, QProcess, pyqtSignal


class CommandRunner(QObject):
finished = pyqtSignal(str) # Emits the full output when done

def __init__(self):
super().__init__()
self.process = QProcess()
self.process.readyReadStandardOutput.connect(self._handle_output)
self.process.finished.connect(self._on_finished)
self.output = "" # Store output here

def run(self, cmd, args):
self.output = "" # Reset output
self.process.start(cmd, args)
self.process.waitForFinished()

def _handle_output(self):
new_output = self.process.readAllStandardOutput().data().decode()
self.output += new_output # Append to stored output

def _on_finished(self):
self.finished.emit(self.output) # Emit the full output

def close(self):
self.process.close()
from core import CommandRunner


def checkUndervoltStatus(self):
runner = CommandRunner()
runner.run("amdctl", ["-m", "-g", "-c0"])
underVoltStatus = runner.output
# remove the first 3 lines which are not needed
underVoltStatus = underVoltStatus.splitlines()[3:]
# we only want column 0, 5, 6, 7, 10 and 11
underVoltStatus = "\n".join(
under_volt_status = runner.output
under_volt_status = under_volt_status.splitlines()[3:]
under_volt_status = "\n".join(
f"{l[0]}\t{l[5]}\t{l[6].replace('.00', '')}\t{l[7]}\t{l[11]}"
for l in (line.split() for line in underVoltStatus)
for l in (line.split() for line in under_volt_status)
if len(l) > 11
)
self.undervolt = under_volt_status

self.undervolt = underVoltStatus


# Apply the undervoltage offsets values
def applyUndervolt(self):
runner = CommandRunner()
core = self.undervolt_dropdown.currentIndex()
Expand All @@ -53,9 +22,6 @@ def applyUndervolt(self):
runner.run("amdctl", ["-m", f"-v{vid}"])
checkUndervoltStatus(self)


# Global process better perf instead of creating and destroying every update cycle.
# Update the current VCore
voltage_process = CommandRunner()


Expand All @@ -72,9 +38,7 @@ def checkVoltage(self):

if voltages:
avg_v = sum(voltages) / len(voltages)

self.voltage = avg_v

if avg_v < self.minrecordedVoltage:
self.minrecordedVoltage = avg_v
if avg_v > self.maxrecordedVoltage:
Expand Down
13 changes: 9 additions & 4 deletions core/ecwrite.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import subprocess
import sys


Expand All @@ -13,8 +14,8 @@ def __init__(self):
)

def _load_acpi_ec_module(self):
os.system("modprobe -r ec_sys")
os.system("modprobe ec_sys write_support=y")
subprocess.run(["modprobe", "-r", "ec_sys"], check=False)
subprocess.run(["modprobe", "ec_sys", "write_support=y"], check=False)
if os.path.exists("/sys/kernel/debug/ec/ec0/io"):
try:
self.ec_file = open("/sys/kernel/debug/ec/ec0/io", "wb+")
Expand All @@ -28,7 +29,7 @@ def _load_acpi_ec_module(self):
"Failed to load 'ec_sys' module. Attempting to load 'acpi_ec' module."
)

os.system("modprobe acpi_ec")
subprocess.run(["modprobe", "acpi_ec"], check=False)
if os.path.exists("/dev/ec"):
self.ec_file = open("/dev/ec", "wb+")
print("Loaded 'acpi_ec' module successfully.")
Expand All @@ -41,6 +42,7 @@ def ec_write(self, address: int, value: int):
self._handle_error(
"EC file is not initialized. Ensure '_setup_ec()' was successful."
)
return
self.ec_file.seek(address)
self.ec_file.write(bytearray([value]))
except Exception as e:
Expand All @@ -52,6 +54,7 @@ def ec_refresh(self):
self._handle_error(
"EC file is not initialized. Ensure '_setup_ec()' was successful."
)
return
self.ec_file.seek(0)
self.buffer = self.ec_file.read()
if not self.buffer:
Expand All @@ -68,12 +71,14 @@ def ec_read(self, address: int) -> int:
return self.buffer[address]
except Exception as e:
self._handle_error(f"Error reading from the EC buffer: {e}")
return 0

def shutdown_ec(self):
if self.ec_file:
self.ec_file.close()
print("EC access successfully terminated.")

def _handle_error(self, message):
@staticmethod
def _handle_error(message):
print(f"Error: {message}")
sys.exit(1)
31 changes: 2 additions & 29 deletions core/intelctl.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,4 @@
from PyQt6.QtCore import QObject, QProcess, pyqtSignal


class CommandRunner(QObject):
finished = pyqtSignal(str) # Emits the full output when done

def __init__(self):
super().__init__()
self.process = QProcess()
self.process.readyReadStandardOutput.connect(self._handle_output)
self.process.finished.connect(self._on_finished)
self.output = "" # Store output here

def run(self, cmd, args):
self.output = "" # Reset output
self.process.start(cmd, args)
self.process.waitForFinished()

def _handle_output(self):
new_output = self.process.readAllStandardOutput().data().decode()
self.output += new_output # Append to stored output

def _on_finished(self):
self.finished.emit(self.output) # Emit the full output

def close(self):
self.process.close()
from PyQt6.QtCore import QProcess


def checkUndervoltStatus(self):
Expand All @@ -40,7 +14,7 @@ def applyUndervolt(self):

def checkVoltage(self):
## https://askubuntu.com/questions/876286/how-to-monitor-the-vcore-voltage
voltage_process.start("sudo rdmsr 0x198 -a -u --bitfield 47:32") # All processors
voltage_process.start("sudo rdmsr 0x198 -a -u --bitfield 47:32")
voltage_process.waitForFinished()
voltage = voltage_process.readAll()

Expand All @@ -56,4 +30,3 @@ def checkVoltage(self):
self.minrecordedVoltage = voltage
if voltage > self.maxrecordedVoltage:
self.maxrecordedVoltage = voltage

Loading