42 lines
1.5 KiB
C#
42 lines
1.5 KiB
C#
namespace ChromeboxFanControl;
|
||
|
||
/// <summary>
|
||
/// Fan curve: 14 control points at 0 °C and 40–100 °C every 5 °C, linear interpolation.
|
||
/// </summary>
|
||
public static class FanCurve
|
||
{
|
||
private const int PointCount = 14;
|
||
|
||
/// <summary>Temperature breakpoints (°C): 0, 40, 45, 50, …, 100.</summary>
|
||
public static readonly int[] TempBreakpoints = [0, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100];
|
||
|
||
/// <param name="tempC">CPU temperature in °C.</param>
|
||
/// <param name="curve">Exactly 14 values 0–100 (fan duty).</param>
|
||
public static byte CalculateFanPercent(double tempC, ReadOnlySpan<int> curve)
|
||
{
|
||
if (curve.Length != PointCount)
|
||
throw new ArgumentException($"Curve must contain exactly {PointCount} points.", nameof(curve));
|
||
|
||
var t = Math.Clamp(tempC, 0, 100);
|
||
if (t <= TempBreakpoints[0])
|
||
return (byte)Math.Clamp(curve[0], 0, 100);
|
||
if (t >= TempBreakpoints[PointCount - 1])
|
||
return (byte)Math.Clamp(curve[PointCount - 1], 0, 100);
|
||
|
||
for (var i = 0; i < PointCount - 1; i++)
|
||
{
|
||
var t0 = TempBreakpoints[i];
|
||
var t1 = TempBreakpoints[i + 1];
|
||
if (t >= t0 && t <= t1)
|
||
{
|
||
var d0 = Math.Clamp(curve[i], 0, 100);
|
||
var d1 = Math.Clamp(curve[i + 1], 0, 100);
|
||
var frac = (t - t0) / (t1 - t0);
|
||
return (byte)Math.Round(d0 + (d1 - d0) * frac);
|
||
}
|
||
}
|
||
|
||
return (byte)Math.Clamp(curve[PointCount - 1], 0, 100);
|
||
}
|
||
}
|