diff --git a/FanControl/App.config b/FanControl/App.config
new file mode 100644
index 0000000..49cc43e
--- /dev/null
+++ b/FanControl/App.config
@@ -0,0 +1,3 @@
+
+
+
\ No newline at end of file
diff --git a/FanControl/FanControl.cs b/FanControl/FanControl.cs
index e3619be..f903c4a 100644
--- a/FanControl/FanControl.cs
+++ b/FanControl/FanControl.cs
@@ -1,4 +1,7 @@
-using System;
+using LibreHardwareMonitor.Hardware;
+using LibreHardwareMonitor.Hardware.CPU;
+using Microsoft.VisualBasic.Devices;
+using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Metrics;
@@ -9,7 +12,7 @@ using System.Threading.Tasks;
namespace FanControl
{
[TypeConverter(typeof(ExpandableObjectConverter))]
- internal class FanControl
+ internal class FanControl : IDisposable
{
public enum FanMode
{
@@ -18,6 +21,79 @@ namespace FanControl
Max
}
+ [TypeConverter(typeof(ExpandableObjectConverter))]
+ internal class FanSensor
+ {
+ public string? Name { get; internal set; }
+ public float? Value { get; internal set; }
+ public ushort InducedRPM { get; internal set; }
+
+ internal string HardwareName { get; set; } = "";
+ internal HardwareType HardwareType { get; set; }
+ internal string SensorName { get; set; } = "";
+ internal SensorType SensorType { get; set; }
+
+ public void Reset()
+ {
+ Name = null;
+ Value = null;
+ InducedRPM = 0;
+ }
+
+ public bool Matches(ISensor sensor)
+ {
+ return sensor != null &&
+ sensor.Hardware.HardwareType == HardwareType &&
+ sensor.Hardware.Name.StartsWith(HardwareName) &&
+ sensor.SensorType == SensorType &&
+ sensor.Name == SensorName;
+ }
+
+ public bool Update(ISensor hwSensor)
+ {
+ if (!Matches(hwSensor))
+ return false;
+
+ System.Diagnostics.Trace.WriteLine(String.Format("{0}: {1} {2}, value: {3}, type: {4}",
+ hwSensor.Identifier, hwSensor.Hardware.Name, hwSensor.Name, hwSensor.Value, hwSensor.SensorType));
+
+ return Update(
+ String.Format("{0} {1}", hwSensor.Hardware.Name, hwSensor.Name),
+ hwSensor.Value);
+ }
+
+ public bool Update(string name, float? value)
+ {
+ if (!value.HasValue || value <= 0.0)
+ return false;
+
+ Name = name;
+ Value = value;
+ return true;
+ }
+
+ public String FormattedValue()
+ {
+ if (!Value.HasValue)
+ return "";
+
+ switch (SensorType)
+ {
+ case SensorType.Temperature:
+ return Value.Value.ToString("F1") + "℃";
+ case SensorType.Power:
+ return Value.Value.ToString("F1") + "W";
+ default:
+ return Value.Value.ToString("F1");
+ }
+ }
+
+ public override string ToString()
+ {
+ return Name;
+ }
+ }
+
[CategoryAttribute("Fan")]
public FanMode Mode { get; private set; }
@@ -27,10 +103,124 @@ namespace FanControl
[CategoryAttribute("Fan")]
public ushort DesiredRPM { get; private set; }
+ [CategoryAttribute("Sensor - APU"), DisplayName("Name")]
+ public String? APUName { get { return allSensors["APU"].Name; } }
+ [CategoryAttribute("Sensor - APU"), DisplayName("Power")]
+ public String? APUPower { get { return allSensors["APU"].FormattedValue(); } }
+
+ [CategoryAttribute("Sensor - CPU"), DisplayName("Name")]
+ public String? CPUName { get { return allSensors["CPU"].Name; } }
+ [CategoryAttribute("Sensor - CPU"), DisplayName("Temperature")]
+ public String? CPUTemperature { get { return allSensors["CPU"].FormattedValue(); } }
+
+ [CategoryAttribute("Sensor - GPU"), DisplayName("Name")]
+ public String? GPUName { get { return allSensors["GPU"].Name; } }
+ [CategoryAttribute("Sensor - GPU"), DisplayName("Temperature")]
+ public String? GPUTemperature { get { return allSensors["GPU"].FormattedValue(); } }
+
+ [CategoryAttribute("Sensor - SSD"), DisplayName("Name")]
+ public String? SSDName { get { return allSensors["SSD"].Name; } }
+ [CategoryAttribute("Sensor - SSD"), DisplayName("Temperature")]
+ public String? SSDTemperature { get { return allSensors["SSD"].FormattedValue(); } }
+ [CategoryAttribute("Sensor - Battery"), DisplayName("Name")]
+ public String? BatteryName { get { return allSensors["Batt"].Name; } }
+ [CategoryAttribute("Sensor - Battery"), DisplayName("Temperature")]
+ public String? BatteryTemperature { get { return allSensors["Batt"].FormattedValue(); } }
+
+ private Dictionary allSensors = new Dictionary
+ {
+ { "APU",
+ new FanSensor()
+ {
+ // TODO: Is this correct?
+ HardwareName = "AMD Custom APU 0405",
+ HardwareType = HardwareType.Cpu,
+ SensorName = "Package",
+ SensorType = SensorType.Power
+ } },
+ { "CPU",
+ new FanSensor()
+ {
+ HardwareName = "AMD Custom APU 0405",
+ HardwareType = HardwareType.Cpu,
+ SensorName = "Core (Tctl/Tdie)",
+ SensorType = SensorType.Temperature
+ } },
+ { "GPU",
+ new FanSensor()
+ {
+ HardwareName = "AMD Custom GPU 0405",
+ HardwareType = HardwareType.GpuAmd,
+ SensorName = "GPU Core",
+ SensorType = SensorType.Temperature
+ } },
+ { "SSD",
+ new FanSensor()
+ {
+ HardwareType = HardwareType.Storage,
+ SensorName = "Temperature",
+ SensorType = SensorType.Temperature
+ } },
+ { "Batt",
+ new FanSensor()
+ {
+ HardwareType = HardwareType.Battery,
+ SensorName = "Temperature",
+ SensorType = SensorType.Temperature
+ } }
+ };
+
+ LibreHardwareMonitor.Hardware.Computer libreHardwareComputer = new LibreHardwareMonitor.Hardware.Computer
+ {
+ IsCpuEnabled = true,
+ IsGpuEnabled = true,
+ IsStorageEnabled = true,
+ IsBatteryEnabled = true
+ };
+
+ public FanControl()
+ {
+ libreHardwareComputer.Open();
+ }
+
+ private void visitHardware(IHardware hardware)
+ {
+ Dictionary matched = new Dictionary();
+
+ foreach (ISensor hwSensor in hardware.Sensors)
+ {
+ foreach (var sensor in allSensors.Values)
+ {
+ if (sensor.Matches(hwSensor))
+ matched[sensor] = hwSensor;
+ }
+ }
+
+ if (matched.Any())
+ {
+ hardware.Update();
+ foreach (var sensor in matched)
+ sensor.Key.Update(sensor.Value);
+ }
+
+ foreach (IHardware subhardware in hardware.SubHardware)
+ {
+ visitHardware(subhardware);
+ }
+ }
+
public void Update()
{
CurrentRPM = Vlv0100.GetFanRPM();
DesiredRPM = Vlv0100.GetFanDesiredRPM();
+
+ foreach (var sensor in allSensors.Values)
+ sensor.Reset();
+
+ foreach(var hardware in libreHardwareComputer.Hardware)
+ visitHardware(hardware);
+
+ allSensors["Batt"].Update("VLV0100", Vlv0100.GetBattTemperature());
}
public void SetMode(FanMode mode)
@@ -54,5 +244,10 @@ namespace FanControl
this.Mode = mode;
}
+
+ public void Dispose()
+ {
+ libreHardwareComputer.Close();
+ }
}
}
diff --git a/FanControl/FanControl.csproj b/FanControl/FanControl.csproj
index 73ca95a..ab2ca79 100644
--- a/FanControl/FanControl.csproj
+++ b/FanControl/FanControl.csproj
@@ -7,16 +7,29 @@
enable
True
FanControl.Program
+ app.manifest
+
+
+ True
+ True
+ Settings.settings
+
+
+
PreserveNewest
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
diff --git a/FanControl/FanControlForm.Designer.cs b/FanControl/FanControlForm.Designer.cs
index 9148584..2627524 100644
--- a/FanControl/FanControlForm.Designer.cs
+++ b/FanControl/FanControlForm.Designer.cs
@@ -30,7 +30,7 @@
{
this.components = new System.ComponentModel.Container();
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FanControlForm));
- this.updateTimer = new System.Windows.Forms.Timer(this.components);
+ this.fanLoopTimer = new System.Windows.Forms.Timer(this.components);
this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
this.contextMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
this.fanModeSelectNotifyMenu = new System.Windows.Forms.ToolStripComboBox();
@@ -41,15 +41,16 @@
this.fanModeSelectMenu = new System.Windows.Forms.ToolStripComboBox();
this.controlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this.propertyGridUpdateTimer = new System.Windows.Forms.Timer(this.components);
this.contextMenu.SuspendLayout();
this.menuStrip1.SuspendLayout();
this.SuspendLayout();
//
- // updateTimer
+ // fanLoopTimer
//
- this.updateTimer.Enabled = true;
- this.updateTimer.Interval = 250;
- this.updateTimer.Tick += new System.EventHandler(this.updateTimer_Tick);
+ this.fanLoopTimer.Enabled = true;
+ this.fanLoopTimer.Interval = 250;
+ this.fanLoopTimer.Tick += new System.EventHandler(this.fanLoopTimer_Tick);
//
// notifyIcon
//
@@ -98,7 +99,7 @@
this.propertyGrid1.HelpVisible = false;
this.propertyGrid1.Location = new System.Drawing.Point(0, 44);
this.propertyGrid1.Name = "propertyGrid1";
- this.propertyGrid1.Size = new System.Drawing.Size(712, 599);
+ this.propertyGrid1.Size = new System.Drawing.Size(712, 885);
this.propertyGrid1.TabIndex = 0;
this.propertyGrid1.ToolbarVisible = false;
//
@@ -138,11 +139,17 @@
this.exitToolStripMenuItem.Text = "&Exit";
this.exitToolStripMenuItem.Click += new System.EventHandler(this.formClose_Event);
//
+ // propertyGridUpdateTimer
+ //
+ this.propertyGridUpdateTimer.Enabled = true;
+ this.propertyGridUpdateTimer.Interval = 1000;
+ this.propertyGridUpdateTimer.Tick += new System.EventHandler(this.propertyGridUpdateTimer_Tick);
+ //
// FanControlForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(13F, 32F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(712, 643);
+ this.ClientSize = new System.Drawing.Size(712, 929);
this.Controls.Add(this.propertyGrid1);
this.Controls.Add(this.menuStrip1);
this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
@@ -150,7 +157,6 @@
this.Name = "FanControlForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Steam Deck Fan Control";
- this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FanControlForm_FormClosing);
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FanControlForm_FormClosed);
this.contextMenu.ResumeLayout(false);
@@ -163,7 +169,7 @@
#endregion
- private System.Windows.Forms.Timer updateTimer;
+ private System.Windows.Forms.Timer fanLoopTimer;
private NotifyIcon notifyIcon;
private PropertyGrid propertyGrid1;
private ContextMenuStrip contextMenu;
@@ -174,5 +180,6 @@
private ToolStripComboBox fanModeSelectMenu;
private ToolStripMenuItem controlToolStripMenuItem;
private ToolStripMenuItem exitToolStripMenuItem;
+ private System.Windows.Forms.Timer propertyGridUpdateTimer;
}
}
\ No newline at end of file
diff --git a/FanControl/FanControlForm.cs b/FanControl/FanControlForm.cs
index 80330e3..9de96be 100644
--- a/FanControl/FanControlForm.cs
+++ b/FanControl/FanControlForm.cs
@@ -21,8 +21,9 @@ namespace FanControl
InitializeComponent();
propertyGrid1.SelectedObject = fanControl;
+ propertyGrid1.ExpandAllGridItems();
- foreach(var item in Enum.GetValues(typeof(FanControl.FanMode)))
+ foreach (var item in Enum.GetValues(typeof(FanControl.FanMode)))
{
fanModeSelectMenu.Items.Add(item);
fanModeSelectNotifyMenu.Items.Add(item);
@@ -55,6 +56,7 @@ namespace FanControl
private void formShow_Event(object sender, EventArgs e)
{
Show();
+ propertyGrid1.Refresh();
}
private void formClose_Event(object sender, EventArgs e)
@@ -69,15 +71,19 @@ namespace FanControl
fanControl.SetMode(FanControl.FanMode.Default);
}
- private void updateTimer_Tick(object sender, EventArgs e)
+ private void fanLoopTimer_Tick(object sender, EventArgs e)
{
fanControl.Update();
+ }
- if (Visible)
- {
- propertyGrid1.Refresh();
- }
+ private void propertyGridUpdateTimer_Tick(object sender, EventArgs e)
+ {
+ if (!Visible)
+ return;
+ var item = propertyGrid1.SelectedGridItem;
+ propertyGrid1.Refresh();
+ propertyGrid1.SelectedGridItem = item;
notifyIcon.Text = String.Format("Fan: {0} RPM Mode: {1}", fanControl.CurrentRPM, fanControl.Mode);
}
}
diff --git a/FanControl/FanControlForm.resx b/FanControl/FanControlForm.resx
index d02e7fc..87f2860 100644
--- a/FanControl/FanControlForm.resx
+++ b/FanControl/FanControlForm.resx
@@ -57,14 +57,14 @@
System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
-
- 17, 17
+
+ 1188, 17
- 159, 17
+ 955, 18
- 353, 17
+ 8, 6
@@ -111,6 +111,9 @@
651, 17
+
+ 1477, 16
+
AAABAAEAAAAAAAEAIAB5CAAAFgAAAIlQTkcNChoKAAAADUlIRFIAAABAAAAAQAgGAAAAqmlx3gAAAAFz
diff --git a/FanControl/Program.cs b/FanControl/Program.cs
index 5622e47..4a124da 100644
--- a/FanControl/Program.cs
+++ b/FanControl/Program.cs
@@ -34,15 +34,17 @@ namespace FanControl
IsMotherboardEnabled = true,
IsControllerEnabled = true,
IsNetworkEnabled = true,
- IsStorageEnabled = true
+ IsStorageEnabled = true,
+ IsPsuEnabled = true,
+ IsBatteryEnabled = true
};
computer.Open();
- computer.Accept(new UpdateVisitor());
+ //computer.Accept(new UpdateVisitor());
foreach (IHardware hardware in computer.Hardware)
{
- Console.WriteLine("Hardware: {0}", hardware.Name);
+ Console.WriteLine("Hardware: {0}. Type: {1}", hardware.Name, hardware.HardwareType);
foreach (IHardware subhardware in hardware.SubHardware)
{
@@ -50,13 +52,13 @@ namespace FanControl
foreach (ISensor sensor in subhardware.Sensors)
{
- Console.WriteLine("\t\tSensor: {0}, value: {1}", sensor.Name, sensor.Value);
+ Console.WriteLine("\t\tSensor: {0}, value: {1}, type: {2}", sensor.Name, sensor.Value, sensor.SensorType);
}
}
foreach (ISensor sensor in hardware.Sensors)
{
- Console.WriteLine("\tSensor: {0}, value: {1}", sensor.Name, sensor.Value);
+ Console.WriteLine("\tSensor: {0}, value: {1}, type: {2}", sensor.Name, sensor.Value, sensor.SensorType);
}
}
@@ -64,7 +66,7 @@ namespace FanControl
}
static void ConsoleMain(string[] args)
{
- // Monitor();
+ Monitor();
while (true)
{
diff --git a/FanControl/Properties/Settings.Designer.cs b/FanControl/Properties/Settings.Designer.cs
new file mode 100644
index 0000000..4bb435d
--- /dev/null
+++ b/FanControl/Properties/Settings.Designer.cs
@@ -0,0 +1,26 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace FanControl.Properties {
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.3.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default {
+ get {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/FanControl/Properties/Settings.settings b/FanControl/Properties/Settings.settings
new file mode 100644
index 0000000..049245f
--- /dev/null
+++ b/FanControl/Properties/Settings.settings
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/FanControl/Vlv0100.cs b/FanControl/Vlv0100.cs
index 7300617..9e68a69 100644
--- a/FanControl/Vlv0100.cs
+++ b/FanControl/Vlv0100.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
@@ -16,6 +17,7 @@ namespace FanControl
static IntPtr FRPR = new IntPtr(0xFE700B00 + 0x97);
static IntPtr FNRL_FNRH = new IntPtr(0xFE700300 + 0xB0);
static IntPtr FNCK = new IntPtr(0xFE700300 + 0x9F);
+ static IntPtr BATH_BATL = new IntPtr(0xFE700400 + 0x6E);
static ushort IO6C = 0x6C;
public const ushort MAX_FAN_RPM = 0x1C84;
@@ -54,6 +56,13 @@ namespace FanControl
return (data[0] & 0x1) != 0;
}
+ public static float GetBattTemperature()
+ {
+ byte[] data = InpOut.ReadMemory(BATH_BATL, 2);
+ int value = (data[0] << 8) + data[1];
+ return (float)(value - 0x0AAC) / 10.0f;
+ }
+
private static void SetGain(ushort gain)
{
byte[] data = BitConverter.GetBytes(gain);
diff --git a/FanControl/app.manifest b/FanControl/app.manifest
new file mode 100644
index 0000000..9eddb63
--- /dev/null
+++ b/FanControl/app.manifest
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+ true
+
+
+
+
+
+
+