Hardware/TBalancer/TBalancer.cs
author moel.mich
Sun, 23 Sep 2012 18:37:43 +0000
changeset 380 573f1fff48b2
parent 298 96263190189a
child 384 76f859f4aea1
permissions -rw-r--r--
Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
moel@1
     1
/*
moel@1
     2
 
moel@344
     3
  This Source Code Form is subject to the terms of the Mozilla Public
moel@344
     4
  License, v. 2.0. If a copy of the MPL was not distributed with this
moel@344
     5
  file, You can obtain one at http://mozilla.org/MPL/2.0/.
moel@1
     6
 
moel@344
     7
  Copyright (C) 2009-2011 Michael Möller <mmoeller@openhardwaremonitor.org>
moel@344
     8
	
moel@1
     9
*/
moel@1
    10
moel@1
    11
using System;
moel@1
    12
using System.Collections.Generic;
moel@166
    13
using System.Globalization;
moel@1
    14
using System.Text;
moel@1
    15
moel@1
    16
namespace OpenHardwareMonitor.Hardware.TBalancer {
moel@275
    17
  internal class TBalancer : Hardware {
moel@1
    18
moel@195
    19
    private readonly int portIndex;    
moel@195
    20
    private readonly byte protocolVersion;
moel@195
    21
    private readonly Sensor[] digitalTemperatures = new Sensor[8];
moel@195
    22
    private readonly Sensor[] analogTemperatures = new Sensor[4];
moel@195
    23
    private readonly Sensor[] sensorhubTemperatures = new Sensor[6];
moel@195
    24
    private readonly Sensor[] sensorhubFlows = new Sensor[2];
moel@195
    25
    private readonly Sensor[] fans = new Sensor[4];
moel@195
    26
    private readonly Sensor[] controls = new Sensor[4];
moel@195
    27
    private readonly Sensor[] miniNGTemperatures = new Sensor[4];
moel@195
    28
    private readonly Sensor[] miniNGFans = new Sensor[4];
moel@195
    29
    private readonly Sensor[] miniNGControls = new Sensor[4];
moel@195
    30
    private readonly List<ISensor> deactivating = new List<ISensor>();
moel@195
    31
moel@87
    32
    private FT_HANDLE handle;
moel@57
    33
    private int[] primaryData = new int[0];
moel@57
    34
    private int[] alternativeData = new int[0];
moel@1
    35
moel@1
    36
    public const byte STARTFLAG = 100;
moel@57
    37
    public const byte ENDFLAG = 254;
moel@57
    38
moel@57
    39
    private delegate void MethodDelegate();
moel@275
    40
    private readonly MethodDelegate alternativeRequest;
moel@1
    41
moel@275
    42
    public TBalancer(int portIndex, byte protocolVersion, ISettings settings)
moel@275
    43
      : base("T-Balancer bigNG",  new Identifier("bigng",
moel@275
    44
        portIndex.ToString(CultureInfo.InvariantCulture)), settings) 
moel@275
    45
    {
moel@165
    46
moel@87
    47
      this.portIndex = portIndex;
moel@33
    48
      this.protocolVersion = protocolVersion;
moel@1
    49
moel@195
    50
      ParameterDescription[] parameter = new [] {
moel@122
    51
        new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
moel@63
    52
      };
moel@57
    53
      int offset = 0;
moel@57
    54
      for (int i = 0; i < digitalTemperatures.Length; i++)
moel@88
    55
        digitalTemperatures[i] = new Sensor("Digital Sensor " + i,
moel@165
    56
          offset + i, SensorType.Temperature, this, parameter, settings);
moel@57
    57
      offset += digitalTemperatures.Length;
moel@57
    58
moel@57
    59
      for (int i = 0; i < analogTemperatures.Length; i++)
moel@88
    60
        analogTemperatures[i] = new Sensor("Analog Sensor " + (i + 1),
moel@165
    61
          offset + i, SensorType.Temperature, this, parameter, settings);
moel@57
    62
      offset += analogTemperatures.Length;
moel@57
    63
moel@57
    64
      for (int i = 0; i < sensorhubTemperatures.Length; i++)
moel@88
    65
        sensorhubTemperatures[i] = new Sensor("Sensorhub Sensor " + i,
moel@165
    66
          offset + i, SensorType.Temperature, this, parameter, settings);
moel@57
    67
      offset += sensorhubTemperatures.Length;
moel@57
    68
moel@57
    69
      for (int i = 0; i < miniNGTemperatures.Length; i++)
moel@63
    70
        miniNGTemperatures[i] = new Sensor("miniNG #" + (i / 2 + 1) +
moel@165
    71
          " Sensor " + (i % 2 + 1), offset + i, SensorType.Temperature,
moel@165
    72
          this, parameter, settings);
moel@57
    73
      offset += miniNGTemperatures.Length;
moel@57
    74
moel@118
    75
      for (int i = 0; i < sensorhubFlows.Length; i++)
moel@118
    76
        sensorhubFlows[i] = new Sensor("Flowmeter " + (i + 1),
moel@195
    77
          i, SensorType.Flow, this, new [] {
moel@118
    78
            new ParameterDescription("Impulse Rate", 
moel@118
    79
              "The impulse rate of the flowmeter in pulses/L", 509)
moel@165
    80
          }, settings);
moel@118
    81
moel@118
    82
      for (int i = 0; i < controls.Length; i++) {
moel@137
    83
        controls[i] = new Sensor("Fan Channel " + i, i, SensorType.Control, 
moel@165
    84
          this, settings);
moel@137
    85
      }
moel@137
    86
moel@137
    87
      for (int i = 0; i < miniNGControls.Length; i++) {
moel@137
    88
        miniNGControls[i] = new Sensor("miniNG #" + (i / 2 + 1) +
moel@165
    89
          " Fan Channel " + (i % 2 + 1), 4 + i, SensorType.Control, this, 
moel@165
    90
          settings);
moel@118
    91
      }
moel@118
    92
moel@57
    93
      alternativeRequest = new MethodDelegate(DelayedAlternativeRequest);
moel@57
    94
moel@87
    95
      Open();
moel@87
    96
      Update(); 
moel@1
    97
    }
moel@1
    98
moel@275
    99
    protected override void ActivateSensor(ISensor sensor) {
moel@1
   100
      deactivating.Remove(sensor);
moel@275
   101
      base.ActivateSensor(sensor);   
moel@275
   102
    } 
moel@1
   103
moel@275
   104
    protected override void DeactivateSensor(ISensor sensor) {
moel@1
   105
      if (deactivating.Contains(sensor)) {
moel@1
   106
        deactivating.Remove(sensor);
moel@275
   107
        base.DeactivateSensor(sensor);
moel@1
   108
      } else if (active.Contains(sensor)) {
moel@1
   109
        deactivating.Add(sensor);
moel@1
   110
      }     
moel@1
   111
    }
moel@1
   112
moel@57
   113
    private void ReadminiNG(int[] data, int number) {
moel@57
   114
      int offset = 1 + number * 65;
moel@57
   115
moel@57
   116
      if (data[offset + 61] != ENDFLAG)
moel@57
   117
        return;
moel@57
   118
moel@57
   119
      for (int i = 0; i < 2; i++) {
moel@57
   120
        Sensor sensor = miniNGTemperatures[number * 2 + i];
moel@57
   121
        if (data[offset + 7 + i] > 0) {
moel@63
   122
          sensor.Value = 0.5f * data[offset + 7 + i] + 
moel@63
   123
            sensor.Parameters[0].Value;
moel@57
   124
          ActivateSensor(sensor);
moel@57
   125
        } else {
moel@57
   126
          DeactivateSensor(sensor);
moel@57
   127
        }
moel@57
   128
      }
moel@57
   129
moel@57
   130
      for (int i = 0; i < 2; i++) {
moel@57
   131
        if (miniNGFans[number * 2 + i] == null)
moel@57
   132
          miniNGFans[number * 2 + i] = 
moel@88
   133
            new Sensor("miniNG #" + (number + 1) + " Fan Channel " + (i + 1),
moel@165
   134
            4 + number * 2 + i, SensorType.Fan, this, settings);
moel@57
   135
        
moel@57
   136
        Sensor sensor = miniNGFans[number * 2 + i];
moel@57
   137
moel@57
   138
        sensor.Value = 20.0f * data[offset + 43 + 2 * i];
moel@57
   139
        ActivateSensor(sensor);
moel@57
   140
      }
moel@137
   141
moel@137
   142
      for (int i = 0; i < 2; i++) {
moel@137
   143
        Sensor sensor = miniNGControls[number * 2 + i];
moel@137
   144
        sensor.Value = data[offset + 15 + i];
moel@137
   145
        ActivateSensor(sensor);
moel@137
   146
      }
moel@57
   147
    }
moel@57
   148
moel@1
   149
    private void ReadData() {
moel@1
   150
      int[] data = new int[285];
moel@1
   151
      for (int i = 0; i < data.Length; i++)
moel@87
   152
        data[i] = FTD2XX.ReadByte(handle);
moel@137
   153
      
moel@57
   154
      if (data[0] != STARTFLAG) {
moel@87
   155
        FTD2XX.FT_Purge(handle, FT_PURGE.FT_PURGE_RX);   
moel@1
   156
        return;
moel@1
   157
      }
moel@1
   158
moel@73
   159
      if (data[1] == 255 || data[1] == 88) { // bigNG
moel@57
   160
moel@57
   161
        if (data[274] != protocolVersion) 
moel@57
   162
          return;
moel@57
   163
moel@57
   164
        this.primaryData = data;
moel@57
   165
moel@57
   166
        for (int i = 0; i < digitalTemperatures.Length; i++)
moel@57
   167
          if (data[238 + i] > 0) {
moel@63
   168
            digitalTemperatures[i].Value = 0.5f * data[238 + i] + 
moel@63
   169
              digitalTemperatures[i].Parameters[0].Value;
moel@57
   170
            ActivateSensor(digitalTemperatures[i]);
moel@57
   171
          } else {
moel@57
   172
            DeactivateSensor(digitalTemperatures[i]);
moel@57
   173
          }
moel@57
   174
moel@57
   175
        for (int i = 0; i < analogTemperatures.Length; i++)
moel@57
   176
          if (data[260 + i] > 0) {
moel@63
   177
            analogTemperatures[i].Value = 0.5f * data[260 + i] +
moel@63
   178
              analogTemperatures[i].Parameters[0].Value;
moel@57
   179
            ActivateSensor(analogTemperatures[i]);
moel@57
   180
          } else {
moel@57
   181
            DeactivateSensor(analogTemperatures[i]);
moel@57
   182
          }
moel@57
   183
moel@57
   184
        for (int i = 0; i < sensorhubTemperatures.Length; i++)
moel@57
   185
          if (data[246 + i] > 0) {
moel@63
   186
            sensorhubTemperatures[i].Value = 0.5f * data[246 + i] +
moel@63
   187
              sensorhubTemperatures[i].Parameters[0].Value;
moel@57
   188
            ActivateSensor(sensorhubTemperatures[i]);
moel@57
   189
          } else {
moel@57
   190
            DeactivateSensor(sensorhubTemperatures[i]);
moel@57
   191
          }
moel@57
   192
moel@57
   193
        for (int i = 0; i < sensorhubFlows.Length; i++)
moel@57
   194
          if (data[231 + i] > 0 && data[234] > 0) {
moel@66
   195
            float pulsesPerSecond = (data[231 + i] * 4.0f) / data[234];
moel@63
   196
            float pulsesPerLiter = sensorhubFlows[i].Parameters[0].Value;
moel@57
   197
            sensorhubFlows[i].Value = pulsesPerSecond * 3600 / pulsesPerLiter;
moel@57
   198
            ActivateSensor(sensorhubFlows[i]);
moel@57
   199
          } else {
moel@57
   200
            DeactivateSensor(sensorhubFlows[i]);
moel@57
   201
          }
moel@86
   202
        
moel@57
   203
        for (int i = 0; i < fans.Length; i++) {
moel@57
   204
          float maxRPM = 11.5f * ((data[149 + 2 * i] << 8) | data[148 + 2 * i]);
moel@57
   205
moel@57
   206
          if (fans[i] == null)
moel@134
   207
            fans[i] = new Sensor("Fan Channel " + i, i, SensorType.Fan,
moel@195
   208
              this, new [] { new ParameterDescription("MaxRPM", 
moel@63
   209
                  "Maximum revolutions per minute (RPM) of the fan.", maxRPM)
moel@165
   210
              }, settings);
moel@57
   211
moel@118
   212
          float value;
moel@118
   213
          if ((data[136] & (1 << i)) == 0)  // pwm mode
moel@118
   214
            value = 0.02f * data[137 + i];
moel@63
   215
          else // analog mode
moel@118
   216
            value = 0.01f * data[141 + i];
moel@118
   217
          
moel@118
   218
          fans[i].Value = fans[i].Parameters[0].Value * value;
moel@57
   219
          ActivateSensor(fans[i]);
moel@118
   220
moel@137
   221
          controls[i].Value = 100 * value;
moel@137
   222
          ActivateSensor(controls[i]);
moel@1
   223
        }
moel@1
   224
moel@57
   225
      } else if (data[1] == 253) { // miniNG #1
moel@57
   226
        this.alternativeData = data;
moel@1
   227
moel@57
   228
        ReadminiNG(data, 0);        
moel@57
   229
              
moel@137
   230
        if (data[66] == 253)  // miniNG #2
moel@57
   231
          ReadminiNG(data, 1);
moel@57
   232
      } 
moel@1
   233
    }
moel@1
   234
moel@275
   235
    public override HardwareType HardwareType {
moel@165
   236
      get { return HardwareType.TBalancer; }
moel@1
   237
    }
moel@1
   238
moel@275
   239
    public override string GetReport() {
moel@1
   240
      StringBuilder r = new StringBuilder();
moel@1
   241
moel@1
   242
      r.AppendLine("T-Balancer bigNG");
moel@1
   243
      r.AppendLine();
moel@166
   244
      r.Append("Port Index: "); 
moel@166
   245
      r.AppendLine(portIndex.ToString(CultureInfo.InvariantCulture));
moel@1
   246
      r.AppendLine();
moel@57
   247
moel@57
   248
      r.AppendLine("Primary System Information Answer");
moel@1
   249
      r.AppendLine();
moel@1
   250
      r.AppendLine("       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@1
   251
      r.AppendLine();
moel@1
   252
      for (int i = 0; i <= 0x11; i++) {
moel@166
   253
        r.Append(" "); 
moel@166
   254
        r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture)); 
moel@166
   255
        r.Append("  ");
moel@1
   256
        for (int j = 0; j <= 0xF; j++) {
moel@1
   257
          int index = ((i << 4) | j);
moel@57
   258
          if (index < primaryData.Length) {
moel@1
   259
            r.Append(" ");
moel@166
   260
            r.Append(primaryData[index].ToString("X2", CultureInfo.InvariantCulture));
moel@1
   261
          }          
moel@1
   262
        }
moel@1
   263
        r.AppendLine();
moel@1
   264
      }
moel@1
   265
      r.AppendLine();
moel@1
   266
moel@57
   267
      if (alternativeData.Length > 0) {
moel@57
   268
        r.AppendLine("Alternative System Information Answer");
moel@57
   269
        r.AppendLine();
moel@57
   270
        r.AppendLine("       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@57
   271
        r.AppendLine();
moel@57
   272
        for (int i = 0; i <= 0x11; i++) {
moel@166
   273
          r.Append(" "); 
moel@166
   274
          r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture)); 
moel@166
   275
          r.Append("  ");
moel@57
   276
          for (int j = 0; j <= 0xF; j++) {
moel@57
   277
            int index = ((i << 4) | j);
moel@57
   278
            if (index < alternativeData.Length) {
moel@57
   279
              r.Append(" ");
moel@166
   280
              r.Append(alternativeData[index].ToString("X2", CultureInfo.InvariantCulture));
moel@57
   281
            }
moel@57
   282
          }
moel@57
   283
          r.AppendLine();
moel@57
   284
        }
moel@57
   285
        r.AppendLine();
moel@57
   286
      }
moel@57
   287
moel@1
   288
      return r.ToString();
moel@1
   289
    }
moel@1
   290
moel@57
   291
    private void DelayedAlternativeRequest() {
moel@87
   292
      System.Threading.Thread.Sleep(500);      
moel@87
   293
      FTD2XX.Write(handle, new byte[] { 0x37 });
moel@57
   294
    }
moel@57
   295
moel@87
   296
    public void Open() {
moel@87
   297
      FTD2XX.FT_Open(portIndex, out handle); 
moel@87
   298
      FTD2XX.FT_SetBaudRate(handle, 19200);
moel@87
   299
      FTD2XX.FT_SetDataCharacteristics(handle, 8, 1, 0);
moel@87
   300
      FTD2XX.FT_SetFlowControl(handle, FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11,
moel@87
   301
        0x13);
moel@87
   302
      FTD2XX.FT_SetTimeouts(handle, 1000, 1000);
moel@87
   303
      FTD2XX.FT_Purge(handle, FT_PURGE.FT_PURGE_ALL);
moel@87
   304
    }
moel@57
   305
moel@275
   306
    public override void Update() {
moel@87
   307
      while (FTD2XX.BytesToRead(handle) >= 285)
moel@87
   308
        ReadData();
moel@87
   309
      if (FTD2XX.BytesToRead(handle) == 1)
moel@87
   310
        FTD2XX.ReadByte(handle);
moel@87
   311
moel@87
   312
      FTD2XX.Write(handle, new byte[] { 0x38 });
moel@87
   313
      alternativeRequest.BeginInvoke(null, null);
moel@1
   314
    }
moel@1
   315
moel@298
   316
    public override void Close() {
moel@87
   317
      FTD2XX.FT_Close(handle);
moel@298
   318
      base.Close();
moel@1
   319
    }
moel@1
   320
moel@1
   321
  }
moel@1
   322
}