Skip to content

Commit fcef71a

Browse files
committed
RAMSPDToolkit Update + timings added
* Workaround for page changing on DDR5 systems with SPD Write Protection active has been implemented in new version of RAMSPDToolkit. Code for LHM has been adjusted accordingly. Added more sensors (timings). * Move abbreviation of timings to start of string. * Simplify names for timings. * Update version. * Remove extra padding.
1 parent 7b4b2f6 commit fcef71a

7 files changed

Lines changed: 110 additions & 28 deletions

File tree

OpenHardwareMonitor/UI/SensorGadget.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,9 @@ protected override void OnPaint(PaintEventArgs e)
632632
case SensorType.TimeSpan:
633633
format = "{0:g}";
634634
break;
635+
case SensorType.Timing:
636+
format = "{0:F3} ns";
637+
break;
635638
case SensorType.Energy:
636639
format = "{0:F0} mWh";
637640
break;

OpenHardwareMonitor/UI/SensorNode.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ public SensorNode(ISensor sensor, PersistentSettings settings)
6969
case SensorType.TimeSpan:
7070
Format = "{0:g}";
7171
break;
72+
case SensorType.Timing:
73+
Format = "{0:F3} ns";
74+
break;
7275
case SensorType.Energy:
7376
Format = "{0:F0} mWh";
7477
break;

OpenHardwareMonitor/UI/SensorNotifyIcon.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ private string GetString()
114114
{
115115
SensorType.Temperature => UnitManager.IsFahrenheitUsed ? $"{UnitManager.CelsiusToFahrenheit(Sensor.Value):F0}" : Sensor.Value.Value.ToTrayValue(),
116116
SensorType.TimeSpan => $"{TimeSpan.FromSeconds(Sensor.Value.Value):g}",
117+
SensorType.Timing => $"{Sensor.Value.Value:F3}",
117118
SensorType.Clock or SensorType.Fan or SensorType.Flow => $"{1e-3f * Sensor.Value:F1}",
118119
SensorType.Throughput => GetThroughputValue(Sensor.Value ?? 0),
119120
_ => Sensor.Value.Value.ToTrayValue(),
@@ -171,6 +172,7 @@ public void Update()
171172
SensorType.Noise => "\n{0}: {0:F0} dBA",
172173
SensorType.Conductivity => "\n{0}: {0:F1} µS/cm",
173174
SensorType.Humidity => "\n{0}: {0:F0} %",
175+
SensorType.Timing => "\n{0}: {0:F3} ns",
174176
_ => "\n{0}: {1}",
175177
};
176178
string formattedValue = Sensor.SensorType switch

OpenHardwareMonitor/UI/TypeNode.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@ public TypeNode(SensorType sensorType, Identifier parentId, PersistentSettings s
8686
Image = EmbeddedResources.GetImage("time.png");
8787
Text = "Times";
8888
break;
89+
case SensorType.Timing:
90+
Image = Utilities.EmbeddedResources.GetImage("time.png");
91+
Text = "Timings";
92+
break;
8993
case SensorType.Noise:
9094
Image = EmbeddedResources.GetImage("loudspeaker.png");
9195
Text = "Noise Levels";

OpenHardwareMonitorLib/Hardware/ISensor.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ public enum SensorType
2525
SmallData, // MB = 2^20 Bytes
2626
Throughput, // B/s
2727
TimeSpan, // Seconds
28+
Timing, // ns
2829
Energy, // milliwatt-hour (mWh)
2930
Noise, // dBA
3031
Conductivity, // µS/cm
Lines changed: 95 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
using OpenHardwareMonitor.Hardware.Memory.Sensors;
22
using RAMSPDToolkit.SPD;
3-
using RAMSPDToolkit.SPD.Enums;
43
using RAMSPDToolkit.SPD.Interfaces;
54
using RAMSPDToolkit.SPD.Interop.Shared;
65

@@ -13,40 +12,36 @@ internal sealed class DimmMemory : Hardware
1312
public DimmMemory(SPDAccessor accessor, string name, Identifier identifier, ISettings settings)
1413
: base(name, identifier, settings)
1514
{
16-
//Check which kind of RAM we have
17-
switch (accessor.MemoryType())
15+
//Only add thermal sensor if present
16+
if (accessor is IThermalSensor ts && ts.HasThermalSensor)
1817
{
19-
case SPDMemoryType.SPD_DDR4_SDRAM:
20-
case SPDMemoryType.SPD_DDR4E_SDRAM:
21-
case SPDMemoryType.SPD_LPDDR4_SDRAM:
22-
case SPDMemoryType.SPD_LPDDR4X_SDRAM:
23-
_thermalSensor = new SpdThermalSensor($"DIMM #{accessor.Index}",
24-
accessor.Index,
25-
SensorType.Temperature,
26-
this,
27-
settings,
28-
accessor as IThermalSensor);
29-
30-
break;
31-
case SPDMemoryType.SPD_DDR5_SDRAM:
32-
case SPDMemoryType.SPD_LPDDR5_SDRAM:
33-
//Check if we are on correct page or if write protection is not enabled
34-
if (accessor.PageData.HasFlag(PageData.ThermalData) || !accessor.HasSPDWriteProtection)
35-
{
18+
//Check which kind of RAM we have
19+
switch (accessor.MemoryType())
20+
{
21+
case SPDMemoryType.SPD_DDR4_SDRAM:
22+
case SPDMemoryType.SPD_DDR4E_SDRAM:
23+
case SPDMemoryType.SPD_LPDDR4_SDRAM:
24+
case SPDMemoryType.SPD_LPDDR4X_SDRAM:
25+
case SPDMemoryType.SPD_DDR5_SDRAM:
26+
case SPDMemoryType.SPD_LPDDR5_SDRAM:
3627
_thermalSensor = new SpdThermalSensor($"DIMM #{accessor.Index}",
3728
accessor.Index,
3829
SensorType.Temperature,
3930
this,
4031
settings,
4132
accessor as IThermalSensor);
42-
}
43-
44-
break;
33+
break;
34+
}
4535
}
4636

37+
bool hasThermalSensor = _thermalSensor != null;
38+
4739
//Add thermal sensor
48-
if (_thermalSensor != null)
40+
if (hasThermalSensor)
4941
ActivateSensor(_thermalSensor);
42+
43+
//Add other sensors
44+
CreateSensors(accessor, hasThermalSensor);
5045
}
5146

5247
public override HardwareType HardwareType => HardwareType.Memory;
@@ -55,4 +50,80 @@ public override void Update()
5550
{
5651
_thermalSensor?.UpdateSensor();
5752
}
53+
54+
private void CreateSensors(SPDAccessor accessor, bool hasThermalSensor)
55+
{
56+
if (accessor is DDR4Accessor ddr4)
57+
{
58+
CreateSensorsDDR4(ddr4, hasThermalSensor);
59+
}
60+
else if (accessor is DDR5Accessor ddr5)
61+
{
62+
CreateSensorsDDR5(ddr5, hasThermalSensor);
63+
}
64+
}
65+
66+
private void CreateSensorsDDR4(DDR4Accessor accessor, bool hasThermalSensor)
67+
{
68+
if (hasThermalSensor)
69+
{
70+
//Temperature Resolution (fixed value)
71+
AddSensor("Temperature Sensor Resolution", 0, false, SensorType.Temperature, accessor.TemperatureResolution);
72+
}
73+
74+
//Timings
75+
AddSensor("tCKAVGmin (Minimum Cycle Time)", 1, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumCycleTime);
76+
AddSensor("tCKAVGmax (Maximum Cycle Time)", 2, false, SensorType.Timing, (float)accessor.SDRAMTimings.MaximumCycleTime);
77+
AddSensor("tAA (CAS Latency Time)", 3, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumCASLatencyTime);
78+
AddSensor("tRCD (RAS to CAS Delay Time)", 4, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumRASToCASDelayTime);
79+
AddSensor("tRP (Row Precharge Delay Time)", 5, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumRowPrechargeDelayTime);
80+
AddSensor("tRAS (Active to Precharge Delay Time)", 6, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumActiveToPrechargeDelayTime);
81+
AddSensor("tRC (Active to Active/Refresh Delay Time)", 7, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumActiveToActiveRefreshDelayTime);
82+
AddSensor("tRFC1 (Refresh Recovery Delay Time)", 8, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumRefreshRecoveryDelayTime1);
83+
AddSensor("tRFC2 (Refresh Recovery Delay Time)", 9, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumRefreshRecoveryDelayTime2);
84+
AddSensor("tRFC4 (Refresh Recovery Delay Time)", 10, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumRefreshRecoveryDelayTime4);
85+
AddSensor("tFAW (Four Activate Window Time)", 11, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumFourActivateWindowTime);
86+
AddSensor("tRRD_S (Activate to Activate Delay Time)", 12, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumActivateToActivateDelay_DiffGroup);
87+
AddSensor("tRRD_L (Activate to Activate Delay Time)", 13, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumActivateToActivateDelay_SameGroup);
88+
AddSensor("tCCD_L (CAS to CAS Delay Time)", 14, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumCASToCASDelay_SameGroup);
89+
AddSensor("tWR (Write Recovery Time)", 15, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumWriteRecoveryTime);
90+
AddSensor("tWTR_S (Write to Read Time)", 16, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumWriteToReadTime_DiffGroup);
91+
AddSensor("tWTR_L (Write to Read Time)", 17, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumWriteToReadTime_SameGroup);
92+
93+
}
94+
95+
private void CreateSensorsDDR5(DDR5Accessor accessor, bool hasThermalSensor)
96+
{
97+
if (hasThermalSensor)
98+
{
99+
//Temperature Resolution (fixed value)
100+
AddSensor("Temperature Sensor Resolution", 0, false, SensorType.Temperature, accessor.TemperatureResolution);
101+
}
102+
103+
//Timings
104+
AddSensor("tCKAVGmin (Minimum Cycle Time)", 1, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumCycleTime);
105+
AddSensor("tCKAVGmax (Maximum Cycle Time)", 2, false, SensorType.Timing, (float)accessor.SDRAMTimings.MaximumCycleTime);
106+
AddSensor("tAA (CAS Latency Time)", 3, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumCASLatencyTime);
107+
AddSensor("tRCD (RAS to CAS Delay Time)", 4, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumRASToCASDelayTime);
108+
AddSensor("tRP (Row Precharge Delay Time)", 5, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumRowPrechargeDelayTime);
109+
AddSensor("tRAS (Active to Precharge Delay Time)", 6, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumActiveToPrechargeDelayTime);
110+
AddSensor("tRC (Active to Active/Refresh Delay Time)", 7, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumActiveToActiveRefreshDelayTime);
111+
AddSensor("tWR (Write Recovery Time)", 8, false, SensorType.Timing, (float)accessor.SDRAMTimings.MinimumWriteRecoveryTime);
112+
AddSensor("tRFC1 (Normal Refresh Recovery Time)", 9, false, SensorType.Timing, (float)accessor.SDRAMTimings.NormalRefreshRecoveryTime);
113+
AddSensor("tRFC2 (Fine Granularity Refresh Recovery Time)", 10, false, SensorType.Timing, (float)accessor.SDRAMTimings.FineGranularityRefreshRecoveryTime);
114+
AddSensor("tRFCsb (Same Bank Refresh Recovery Time)", 11, false, SensorType.Timing, (float)accessor.SDRAMTimings.SameBankRefreshRecoveryTime);
115+
AddSensor("tRFC1_dlr (Normal Refresh Recovery Time 3DS)", 12, false, SensorType.Timing, (float)accessor.SDRAMTimings.NormalRefreshRecoveryTime_3DSDifferentLogicalRank);
116+
AddSensor("tRFC2_dlr (Fine Granularity Refresh Recovery Time 3DS)", 13, false, SensorType.Timing, (float)accessor.SDRAMTimings.FineGranularityRefreshRecoveryTime_3DSDifferentLogicalRank);
117+
AddSensor("tRFCsb_dlr (Same Bank Refresh Recovery Time 3DS)", 14, false, SensorType.Timing, (float)accessor.SDRAMTimings.SameBankRefreshRecoveryTime_3DSDifferentLogicalRank);
118+
}
119+
120+
private void AddSensor(string name, int index, bool defaultHidden, SensorType sensorType, float value)
121+
{
122+
var sensor = new Sensor(name, index, defaultHidden, sensorType, this, null, _settings)
123+
{
124+
Value = value,
125+
};
126+
127+
ActivateSensor(sensor);
128+
}
58129
}

OpenHardwareMonitorLib/Hardware/Memory/MemoryGroup.cs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
using RAMSPDToolkit.I2CSMBus;
88
using RAMSPDToolkit.SPD;
99
using RAMSPDToolkit.SPD.Enums;
10-
using RAMSPDToolkit.SPD.Interfaces;
1110
using RAMSPDToolkit.SPD.Interop.Shared;
1211
using RAMSPDToolkit.Windows.Driver;
1312

@@ -147,9 +146,8 @@ private static bool DetectThermalSensors(out List<SPDAccessor> accessors)
147146
//RAM available and detected
148147
if (detector.Accessor != null)
149148
{
150-
//We are only interested in modules with thermal sensor
151-
if (detector.Accessor is IThermalSensor { HasThermalSensor: true })
152-
accessors.Add(detector.Accessor);
149+
//Add all detected modules
150+
accessors.Add(detector.Accessor);
153151

154152
ramDetected = true;
155153
}

0 commit comments

Comments
 (0)