Added a minimal control interface to allow manual fan control and implemented the interface for ATI GPUs.

This commit is contained in:
Michael Möller
2011-01-20 21:31:54 +00:00
parent 667b36a431
commit 86dbc6f06b
11 changed files with 331 additions and 7 deletions

View File

@@ -461,6 +461,34 @@ namespace OpenHardwareMonitor.GUI {
};
sensorContextMenu.MenuItems.Add(item);
}
if (node.Sensor.Control != null) {
IControl control = node.Sensor.Control;
MenuItem controlItem = new MenuItem("Control");
MenuItem defaultItem = new MenuItem("Default");
defaultItem.Checked = control.ControlMode == ControlMode.Default;
controlItem.MenuItems.Add(defaultItem);
defaultItem.Click += delegate(object obj, EventArgs args) {
control.SetDefault();
};
MenuItem manualItem = new MenuItem("Manual");
controlItem.MenuItems.Add(manualItem);
manualItem.Checked = control.ControlMode == ControlMode.Software;
for (int i = 0; i <= 100; i += 5) {
if (i <= control.MaxSoftwareValue &&
i >= control.MinSoftwareValue)
{
MenuItem item = new MenuItem(i + " %");
manualItem.MenuItems.Add(item);
item.Checked = control.ControlMode == ControlMode.Software &&
Math.Round(control.SoftwareValue) == i;
int softwareValue = i;
item.Click += delegate(object obj, EventArgs args) {
control.SetSoftware(softwareValue);
};
}
}
sensorContextMenu.MenuItems.Add(controlItem);
}
sensorContextMenu.Show(treeView, new Point(m.X, m.Y));
}

View File

@@ -122,6 +122,7 @@ namespace OpenHardwareMonitor.Hardware.ATI {
public const int ADL_DL_FANCTRL_SUPPORTS_PERCENT_WRITE = 2;
public const int ADL_DL_FANCTRL_SUPPORTS_RPM_READ = 4;
public const int ADL_DL_FANCTRL_SUPPORTS_RPM_WRITE = 8;
public const int ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED = 1;
public const int ATI_VENDOR_ID1 = 1002;
public const int ATI_VENDOR_ID2 = 0x1002;
@@ -149,6 +150,10 @@ namespace OpenHardwareMonitor.Hardware.ATI {
public delegate int ADL_Overdrive5_FanSpeedInfo_GetDelegate(
int adapterIndex, int thermalControllerIndex,
ref ADLFanSpeedInfo fanSpeedInfo);
public delegate int ADL_Overdrive5_FanSpeedToDefault_SetDelegate(
int adapterIndex, int thermalControllerIndex);
public delegate int ADL_Overdrive5_FanSpeed_SetDelegate(int adapterIndex,
int thermalControllerIndex, ref ADLFanSpeedValue fanSpeedValue);
private static ADL_Main_Control_CreateDelegate
_ADL_Main_Control_Create;
@@ -173,6 +178,10 @@ namespace OpenHardwareMonitor.Hardware.ATI {
ADL_Overdrive5_FanSpeed_Get;
public static ADL_Overdrive5_FanSpeedInfo_GetDelegate
ADL_Overdrive5_FanSpeedInfo_Get;
public static ADL_Overdrive5_FanSpeedToDefault_SetDelegate
ADL_Overdrive5_FanSpeedToDefault_Set;
public static ADL_Overdrive5_FanSpeed_SetDelegate
ADL_Overdrive5_FanSpeed_Set;
private static string dllName;
@@ -215,6 +224,10 @@ namespace OpenHardwareMonitor.Hardware.ATI {
out ADL_Overdrive5_FanSpeed_Get);
GetDelegate("ADL_Overdrive5_FanSpeedInfo_Get",
out ADL_Overdrive5_FanSpeedInfo_Get);
GetDelegate("ADL_Overdrive5_FanSpeedToDefault_Set",
out ADL_Overdrive5_FanSpeedToDefault_Set);
GetDelegate("ADL_Overdrive5_FanSpeed_Set",
out ADL_Overdrive5_FanSpeed_Set);
}
static ADL() {

View File

@@ -51,7 +51,10 @@ namespace OpenHardwareMonitor.Hardware.ATI {
private readonly Sensor memoryClock;
private readonly Sensor coreVoltage;
private readonly Sensor coreLoad;
private readonly Sensor fanControl;
private readonly Sensor controlSensor;
private readonly Control fanControl;
private ADLFanSpeedValue initialFanSpeedValue;
public ATIGPU(string name, int adapterIndex, int busNumber,
int deviceNumber, ISettings settings)
@@ -61,16 +64,61 @@ namespace OpenHardwareMonitor.Hardware.ATI {
this.busNumber = busNumber;
this.deviceNumber = deviceNumber;
this.initialFanSpeedValue = new ADLFanSpeedValue();
this.initialFanSpeedValue.SpeedType =
ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0,
ref this.initialFanSpeedValue);
this.temperature = new Sensor("GPU Core", 0, SensorType.Temperature, this, settings);
this.fan = new Sensor("GPU Fan", 0, SensorType.Fan, this, settings);
this.coreClock = new Sensor("GPU Core", 0, SensorType.Clock, this, settings);
this.memoryClock = new Sensor("GPU Memory", 1, SensorType.Clock, this, settings);
this.coreVoltage = new Sensor("GPU Core", 0, SensorType.Voltage, this, settings);
this.coreLoad = new Sensor("GPU Core", 0, SensorType.Load, this, settings);
this.fanControl = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
this.controlSensor = new Sensor("GPU Fan", 0, SensorType.Control, this, settings);
ADLFanSpeedInfo afsi = new ADLFanSpeedInfo();
if (ADL.ADL_Overdrive5_FanSpeedInfo_Get(adapterIndex, 0, ref afsi)
!= ADL.ADL_OK)
{
afsi.MaxPercent = 100;
afsi.MinPercent = 0;
}
this.fanControl = new Control(controlSensor, settings, afsi.MinPercent,
afsi.MaxPercent);
this.fanControl.ControlModeChanged += ControlModeChanged;
this.fanControl.SoftwareControlValueChanged +=
SoftwareControlValueChanged;
ControlModeChanged(fanControl);
this.controlSensor.Control = fanControl;
Update();
}
private void SoftwareControlValueChanged(IControl control) {
if (control.ControlMode == ControlMode.Software) {
ADLFanSpeedValue adlf = new ADLFanSpeedValue();
adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
adlf.Flags = ADL.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
adlf.FanSpeed = (int)control.SoftwareValue;
ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, ref adlf);
}
}
private void ControlModeChanged(IControl control) {
if (control.ControlMode == ControlMode.Default) {
ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0,
ref this.initialFanSpeedValue);
} else {
ADLFanSpeedValue adlf = new ADLFanSpeedValue();
adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
adlf.Flags = ADL.ADL_DL_FANCTRL_FLAG_USER_DEFINED_SPEED;
adlf.FanSpeed = (int)control.SoftwareValue;
ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0, ref adlf);
}
}
public int BusNumber { get { return busNumber; } }
public int DeviceNumber { get { return deviceNumber; } }
@@ -116,10 +164,10 @@ namespace OpenHardwareMonitor.Hardware.ATI {
adlf.SpeedType = ADL.ADL_DL_FANCTRL_SPEED_TYPE_PERCENT;
if (ADL.ADL_Overdrive5_FanSpeed_Get(adapterIndex, 0, ref adlf)
== ADL.ADL_OK) {
fanControl.Value = adlf.FanSpeed;
ActivateSensor(fanControl);
controlSensor.Value = adlf.FanSpeed;
ActivateSensor(controlSensor);
} else {
fanControl.Value = null;
controlSensor.Value = null;
}
ADLPMActivity adlp = new ADLPMActivity();
@@ -150,5 +198,14 @@ namespace OpenHardwareMonitor.Hardware.ATI {
coreLoad.Value = null;
}
}
public void Close() {
this.fanControl.ControlModeChanged -= ControlModeChanged;
this.fanControl.SoftwareControlValueChanged -=
SoftwareControlValueChanged;
ADL.ADL_Overdrive5_FanSpeed_Set(adapterIndex, 0,
ref this.initialFanSpeedValue);
}
}
}

View File

@@ -144,6 +144,8 @@ namespace OpenHardwareMonitor.Hardware.ATI {
public void Close() {
try {
foreach (ATIGPU gpu in hardware)
gpu.Close();
ADL.ADL_Main_Control_Destroy();
} catch (Exception) { }
}

143
Hardware/Control.cs Normal file
View File

@@ -0,0 +1,143 @@
/*
Version: MPL 1.1/GPL 2.0/LGPL 2.1
The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the License.
The Original Code is the Open Hardware Monitor code.
The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>.
Portions created by the Initial Developer are Copyright (C) 2010
the Initial Developer. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
*/
using System;
using System.Globalization;
namespace OpenHardwareMonitor.Hardware {
internal delegate void ControlEventHandler(Control control);
internal class Control : IControl {
private readonly Identifier identifier;
private readonly ISettings settings;
private ControlMode mode;
private float softwareValue;
private float minSoftwareValue;
private float maxSoftwareValue;
public Control(ISensor sensor, ISettings settings, float minSoftwareValue,
float maxSoftwareValue)
{
this.identifier = new Identifier(sensor.Identifier, "control");
this.settings = settings;
this.minSoftwareValue = minSoftwareValue;
this.maxSoftwareValue = maxSoftwareValue;
if (!float.TryParse(settings.GetValue(
new Identifier(identifier, "value").ToString(), "0"),
NumberStyles.Float, CultureInfo.InvariantCulture,
out this.softwareValue))
{
this.softwareValue = 0;
}
int mode;
if (!int.TryParse(settings.GetValue(
new Identifier(identifier, "mode").ToString(),
((int)ControlMode.Default).ToString(CultureInfo.InvariantCulture)),
NumberStyles.Integer, CultureInfo.InvariantCulture,
out mode))
{
this.mode = ControlMode.Default;
} else {
this.mode = (ControlMode)mode;
}
}
public Identifier Identifier {
get {
return identifier;
}
}
public ControlMode ControlMode {
get {
return mode;
}
private set {
if (mode != value) {
mode = value;
if (ControlModeChanged != null)
ControlModeChanged(this);
this.settings.SetValue(new Identifier(identifier, "mode").ToString(),
((int)mode).ToString(CultureInfo.InvariantCulture));
}
}
}
public float SoftwareValue {
get {
return softwareValue;
}
private set {
if (softwareValue != value) {
softwareValue = value;
if (SoftwareControlValueChanged != null)
SoftwareControlValueChanged(this);
this.settings.SetValue(new Identifier(identifier,
"value").ToString(),
value.ToString(CultureInfo.InvariantCulture));
}
}
}
public void SetDefault() {
ControlMode = ControlMode.Default;
}
public float MinSoftwareValue {
get {
return minSoftwareValue;
}
}
public float MaxSoftwareValue {
get {
return maxSoftwareValue;
}
}
public void SetSoftware(float value) {
ControlMode = ControlMode.Software;
SoftwareValue = value;
}
internal event ControlEventHandler ControlModeChanged;
internal event ControlEventHandler SoftwareControlValueChanged;
}
}

View File

@@ -55,13 +55,13 @@ namespace OpenHardwareMonitor.Hardware {
get { return active.ToArray(); }
}
protected void ActivateSensor(Sensor sensor) {
protected void ActivateSensor(ISensor sensor) {
if (active.Add(sensor))
if (SensorAdded != null)
SensorAdded(sensor);
}
protected void DeactivateSensor(Sensor sensor) {
protected void DeactivateSensor(ISensor sensor) {
if (active.Remove(sensor))
if (SensorRemoved != null)
SensorRemoved(sensor);

61
Hardware/IControl.cs Normal file
View File

@@ -0,0 +1,61 @@
/*
Version: MPL 1.1/GPL 2.0/LGPL 2.1
The contents of this file are subject to the Mozilla Public License Version
1.1 (the "License"); you may not use this file except in compliance with
the License. You may obtain a copy of the License at
http://www.mozilla.org/MPL/
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the License.
The Original Code is the Open Hardware Monitor code.
The Initial Developer of the Original Code is
Michael Möller <m.moeller@gmx.ch>.
Portions created by the Initial Developer are Copyright (C) 2010
the Initial Developer. All Rights Reserved.
Contributor(s):
Alternatively, the contents of this file may be used under the terms of
either the GNU General Public License Version 2 or later (the "GPL"), or
the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
in which case the provisions of the GPL or the LGPL are applicable instead
of those above. If you wish to allow use of your version of this file only
under the terms of either the GPL or the LGPL, and not to allow others to
use your version of this file under the terms of the MPL, indicate your
decision by deleting the provisions above and replace them with the notice
and other provisions required by the GPL or the LGPL. If you do not delete
the provisions above, a recipient may use your version of this file under
the terms of any one of the MPL, the GPL or the LGPL.
*/
namespace OpenHardwareMonitor.Hardware {
public enum ControlMode {
Default,
Software
}
public interface IControl {
Identifier Identifier { get; }
ControlMode ControlMode { get; }
float SoftwareValue { get; }
void SetDefault();
float MinSoftwareValue { get; }
float MaxSoftwareValue { get; }
void SetSoftware(float value);
}
}

View File

@@ -87,6 +87,8 @@ namespace OpenHardwareMonitor.Hardware {
void ResetMax();
IEnumerable<SensorValue> Values { get; }
IControl Control { get; }
}
}

View File

@@ -82,6 +82,12 @@ namespace OpenHardwareMonitor.Hardware.LPC {
return value;
}
private bool WriteByte(byte register, byte value) {
Ring0.WriteIoPort(addressReg, register);
Ring0.WriteIoPort(dataReg, value);
return register == Ring0.ReadIoPort(addressReg);
}
public byte? ReadGPIO(int index) {
if (index >= gpioCount)
return null;

View File

@@ -57,6 +57,7 @@ namespace OpenHardwareMonitor.Hardware {
private readonly Queue<SensorValue> values =
new Queue<SensorValue>(MAX_MINUTES * 15);
private readonly ISettings settings;
private IControl control;
private float sum;
private int count;
@@ -186,5 +187,14 @@ namespace OpenHardwareMonitor.Hardware {
foreach (IParameter parameter in parameters)
parameter.Accept(visitor);
}
public IControl Control {
get {
return control;
}
internal set {
this.control = value;
}
}
}
}

View File

@@ -59,6 +59,8 @@
<Compile Include="Hardware\ATI\ADL.cs" />
<Compile Include="Hardware\ATI\ATIGPU.cs" />
<Compile Include="Hardware\ATI\ATIGroup.cs" />
<Compile Include="Hardware\Control.cs" />
<Compile Include="Hardware\IControl.cs" />
<Compile Include="Hardware\IOControlCode.cs" />
<Compile Include="Hardware\Computer.cs" />
<Compile Include="Hardware\CPU\AMDCPU.cs" />