mirror of
https://gitlab.com/ryzen-controller-team/ryzen-controller.git
synced 2024-12-22 18:13:28 +07:00
451 lines
23 KiB
PowerShell
451 lines
23 KiB
PowerShell
<#
|
|
.SYNOPSIS
|
|
Automates ryzenAdj calls based on custom conditions
|
|
.DESCRIPTION
|
|
This script is designed to provide maximum flexibility to the user. For that reason it does not use parameters.
|
|
Instead of parameters, you need to populate the functions in the configuration section with your custom adjustments and additional custom code.
|
|
.NOTES
|
|
SPDX-License-Identifier: LGPL
|
|
Falco Schaffrath <falco.schaffrath@gmail.com>
|
|
#>
|
|
|
|
Param([Parameter(Mandatory=$false)][switch]$noGUI)
|
|
$Error.Clear()
|
|
################################################################################
|
|
#### Configuration Start
|
|
################################################################################
|
|
# WARNING: Use at your own risk!
|
|
|
|
$pathToRyzenAdjDlls = Split-Path -Parent $PSCommandPath #script path is DLL path, needs to be absolut path if you define something else
|
|
|
|
$showErrorPopupsDuringInit = $true
|
|
# debug mode prints adjust success messages too instead of errorss only
|
|
$debugMode = $false
|
|
# if monitorField is set, this script does only adjust values if something did revert your monitored value. Clear monitorField String to disable monitoring
|
|
# This needs to be an value which actually gets overwritten by your device firmware/software if no changes get detected, your settings will not reapplied
|
|
$monitorField = "fast_limit"
|
|
# Does reapply adjustments if power slider did change position, check $Script:acSlider or $Script:dcSlider to apply slider specific values
|
|
$monitorPowerSlider = $true
|
|
# HWiNFO needs to be restartet after this script did run the first time with this option
|
|
$updateHWINFOSensors = $false
|
|
# some Zen3 devices have a locked STAPM limit, this workarround resets the stapm timer to have unlimited stapm. Use max stapm_limit and stapm_time (usually 500) to triger as less resets as possible
|
|
$resetSTAPMUsage = $false
|
|
|
|
function doAdjust_ACmode {
|
|
$Script:repeatWaitTimeSeconds = 1 #only use values below 5s if you are using $monitorField
|
|
adjust "fast_limit" 46000
|
|
adjust "slow_limit" 25000
|
|
#adjust "slow_time" 30
|
|
#adjust "tctl_temp" 93
|
|
#adjust "apu_skin_temp_limit" 50
|
|
#adjust "vrmmax_current" 100000
|
|
#replace any_other_field with additional adjustments. Name is equal to RyzenAdj options but it uses _ instead of -
|
|
#adjust "any_other_field" 1234
|
|
|
|
#custom code, for example set fan controll back to auto
|
|
#values (WriteRegister: 47, FanSpeedResetValue:128) extracted from similar devices at https://github.com/hirschmann/nbfc/blob/master/Configs/
|
|
#Start-Process -NoNewWindow -Wait -filePath "C:\Program Files (x86)\NoteBook FanControl\ec-probe.exe" -ArgumentList("write", "47", "128")
|
|
|
|
if($Script:acSlider -eq $Script:betterBattery){
|
|
#put adjustments for energie saving slider position here:
|
|
enable "power_saving" #add 10s boost delay for usage on cable to reduce idle power consumtion
|
|
}
|
|
}
|
|
|
|
function doAdjust_BatteryMode {
|
|
$Script:repeatWaitTimeSeconds = 10 #do less reapplies and less HWiNFO updates to save power
|
|
adjust "fast_limit" 26000
|
|
adjust "slow_limit" 10000
|
|
#adjust "any_other_field" 1234
|
|
|
|
if($Script:dcSlider -eq $Script:betterBattery){
|
|
#put adjustments for energie saving slider position here: for example disable fan to save power
|
|
#Start-Process -NoNewWindow -Wait -filePath "C:\Program Files (x86)\NoteBook FanControl\ec-probe.exe" -ArgumentList("write", "47", "0")
|
|
}
|
|
|
|
if($Script:dcSlider -eq $Script:bestPerformance){
|
|
#put adjustments for highest performance slider position here:
|
|
enable "max_performance" #removes 10s boost delay on battery
|
|
doAdjust_ACmode #set limits from cable mode on battery
|
|
}
|
|
}
|
|
################################################################################
|
|
#### Configuration End
|
|
################################################################################
|
|
|
|
$env:PATH += ";$pathToRyzenAdjDlls"
|
|
$NL = $([System.Environment]::NewLine);
|
|
|
|
if($noGUI){ $showErrorPopupsDuringInit = $false }
|
|
|
|
$apiHeader = @'
|
|
[DllImport("libryzenadj.dll")] public static extern IntPtr init_ryzenadj();
|
|
[DllImport("libryzenadj.dll")] public static extern int set_stapm_limit(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_fast_limit(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_slow_limit(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_slow_time(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_stapm_time(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_tctl_temp(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_vrm_current(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_vrmsoc_current(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_vrmmax_current(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_vrmsocmax_current(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_psi0_current(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_psi0soc_current(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_max_gfxclk_freq(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_min_gfxclk_freq(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_max_socclk_freq(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_min_socclk_freq(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_max_fclk_freq(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_min_fclk_freq(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_max_vcn(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_min_vcn(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_max_lclk(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_min_lclk(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_prochot_deassertion_ramp(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_apu_skin_temp_limit(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_dgpu_skin_temp_limit(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_apu_slow_limit(IntPtr ry, [In]uint value);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_power_saving(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern int set_max_performance(IntPtr ry);
|
|
|
|
[DllImport("libryzenadj.dll")] public static extern int refresh_table(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern IntPtr get_table_values(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_stapm_limit(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_stapm_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_stapm_time(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_fast_limit(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_fast_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_slow_limit(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_slow_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_apu_slow_limit(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_apu_slow_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_vrm_current(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_vrm_current_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_vrmsoc_current(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_vrmsoc_current_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_vrmmax_current(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_vrmmax_current_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_vrmsocmax_current(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_vrmsocmax_current_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_tctl_temp(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_tctl_temp_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_apu_skin_temp_limit(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_apu_skin_temp_value(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_dgpu_skin_temp_limit(IntPtr ry);
|
|
[DllImport("libryzenadj.dll")] public static extern float get_dgpu_skin_temp_value(IntPtr ry);
|
|
|
|
[DllImport("kernel32.dll")] public static extern uint GetModuleFileName(IntPtr hModule, [Out]StringBuilder lpFilename, [In]int nSize);
|
|
[DllImport("kernel32.dll")] public static extern Boolean GetSystemPowerStatus(out SystemPowerStatus sps);
|
|
public struct SystemPowerStatus {
|
|
public Byte ACLineStatus;
|
|
public Byte BatteryFlag;
|
|
public Byte BatteryLifePercent;
|
|
public Byte Reserved1;
|
|
public Int32 BatteryLifeTime;
|
|
public Int32 BatteryFullLifeTime;
|
|
}
|
|
|
|
public static String getExpectedWinRing0DriverFilepath(){
|
|
StringBuilder fileName = new StringBuilder(255);
|
|
GetModuleFileName(IntPtr.Zero, fileName, fileName.Capacity);
|
|
return Path.GetDirectoryName(fileName.ToString()) + "\\WinRing0x64.sys";
|
|
}
|
|
|
|
public static String getDllImportErrors(){
|
|
try {
|
|
Marshal.PrelinkAll(typeof(adj));
|
|
} catch (Exception e) {
|
|
return e.Message;
|
|
}
|
|
return "";
|
|
}
|
|
'@
|
|
|
|
if(-not ([System.Management.Automation.PSTypeName]'ryzen.adj').Type){
|
|
Add-Type -MemberDefinition $apiHeader -Namespace 'ryzen' -Name 'adj' -UsingNamespace ('System.Text', 'System.IO')
|
|
}
|
|
|
|
Add-Type -AssemblyName System.Windows.Forms
|
|
function showErrorMsg ([String] $msg){
|
|
if($showErrorPopupsDuringInit){
|
|
[void][System.Windows.Forms.MessageBox]::Show($msg, $PSCommandPath,
|
|
[System.Windows.Forms.MessageBoxButtons]::OK,
|
|
[System.Windows.Forms.MessageBoxIcon]::Error)
|
|
}
|
|
}
|
|
|
|
$dllImportErrors = [ryzen.adj]::getDllImportErrors();
|
|
if($dllImportErrors -or $Error){
|
|
Write-Error $dllImportErrors
|
|
showErrorMsg "Problem with using libryzenadj.dll$NL$NL$($Error -join $NL)"
|
|
exit 1
|
|
}
|
|
|
|
$winring0DriverFilepath = [ryzen.adj]::getExpectedWinRing0DriverFilepath()
|
|
if(!(Test-Path $winring0DriverFilepath)) { Copy-Item -Path $pathToRyzenAdjDlls\WinRing0x64.sys -Destination $winring0DriverFilepath }
|
|
|
|
$ry = [ryzen.adj]::init_ryzenadj()
|
|
if($ry -eq 0){
|
|
$msg = "RyzenAdj could not get initialized.$($NL)Reason can be found inside Powershell$($NL)"
|
|
if($psISE) { $msg += "It is not possible to see the error reason inside ISE, you need to test it in PowerShell Console" }
|
|
showErrorMsg "$msg$NL$NL$($Error -join $NL)"
|
|
exit 1
|
|
}
|
|
|
|
function adjust ([String] $fieldName, [uInt32] $value) {
|
|
if($fieldName -eq $Script:monitorField) {
|
|
$newTargetValue = [math]::round($value * 0.001, 3, 0)
|
|
if($Script:monitorFieldAdjTarget -ne $newTargetValue){
|
|
$Script:monitorFieldAdjTarget = $newTargetValue
|
|
Write-Host "set new monitoring target $fieldName to $newTargetValue"
|
|
}
|
|
}
|
|
$res = Invoke-Expression "[ryzen.adj]::set_$fieldName($ry, $value)"
|
|
switch ($res) {
|
|
0 {
|
|
if($debugMode) { Write-Host "set $fieldName to $value" }
|
|
return
|
|
}
|
|
-1 { Write-Error "set_$fieldName is not supported on this family"}
|
|
-3 { Write-Error "set_$fieldName is not supported on this SMU"}
|
|
-4 { Write-Error "set_$fieldName is rejected by SMU"}
|
|
default { Write-Error "set_$fieldName did fail with $res"}
|
|
}
|
|
}
|
|
|
|
function enable ([String] $fieldName) {
|
|
$res = Invoke-Expression "[ryzen.adj]::set_$fieldName($ry)"
|
|
switch ($res) {
|
|
0 {
|
|
if($debugMode) { Write-Host "enable $fieldName"}
|
|
return
|
|
}
|
|
-1 { Write-Error "set_$fieldName is not supported on this family"}
|
|
-3 { Write-Error "set_$fieldName is not supported on this SMU"}
|
|
-4 { Write-Error "set_$fieldName is rejected by SMU"}
|
|
default { Write-Error "set_$fieldName did fail with $res"}
|
|
}
|
|
}
|
|
|
|
function testMonitorField {
|
|
if($monitorField -and $Script:monitorFieldAdjTarget -eq 0){
|
|
Write-Error ("You forgot to set $monitorField in your profile.$NL$NL" +
|
|
"If you ignore it, the script will apply values unnessasary often.$NL")
|
|
}
|
|
}
|
|
|
|
function updateMonitorFieldAdjResult {
|
|
if($monitorField){
|
|
[void][ryzen.adj]::refresh_table($ry)
|
|
$Script:monitorFieldAdjResult = [math]::round((getMonitorValue), 3, 0)
|
|
if($Script:monitorFieldAdjTarget -ne $Script:monitorFieldAdjResult){
|
|
Write-Host ("Warning - $monitorField adjust result $Script:monitorFieldAdjResult does not match target value $Script:monitorFieldAdjTarget. Value $Script:monitorFieldAdjResult will be used for monitoring")
|
|
}
|
|
}
|
|
}
|
|
|
|
function testConfiguration {
|
|
Write-Host "Test Adjustments"
|
|
if($Script:systemPowerStatus.ACLineStatus){
|
|
doAdjust_BatteryMode
|
|
testMonitorField
|
|
$Script:monitorFieldAdjTarget = 0
|
|
doAdjust_ACmode
|
|
} else {
|
|
doAdjust_ACmode
|
|
testMonitorField
|
|
$Script:monitorFieldAdjTarget = 0
|
|
doAdjust_BatteryMode
|
|
}
|
|
testMonitorField
|
|
updateMonitorFieldAdjResult
|
|
|
|
if($resetSTAPMUsage -and [ryzen.adj]::get_stapm_time($ry) -eq 1) {
|
|
Write-Error "resetSTAPMUsage function does only work on devices with active STAPM control and don't do anything on devices with enabled STT control."
|
|
}
|
|
|
|
if($Error -and $showErrorPopupsDuringInit){
|
|
$answer = [System.Windows.Forms.MessageBox]::Show("Your Adjustment configuration did not work.$NL$NL$($Error -join $NL)", $PSCommandPath,
|
|
[System.Windows.Forms.MessageBoxButtons]::AbortRetryIgnore,
|
|
[System.Windows.Forms.MessageBoxIcon]::Warning)
|
|
$Error.Clear()
|
|
if($answer -eq "Abort"){ exit 1 }
|
|
if($answer -eq "Retry"){ testConfiguration }
|
|
}
|
|
}
|
|
|
|
function getMonitorValue {
|
|
if($monitorField){
|
|
return Invoke-Expression "[ryzen.adj]::get_$monitorField($ry)"
|
|
}
|
|
return 0
|
|
}
|
|
|
|
function createOrDeleteHWINFOSensors {
|
|
if($updateHWINFOSensors){
|
|
New-Item -Path HKCU:\Software\HWiNFO64\Sensors\Custom -Name RyzenAdj -Force > $null
|
|
'Key,Name,Value
|
|
Power0,STAPM Limit
|
|
Power1,STAPM
|
|
Power2,PPT FAST Limit
|
|
Power3,PPT FAST
|
|
Power4,PPT SLOW Limit
|
|
Power5,PPT SLOW
|
|
Power6,APU SLOW Limit
|
|
Power7,APU SLOW
|
|
Current0,TDC VRM Limit
|
|
Current1,TDC VRM
|
|
Current2,TDC VRM SoC Limit
|
|
Current3,TDC VRM SoC
|
|
Current4,EDC VRM Max Limit
|
|
Current5,EDC VRM Max
|
|
Current6,EDC VRM SoC Max Limit
|
|
Current7,EDC VRM SoC Max
|
|
Temp0,TCTL Temp Limit
|
|
Temp1,TCTL Temp
|
|
Temp2,SST APU Skin Temp Limit
|
|
Temp3,SST APU Skin Temp
|
|
Temp4,SST dGPU Skin Temp Limit
|
|
Temp5,SST dGPU Skin Temp
|
|
Usage0,STAPM Limit Usage, ("STAPM" / "STAPM Limit") * 100
|
|
Usage1,PPT FAST Limit Usage, ("PPT FAST" / "PPT FAST Limit") * 100
|
|
Usage2,PPT SLOW Limit Usage, ("PPT SLOW" / "PPT SLOW Limit") * 100
|
|
Usage3,APU SLOW Limit Usage, ("APU SLOW" / "APU SLOW Limit") * 100
|
|
Usage4,TDC VRM Limit Usage, ("TDC VRM" / "TDC VRM Limit") * 100
|
|
Usage5,TDC VRM SoC Limit Usage, ("TDC VRM SoC" / "TDC VRM SoC Limit") * 100
|
|
Usage6,EDC VRM Max Limit Usage, ("EDC VRM Max" / "EDC VRM Max Limit") * 100
|
|
Usage7,EDC VRM SoC Max Limit Usage, ("EDC VRM SoC Max" / "EDC VRM SoC Max Limit") * 100
|
|
Usage8,TCTL Temp Limit Usage, ("TCTL Temp" / "TCTL Temp Limit") * 100
|
|
Usage9,SST APU Skin Temp Limit Usage, ("SST APU Skin Temp" / "SST APU Skin Temp Limit") * 100
|
|
Usage10,SST dGPU Skin Temp Limit Usage, ("SST dGPU Skin Temp" / "SST dGPU Skin Temp Limit") * 100' | ConvertFrom-Csv -outvariable hwinfo_keys > $null
|
|
$hwinfo_keys | ForEach-Object {New-item -Path HKCU:\Software\HWiNFO64\Sensors\Custom\RyzenAdj -Name $_.Key -Force} > $null
|
|
$hwinfo_keys | ForEach-Object {[Microsoft.Win32.Registry]::SetValue("HKEY_CURRENT_USER\Software\HWiNFO64\Sensors\Custom\RyzenAdj\" + $_.Key,"Name",$_.Name)} > $null
|
|
$hwinfo_keys | Where Value -ne $null | ForEach-Object {[Microsoft.Win32.Registry]::SetValue("HKEY_CURRENT_USER\Software\HWiNFO64\Sensors\Custom\RyzenAdj\" + $_.Key,"Value",$_.Value)} > $null
|
|
} else {
|
|
Remove-Item HKCU:\Software\HWiNFO64\Sensors\Custom\RyzenAdj -Recurse -ErrorAction:Ignore
|
|
}
|
|
}
|
|
|
|
function setHWINFOValue ([String] $name, [float] $value) {
|
|
if(![float]::IsNaN($value)){ [Microsoft.Win32.Registry]::SetValue("HKEY_CURRENT_USER\Software\HWiNFO64\Sensors\Custom\RyzenAdj\" + $name,"Value",[String]$value) }
|
|
}
|
|
|
|
function updateHWINFOSensors {
|
|
setHWINFOValue Power0 ([ryzen.adj]::get_stapm_limit($ry))
|
|
setHWINFOValue Power1 ([ryzen.adj]::get_stapm_value($ry))
|
|
setHWINFOValue Power2 ([ryzen.adj]::get_fast_limit($ry))
|
|
setHWINFOValue Power3 ([ryzen.adj]::get_fast_value($ry))
|
|
setHWINFOValue Power4 ([ryzen.adj]::get_slow_limit($ry))
|
|
setHWINFOValue Power5 ([ryzen.adj]::get_slow_value($ry))
|
|
setHWINFOValue Power6 ([ryzen.adj]::get_apu_slow_limit($ry))
|
|
setHWINFOValue Power7 ([ryzen.adj]::get_apu_slow_value($ry))
|
|
setHWINFOValue Current0 ([ryzen.adj]::get_vrm_current($ry))
|
|
setHWINFOValue Current1 ([ryzen.adj]::get_vrm_current_value($ry))
|
|
setHWINFOValue Current2 ([ryzen.adj]::get_vrmsoc_current($ry))
|
|
setHWINFOValue Current3 ([ryzen.adj]::get_vrmsoc_current_value($ry))
|
|
setHWINFOValue Current4 ([ryzen.adj]::get_vrmmax_current($ry))
|
|
setHWINFOValue Current5 ([ryzen.adj]::get_vrmmax_current_value($ry))
|
|
setHWINFOValue Current6 ([ryzen.adj]::get_vrmsocmax_current($ry))
|
|
setHWINFOValue Current7 ([ryzen.adj]::get_vrmsocmax_current_value($ry))
|
|
setHWINFOValue Temp0 ([ryzen.adj]::get_tctl_temp($ry))
|
|
setHWINFOValue Temp1 ([ryzen.adj]::get_tctl_temp_value($ry))
|
|
setHWINFOValue Temp2 ([ryzen.adj]::get_apu_skin_temp_limit($ry))
|
|
setHWINFOValue Temp3 ([ryzen.adj]::get_apu_skin_temp_value($ry))
|
|
setHWINFOValue Temp4 ([ryzen.adj]::get_dgpu_skin_temp_limit($ry))
|
|
setHWINFOValue Temp5 ([ryzen.adj]::get_dgpu_skin_temp_value($ry))
|
|
#setHWINFOValue Usage11 $pmTable[546]
|
|
}
|
|
|
|
function resetSTAPMIfNeeded {
|
|
$stapm_limit = [ryzen.adj]::get_stapm_limit($ry)
|
|
$stapm_value = [ryzen.adj]::get_stapm_value($ry)
|
|
$stapm_hysteresis = 1 #Throttling starts arround ~0.9W before limit
|
|
|
|
if ($stapm_value -gt ($stapm_limit - $stapm_hysteresis)) {
|
|
$stapm_time = [ryzen.adj]::get_stapm_time($ry)
|
|
$reduced_stapm_limit = ($stapm_limit - 5) #reduce stapm by 5W
|
|
Write-Host "[STAPM_RESET] stapm_value ($stapm_value) nearing stapm_limit ($stapm_limit), resetting..."
|
|
[void][ryzen.adj]::set_stapm_limit($ry, ($reduced_stapm_limit) * 1000)
|
|
[void][ryzen.adj]::set_stapm_time($ry, 0)
|
|
[Threading.Thread]::Sleep(10) #10ms is usually enough time
|
|
[void][ryzen.adj]::set_stapm_time($ry, $stapm_time)
|
|
[void][ryzen.adj]::set_stapm_limit($ry, $stapm_limit * 1250) # add 25% STAPM limit in case we are at battery saving mode where applied values get reduced by 10% or 20%
|
|
}
|
|
}
|
|
|
|
if(-not $Script:repeatWaitTimeSeconds) { $Script:repeatWaitTimeSeconds = 5 }
|
|
$Script:monitorFieldAdjResult = 0; #adjust result will be used for monitoring because SMU may only set 90% and 80% of your value
|
|
$Script:monitorFieldAdjTarget = 0;
|
|
$powerkey = [Microsoft.Win32.Registry]::LocalMachine.OpenSubKey("SYSTEM\ControlSet001\Control\Power\User\PowerSchemes\")
|
|
$Script:betterBattery = "961cc777-2547-4f9d-8174-7d86181b8a7a"
|
|
$Script:betterPerformance = "00000000-0000-0000-0000-000000000000"
|
|
$Script:bestPerformance = "ded574b5-45a0-4f42-8737-46345c09c238"
|
|
$Script:acSlider = $powerkey.GetValue("ActiveOverlayACPowerScheme")
|
|
$Script:dcSlider = $powerkey.GetValue("ActiveOverlayDCPowerScheme")
|
|
|
|
$systemPowerStatus = New-Object ryzen.adj+SystemPowerStatus
|
|
[void][ryzen.adj]::GetSystemPowerStatus([ref]$systemPowerStatus)
|
|
|
|
testConfiguration
|
|
|
|
<# Example how to get 560 lines of ptable
|
|
$pmTable = [float[]]::new(560)
|
|
$tablePtr = [ryzen.adj]::get_table_values($ry);
|
|
[System.Runtime.InteropServices.Marshal]::Copy($tablePtr, $pmTable, 0, 560);
|
|
#>
|
|
createOrDeleteHWINFOSensors
|
|
|
|
$mtxtArray = @()
|
|
if($monitorField){$mtxtArray += "$monitorField changes"}
|
|
if($monitorPowerSlider){$mtxtArray += "PowerSlider changes"}
|
|
if($mtxtArray.Length){
|
|
$processType = "Monitor " + ($mtxtArray -join " and ")
|
|
} else {
|
|
$processType = "Apply Settings"
|
|
}
|
|
Write-Host "$processType every $Script:repeatWaitTimeSeconds seconds..."
|
|
while($true) {
|
|
$doAdjust = !$monitorField -and !$monitorPowerSlider
|
|
if($monitorField -or $updateHWINFOSensors -or $resetSTAPMUsage) {
|
|
[void][ryzen.adj]::refresh_table($ry)
|
|
#[System.Runtime.InteropServices.Marshal]::Copy($tablePtr, $pmTable, 0, 560);
|
|
}
|
|
|
|
if($updateHWINFOSensors){
|
|
updateHWINFOSensors
|
|
}
|
|
|
|
if($monitorPowerSlider -and ($Script:acSlider -ne $powerkey.GetValue("ActiveOverlayACPowerScheme") -or $Script:dcSlider -ne $powerkey.GetValue("ActiveOverlayDCPowerScheme"))){
|
|
Write-Host "Power Slider changed"
|
|
$Script:acSlider = $powerkey.GetValue("ActiveOverlayACPowerScheme")
|
|
$Script:dcSlider = $powerkey.GetValue("ActiveOverlayDCPowerScheme")
|
|
$doAdjust = $true
|
|
}
|
|
if($monitorField){
|
|
$monitorValue = getMonitorValue
|
|
if($Script:monitorFieldAdjResult -ne [math]::round($monitorValue, 3, 0)){
|
|
Write-Host "$monitorField value unexpectedly changed from $Script:monitorFieldAdjResult to $monitorValue"
|
|
$doAdjust = $true
|
|
}
|
|
}
|
|
|
|
if($resetSTAPMUsage){
|
|
resetSTAPMIfNeeded
|
|
}
|
|
|
|
if($doAdjust){
|
|
[void][ryzen.adj]::GetSystemPowerStatus([ref]$systemPowerStatus)
|
|
$oldWait = $Script:repeatWaitTimeSeconds
|
|
if($systemPowerStatus.ACLineStatus){
|
|
doAdjust_ACmode
|
|
} else {
|
|
doAdjust_BatteryMode
|
|
}
|
|
updateMonitorFieldAdjResult
|
|
if($oldWait -ne $Script:repeatWaitTimeSeconds ) { Write-Host "$processType every $Script:repeatWaitTimeSeconds seconds..." }
|
|
}
|
|
|
|
sleep $Script:repeatWaitTimeSeconds
|
|
}
|