Fixed the bus and core clock reading on AMD family 10h model Ah CPUs. The new "Core Performance Boost" feature of these CPUs resulted in very low accuracy of the bus speed (and as a consequence also an inaccurate TSC multiplier). This fixed Issue 205.
3 Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 The contents of this file are subject to the Mozilla Public License Version
6 1.1 (the "License"); you may not use this file except in compliance with
7 the License. You may obtain a copy of the License at
9 http://www.mozilla.org/MPL/
11 Software distributed under the License is distributed on an "AS IS" basis,
12 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 for the specific language governing rights and limitations under the License.
15 The Original Code is the Open Hardware Monitor code.
17 The Initial Developer of the Original Code is
18 Michael Möller <m.moeller@gmx.ch>.
19 Portions created by the Initial Developer are Copyright (C) 2009-2011
20 the Initial Developer. All Rights Reserved.
24 Alternatively, the contents of this file may be used under the terms of
25 either the GNU General Public License Version 2 or later (the "GPL"), or
26 the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 in which case the provisions of the GPL or the LGPL are applicable instead
28 of those above. If you wish to allow use of your version of this file only
29 under the terms of either the GPL or the LGPL, and not to allow others to
30 use your version of this file under the terms of the MPL, indicate your
31 decision by deleting the provisions above and replace them with the notice
32 and other provisions required by the GPL or the LGPL. If you do not delete
33 the provisions above, a recipient may use your version of this file under
34 the terms of any one of the MPL, the GPL or the LGPL.
39 using System.Collections.Generic;
40 using System.Globalization;
43 namespace OpenHardwareMonitor.Hardware.TBalancer {
44 internal class TBalancer : Hardware {
46 private readonly int portIndex;
47 private readonly byte protocolVersion;
48 private readonly Sensor[] digitalTemperatures = new Sensor[8];
49 private readonly Sensor[] analogTemperatures = new Sensor[4];
50 private readonly Sensor[] sensorhubTemperatures = new Sensor[6];
51 private readonly Sensor[] sensorhubFlows = new Sensor[2];
52 private readonly Sensor[] fans = new Sensor[4];
53 private readonly Sensor[] controls = new Sensor[4];
54 private readonly Sensor[] miniNGTemperatures = new Sensor[4];
55 private readonly Sensor[] miniNGFans = new Sensor[4];
56 private readonly Sensor[] miniNGControls = new Sensor[4];
57 private readonly List<ISensor> deactivating = new List<ISensor>();
59 private FT_HANDLE handle;
60 private int[] primaryData = new int[0];
61 private int[] alternativeData = new int[0];
63 public const byte STARTFLAG = 100;
64 public const byte ENDFLAG = 254;
66 private delegate void MethodDelegate();
67 private readonly MethodDelegate alternativeRequest;
69 public TBalancer(int portIndex, byte protocolVersion, ISettings settings)
70 : base("T-Balancer bigNG", new Identifier("bigng",
71 portIndex.ToString(CultureInfo.InvariantCulture)), settings)
74 this.portIndex = portIndex;
75 this.protocolVersion = protocolVersion;
77 ParameterDescription[] parameter = new [] {
78 new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
81 for (int i = 0; i < digitalTemperatures.Length; i++)
82 digitalTemperatures[i] = new Sensor("Digital Sensor " + i,
83 offset + i, SensorType.Temperature, this, parameter, settings);
84 offset += digitalTemperatures.Length;
86 for (int i = 0; i < analogTemperatures.Length; i++)
87 analogTemperatures[i] = new Sensor("Analog Sensor " + (i + 1),
88 offset + i, SensorType.Temperature, this, parameter, settings);
89 offset += analogTemperatures.Length;
91 for (int i = 0; i < sensorhubTemperatures.Length; i++)
92 sensorhubTemperatures[i] = new Sensor("Sensorhub Sensor " + i,
93 offset + i, SensorType.Temperature, this, parameter, settings);
94 offset += sensorhubTemperatures.Length;
96 for (int i = 0; i < miniNGTemperatures.Length; i++)
97 miniNGTemperatures[i] = new Sensor("miniNG #" + (i / 2 + 1) +
98 " Sensor " + (i % 2 + 1), offset + i, SensorType.Temperature,
99 this, parameter, settings);
100 offset += miniNGTemperatures.Length;
102 for (int i = 0; i < sensorhubFlows.Length; i++)
103 sensorhubFlows[i] = new Sensor("Flowmeter " + (i + 1),
104 i, SensorType.Flow, this, new [] {
105 new ParameterDescription("Impulse Rate",
106 "The impulse rate of the flowmeter in pulses/L", 509)
109 for (int i = 0; i < controls.Length; i++) {
110 controls[i] = new Sensor("Fan Channel " + i, i, SensorType.Control,
114 for (int i = 0; i < miniNGControls.Length; i++) {
115 miniNGControls[i] = new Sensor("miniNG #" + (i / 2 + 1) +
116 " Fan Channel " + (i % 2 + 1), 4 + i, SensorType.Control, this,
120 alternativeRequest = new MethodDelegate(DelayedAlternativeRequest);
126 protected override void ActivateSensor(ISensor sensor) {
127 deactivating.Remove(sensor);
128 base.ActivateSensor(sensor);
131 protected override void DeactivateSensor(ISensor sensor) {
132 if (deactivating.Contains(sensor)) {
133 deactivating.Remove(sensor);
134 base.DeactivateSensor(sensor);
135 } else if (active.Contains(sensor)) {
136 deactivating.Add(sensor);
140 private void ReadminiNG(int[] data, int number) {
141 int offset = 1 + number * 65;
143 if (data[offset + 61] != ENDFLAG)
146 for (int i = 0; i < 2; i++) {
147 Sensor sensor = miniNGTemperatures[number * 2 + i];
148 if (data[offset + 7 + i] > 0) {
149 sensor.Value = 0.5f * data[offset + 7 + i] +
150 sensor.Parameters[0].Value;
151 ActivateSensor(sensor);
153 DeactivateSensor(sensor);
157 for (int i = 0; i < 2; i++) {
158 if (miniNGFans[number * 2 + i] == null)
159 miniNGFans[number * 2 + i] =
160 new Sensor("miniNG #" + (number + 1) + " Fan Channel " + (i + 1),
161 4 + number * 2 + i, SensorType.Fan, this, settings);
163 Sensor sensor = miniNGFans[number * 2 + i];
165 sensor.Value = 20.0f * data[offset + 43 + 2 * i];
166 ActivateSensor(sensor);
169 for (int i = 0; i < 2; i++) {
170 Sensor sensor = miniNGControls[number * 2 + i];
171 sensor.Value = data[offset + 15 + i];
172 ActivateSensor(sensor);
176 private void ReadData() {
177 int[] data = new int[285];
178 for (int i = 0; i < data.Length; i++)
179 data[i] = FTD2XX.ReadByte(handle);
181 if (data[0] != STARTFLAG) {
182 FTD2XX.FT_Purge(handle, FT_PURGE.FT_PURGE_RX);
186 if (data[1] == 255 || data[1] == 88) { // bigNG
188 if (data[274] != protocolVersion)
191 this.primaryData = data;
193 for (int i = 0; i < digitalTemperatures.Length; i++)
194 if (data[238 + i] > 0) {
195 digitalTemperatures[i].Value = 0.5f * data[238 + i] +
196 digitalTemperatures[i].Parameters[0].Value;
197 ActivateSensor(digitalTemperatures[i]);
199 DeactivateSensor(digitalTemperatures[i]);
202 for (int i = 0; i < analogTemperatures.Length; i++)
203 if (data[260 + i] > 0) {
204 analogTemperatures[i].Value = 0.5f * data[260 + i] +
205 analogTemperatures[i].Parameters[0].Value;
206 ActivateSensor(analogTemperatures[i]);
208 DeactivateSensor(analogTemperatures[i]);
211 for (int i = 0; i < sensorhubTemperatures.Length; i++)
212 if (data[246 + i] > 0) {
213 sensorhubTemperatures[i].Value = 0.5f * data[246 + i] +
214 sensorhubTemperatures[i].Parameters[0].Value;
215 ActivateSensor(sensorhubTemperatures[i]);
217 DeactivateSensor(sensorhubTemperatures[i]);
220 for (int i = 0; i < sensorhubFlows.Length; i++)
221 if (data[231 + i] > 0 && data[234] > 0) {
222 float pulsesPerSecond = (data[231 + i] * 4.0f) / data[234];
223 float pulsesPerLiter = sensorhubFlows[i].Parameters[0].Value;
224 sensorhubFlows[i].Value = pulsesPerSecond * 3600 / pulsesPerLiter;
225 ActivateSensor(sensorhubFlows[i]);
227 DeactivateSensor(sensorhubFlows[i]);
230 for (int i = 0; i < fans.Length; i++) {
231 float maxRPM = 11.5f * ((data[149 + 2 * i] << 8) | data[148 + 2 * i]);
234 fans[i] = new Sensor("Fan Channel " + i, i, SensorType.Fan,
235 this, new [] { new ParameterDescription("MaxRPM",
236 "Maximum revolutions per minute (RPM) of the fan.", maxRPM)
240 if ((data[136] & (1 << i)) == 0) // pwm mode
241 value = 0.02f * data[137 + i];
243 value = 0.01f * data[141 + i];
245 fans[i].Value = fans[i].Parameters[0].Value * value;
246 ActivateSensor(fans[i]);
248 controls[i].Value = 100 * value;
249 ActivateSensor(controls[i]);
252 } else if (data[1] == 253) { // miniNG #1
253 this.alternativeData = data;
257 if (data[66] == 253) // miniNG #2
262 public override HardwareType HardwareType {
263 get { return HardwareType.TBalancer; }
266 public override string GetReport() {
267 StringBuilder r = new StringBuilder();
269 r.AppendLine("T-Balancer bigNG");
271 r.Append("Port Index: ");
272 r.AppendLine(portIndex.ToString(CultureInfo.InvariantCulture));
275 r.AppendLine("Primary System Information Answer");
277 r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
279 for (int i = 0; i <= 0x11; i++) {
281 r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture));
283 for (int j = 0; j <= 0xF; j++) {
284 int index = ((i << 4) | j);
285 if (index < primaryData.Length) {
287 r.Append(primaryData[index].ToString("X2", CultureInfo.InvariantCulture));
294 if (alternativeData.Length > 0) {
295 r.AppendLine("Alternative System Information Answer");
297 r.AppendLine(" 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
299 for (int i = 0; i <= 0x11; i++) {
301 r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture));
303 for (int j = 0; j <= 0xF; j++) {
304 int index = ((i << 4) | j);
305 if (index < alternativeData.Length) {
307 r.Append(alternativeData[index].ToString("X2", CultureInfo.InvariantCulture));
318 private void DelayedAlternativeRequest() {
319 System.Threading.Thread.Sleep(500);
320 FTD2XX.Write(handle, new byte[] { 0x37 });
324 FTD2XX.FT_Open(portIndex, out handle);
325 FTD2XX.FT_SetBaudRate(handle, 19200);
326 FTD2XX.FT_SetDataCharacteristics(handle, 8, 1, 0);
327 FTD2XX.FT_SetFlowControl(handle, FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11,
329 FTD2XX.FT_SetTimeouts(handle, 1000, 1000);
330 FTD2XX.FT_Purge(handle, FT_PURGE.FT_PURGE_ALL);
333 public override void Update() {
334 while (FTD2XX.BytesToRead(handle) >= 285)
336 if (FTD2XX.BytesToRead(handle) == 1)
337 FTD2XX.ReadByte(handle);
339 FTD2XX.Write(handle, new byte[] { 0x38 });
340 alternativeRequest.BeginInvoke(null, null);
343 public void Close() {
344 FTD2XX.FT_Close(handle);