Skip to content

Commit

Permalink
✨ Add NVidia usage sensors.
Browse files Browse the repository at this point in the history
  • Loading branch information
hexawyz committed Apr 15, 2024
1 parent abd1c65 commit 82ffd66
Show file tree
Hide file tree
Showing 18 changed files with 850 additions and 445 deletions.
17 changes: 16 additions & 1 deletion Exo.Core/Sensors/ISensor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,26 @@ public interface IStreamedSensor<TValue> : ISensor<TValue>
bool ISensor.IsPolled => false;

/// <summary>Enumerates values from the sensor.</summary>
/// <remarks>Implementations can assume that there will always be at most a single enumeration per sensor at a given time.</remarks>
/// <param name="cancellationToken"></param>
/// <returns></returns>
IAsyncEnumerable<TValue> EnumerateValuesAsync(CancellationToken cancellationToken);
IAsyncEnumerable<SensorDataPoint<TValue>> EnumerateValuesAsync(CancellationToken cancellationToken);
}

public readonly struct SensorDataPoint<TValue>
where TValue : struct, INumber<TValue>
{
public SensorDataPoint(DateTime dateTime, TValue value)
{
DateTime = dateTime;
Value = value;
}

public DateTime DateTime { get; }
public TValue Value { get; }
}


public enum GroupedQueryMode : byte
{
None = 0,
Expand Down
83 changes: 83 additions & 0 deletions Exo.Devices.NVidia/NVidiaGpuDriver.FixedColorLightingZone.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
using Exo.Lighting;
using Exo.Lighting.Effects;

namespace Exo.Devices.NVidia;

public partial class NVidiaGpuDriver
{
private class FixedColorLightingZone : LightingZone, ILightingZoneEffect<DisabledEffect>, ILightingZoneEffect<StaticBrightnessEffect>
{
private byte _brightness;

public FixedColorLightingZone(object @lock, int index, Guid zoneId, byte initialBrightness) : base(@lock, index, zoneId)
{
if (initialBrightness != 0)
{
_brightness = Math.Max(initialBrightness, (byte)100);
Effect = LightingEffect.Static;
}
}

protected override ILightingEffect GetCurrentEffect()
=> Effect switch
{
LightingEffect.Disabled => DisabledEffect.SharedInstance,
LightingEffect.Static => new StaticBrightnessEffect(_brightness),
_ => DisabledEffect.SharedInstance,
};

void ILightingZoneEffect<DisabledEffect>.ApplyEffect(in DisabledEffect effect)
{
lock (Lock)
{
_brightness = default;
Effect = LightingEffect.Disabled;
}
}

bool ILightingZoneEffect<DisabledEffect>.TryGetCurrentEffect(out DisabledEffect effect)
{
lock (Lock)
{
effect = default;

if (Effect == LightingEffect.Disabled)
{
return true;
}

return false;
}
}

void ILightingZoneEffect<StaticBrightnessEffect>.ApplyEffect(in StaticBrightnessEffect effect)
{
lock (Lock)
{
_brightness = effect.BrightnessLevel;
Effect = LightingEffect.Static;
}
}

bool ILightingZoneEffect<StaticBrightnessEffect>.TryGetCurrentEffect(out StaticBrightnessEffect effect)
{
lock (Lock)
{
if (Effect == LightingEffect.Disabled)
{
effect = default;
return false;
}

effect = new(_brightness);
return true;
}
}

protected override void UpdateControl(ref NvApi.Gpu.Client.IlluminationZoneControl control)
{
control.ControlMode = NvApi.Gpu.Client.IlluminationControlMode.Manual;
control.Data.SingleColor.Manual = new() { BrightnessPercentage = _brightness };
}
}
}
11 changes: 11 additions & 0 deletions Exo.Devices.NVidia/NVidiaGpuDriver.LightingEffect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Exo.Devices.NVidia;

public partial class NVidiaGpuDriver
{
// GPUs that support "piecewise" effects could support more effects, but I don't have this on hand, so for now it is only disabled or static.
private enum LightingEffect : byte
{
Disabled = 0,
Static = 1,
}
}
32 changes: 32 additions & 0 deletions Exo.Devices.NVidia/NVidiaGpuDriver.LightingZone.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using Exo.Lighting;
using Exo.Lighting.Effects;

namespace Exo.Devices.NVidia;

public partial class NVidiaGpuDriver
{
private abstract class LightingZone : ILightingZone
{
protected object Lock { get; }
private readonly int _index;
protected LightingEffect Effect;

public Guid ZoneId { get; }

protected LightingZone(object @lock, int index, Guid zoneId)
{
Lock = @lock;
_index = index;
ZoneId = zoneId;
}

internal void UpdateControl(NvApi.Gpu.Client.IlluminationZoneControl[] controls)
=> UpdateControl(ref controls[_index]);

protected abstract void UpdateControl(ref NvApi.Gpu.Client.IlluminationZoneControl control);

ILightingEffect ILightingZone.GetCurrentEffect() => GetCurrentEffect();

protected abstract ILightingEffect GetCurrentEffect();
}
}
44 changes: 44 additions & 0 deletions Exo.Devices.NVidia/NVidiaGpuDriver.MonitorI2CBus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using Exo.I2C;

namespace Exo.Devices.NVidia;

public partial class NVidiaGpuDriver
{
private sealed class MonitorI2CBus : II2CBus
{
private readonly NvApi.PhysicalGpu _gpu;
private readonly uint _outputId;

public MonitorI2CBus(NvApi.PhysicalGpu gpu, uint outputId)
{
_gpu = gpu;
_outputId = outputId;
}

public ValueTask WriteAsync(byte address, ReadOnlyMemory<byte> bytes, CancellationToken cancellationToken)
{
_gpu.I2CMonitorWrite(_outputId, (byte)(address << 1), bytes);
return ValueTask.CompletedTask;
}

public ValueTask WriteAsync(byte address, byte register, ReadOnlyMemory<byte> bytes, CancellationToken cancellationToken)
{
_gpu.I2CMonitorWrite(_outputId, (byte)(address << 1), register, bytes);
return ValueTask.CompletedTask;
}

public ValueTask ReadAsync(byte address, Memory<byte> bytes, CancellationToken cancellationToken)
{
_gpu.I2CMonitorRead(_outputId, (byte)(address << 1), bytes);
return ValueTask.CompletedTask;
}

public ValueTask ReadAsync(byte address, byte register, Memory<byte> bytes, CancellationToken cancellationToken)
{
_gpu.I2CMonitorRead(_outputId, (byte)(address << 1), register, bytes);
return ValueTask.CompletedTask;
}

public ValueTask DisposeAsync() => ValueTask.CompletedTask;
}
}
84 changes: 84 additions & 0 deletions Exo.Devices.NVidia/NVidiaGpuDriver.RgbLightingZone.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using Exo.ColorFormats;
using Exo.Lighting;
using Exo.Lighting.Effects;

namespace Exo.Devices.NVidia;

public partial class NVidiaGpuDriver
{
private class RgbLightingZone : LightingZone, ILightingZoneEffect<DisabledEffect>, ILightingZoneEffect<StaticColorEffect>
{
private RgbColor _color;

public RgbLightingZone(object @lock, int index, Guid zoneId, RgbColor initialColor) : base(@lock, index, zoneId)
{
if (initialColor != default)
{
_color = initialColor;
Effect = LightingEffect.Static;
}
}

protected override ILightingEffect GetCurrentEffect()
=> Effect switch
{
LightingEffect.Disabled => DisabledEffect.SharedInstance,
LightingEffect.Static => new StaticColorEffect(_color),
_ => DisabledEffect.SharedInstance,
};

void ILightingZoneEffect<StaticColorEffect>.ApplyEffect(in StaticColorEffect effect)
{
lock (Lock)
{
_color = effect.Color;
Effect = LightingEffect.Static;
}
}

bool ILightingZoneEffect<StaticColorEffect>.TryGetCurrentEffect(out StaticColorEffect effect)
{
lock (Lock)
{
if (Effect == LightingEffect.Disabled)
{
effect = default;
return false;
}

effect = new(_color);
return true;
}
}

void ILightingZoneEffect<DisabledEffect>.ApplyEffect(in DisabledEffect effect)
{
lock (Lock)
{
_color = default;
Effect = LightingEffect.Disabled;
}
}

bool ILightingZoneEffect<DisabledEffect>.TryGetCurrentEffect(out DisabledEffect effect)
{
lock (Lock)
{
effect = default;

if (Effect == LightingEffect.Disabled)
{
return true;
}

return false;
}
}

protected override void UpdateControl(ref NvApi.Gpu.Client.IlluminationZoneControl control)
{
control.ControlMode = NvApi.Gpu.Client.IlluminationControlMode.Manual;
control.Data.Rgb.Manual = new() { R = _color.R, G = _color.G, B = _color.B, BrightnessPercentage = _color == default ? (byte)0 : (byte)100 };
}
}
}
95 changes: 95 additions & 0 deletions Exo.Devices.NVidia/NVidiaGpuDriver.RgbwLightingZone.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using Exo.ColorFormats;
using Exo.Lighting;
using Exo.Lighting.Effects;

namespace Exo.Devices.NVidia;

public partial class NVidiaGpuDriver
{
// TODO: Implement a proper conversion from RGB to RGBW.
private class RgbwLightingZone : LightingZone, ILightingZoneEffect<DisabledEffect>, ILightingZoneEffect<StaticColorEffect>
{
private RgbwColor _color;

public RgbwLightingZone(object @lock, int index, Guid zoneId, RgbwColor color) : base(@lock, index, zoneId)
{
if (color != default)
{
_color = color;
Effect = LightingEffect.Static;
}
}

protected override ILightingEffect GetCurrentEffect()
=> Effect switch
{
LightingEffect.Disabled => DisabledEffect.SharedInstance,
LightingEffect.Static => new StaticColorEffect(_color.ToRgb()),
_ => DisabledEffect.SharedInstance,
};

void ILightingZoneEffect<DisabledEffect>.ApplyEffect(in DisabledEffect effect)
{
lock (Lock)
{
_color = default;
Effect = LightingEffect.Disabled;
}
}

bool ILightingZoneEffect<DisabledEffect>.TryGetCurrentEffect(out DisabledEffect effect)
{
lock (Lock)
{
effect = default;

if (Effect == LightingEffect.Disabled)
{
return true;
}

return false;
}
}

void ILightingZoneEffect<StaticColorEffect>.ApplyEffect(in StaticColorEffect effect)
{
lock (Lock)
{
_color = RgbwColor.FromRgb(effect.Color);
Effect = LightingEffect.Static;
}
}

bool ILightingZoneEffect<StaticColorEffect>.TryGetCurrentEffect(out StaticColorEffect effect)
{
lock (Lock)
{
if (Effect == LightingEffect.Disabled)
{
effect = default;
return false;
}

effect = new(_color.ToRgb());
return true;
}
}

protected override void UpdateControl(ref NvApi.Gpu.Client.IlluminationZoneControl control)
{
switch (Effect)
{
case LightingEffect.Disabled:
control.ControlMode = NvApi.Gpu.Client.IlluminationControlMode.Manual;
control.Data.Rgbw.Manual = default;
break;
case LightingEffect.Static:
byte brightness = _color == default ? (byte)0 : (byte)100;
control.ControlMode = NvApi.Gpu.Client.IlluminationControlMode.Manual;
control.Data.Rgbw.Manual = new() { R = _color.R, G = _color.G, B = _color.B, W = _color.W, BrightnessPercentage = brightness };
break;
}
}
}
}
Loading

0 comments on commit 82ffd66

Please sign in to comment.