Hardware/TBalancer/TBalancer.cs
author StephaneLenclud
Sun, 03 Feb 2013 18:01:50 +0100
branchMiniDisplay
changeset 433 090259cfd699
parent 344 3145aadca3d2
permissions -rw-r--r--
Adding SoundGraphDisplay and SensorFrontView classes.
They were respectively based on SystemTray and SensorNotifyIcon.
SoundGraphDisplay is now able to load iMONDisplay.dll providing it lives on your PATH.
Adding option to sensor context menu for adding it into FrontView.
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@384
    33
    private byte[] data = new byte[285];
moel@384
    34
    private byte[] primaryData = new byte[0];
moel@384
    35
    private byte[] alternativeData = new byte[0];
moel@1
    36
moel@1
    37
    public const byte STARTFLAG = 100;
moel@57
    38
    public const byte ENDFLAG = 254;
moel@57
    39
moel@57
    40
    private delegate void MethodDelegate();
moel@275
    41
    private readonly MethodDelegate alternativeRequest;
moel@1
    42
moel@275
    43
    public TBalancer(int portIndex, byte protocolVersion, ISettings settings)
moel@275
    44
      : base("T-Balancer bigNG",  new Identifier("bigng",
moel@275
    45
        portIndex.ToString(CultureInfo.InvariantCulture)), settings) 
moel@275
    46
    {
moel@165
    47
moel@87
    48
      this.portIndex = portIndex;
moel@33
    49
      this.protocolVersion = protocolVersion;
moel@1
    50
moel@195
    51
      ParameterDescription[] parameter = new [] {
moel@122
    52
        new ParameterDescription("Offset [°C]", "Temperature offset.", 0)
moel@63
    53
      };
moel@57
    54
      int offset = 0;
moel@57
    55
      for (int i = 0; i < digitalTemperatures.Length; i++)
moel@88
    56
        digitalTemperatures[i] = new Sensor("Digital Sensor " + i,
moel@165
    57
          offset + i, SensorType.Temperature, this, parameter, settings);
moel@57
    58
      offset += digitalTemperatures.Length;
moel@57
    59
moel@57
    60
      for (int i = 0; i < analogTemperatures.Length; i++)
moel@88
    61
        analogTemperatures[i] = new Sensor("Analog Sensor " + (i + 1),
moel@165
    62
          offset + i, SensorType.Temperature, this, parameter, settings);
moel@57
    63
      offset += analogTemperatures.Length;
moel@57
    64
moel@57
    65
      for (int i = 0; i < sensorhubTemperatures.Length; i++)
moel@88
    66
        sensorhubTemperatures[i] = new Sensor("Sensorhub Sensor " + i,
moel@165
    67
          offset + i, SensorType.Temperature, this, parameter, settings);
moel@57
    68
      offset += sensorhubTemperatures.Length;
moel@57
    69
moel@57
    70
      for (int i = 0; i < miniNGTemperatures.Length; i++)
moel@63
    71
        miniNGTemperatures[i] = new Sensor("miniNG #" + (i / 2 + 1) +
moel@165
    72
          " Sensor " + (i % 2 + 1), offset + i, SensorType.Temperature,
moel@165
    73
          this, parameter, settings);
moel@57
    74
      offset += miniNGTemperatures.Length;
moel@57
    75
moel@118
    76
      for (int i = 0; i < sensorhubFlows.Length; i++)
moel@118
    77
        sensorhubFlows[i] = new Sensor("Flowmeter " + (i + 1),
moel@195
    78
          i, SensorType.Flow, this, new [] {
moel@118
    79
            new ParameterDescription("Impulse Rate", 
moel@118
    80
              "The impulse rate of the flowmeter in pulses/L", 509)
moel@165
    81
          }, settings);
moel@118
    82
moel@118
    83
      for (int i = 0; i < controls.Length; i++) {
moel@137
    84
        controls[i] = new Sensor("Fan Channel " + i, i, SensorType.Control, 
moel@165
    85
          this, settings);
moel@137
    86
      }
moel@137
    87
moel@137
    88
      for (int i = 0; i < miniNGControls.Length; i++) {
moel@137
    89
        miniNGControls[i] = new Sensor("miniNG #" + (i / 2 + 1) +
moel@165
    90
          " Fan Channel " + (i % 2 + 1), 4 + i, SensorType.Control, this, 
moel@165
    91
          settings);
moel@118
    92
      }
moel@118
    93
moel@57
    94
      alternativeRequest = new MethodDelegate(DelayedAlternativeRequest);
moel@57
    95
moel@87
    96
      Open();
moel@87
    97
      Update(); 
moel@1
    98
    }
moel@1
    99
moel@275
   100
    protected override void ActivateSensor(ISensor sensor) {
moel@1
   101
      deactivating.Remove(sensor);
moel@275
   102
      base.ActivateSensor(sensor);   
moel@275
   103
    } 
moel@1
   104
moel@275
   105
    protected override void DeactivateSensor(ISensor sensor) {
moel@1
   106
      if (deactivating.Contains(sensor)) {
moel@1
   107
        deactivating.Remove(sensor);
moel@275
   108
        base.DeactivateSensor(sensor);
moel@1
   109
      } else if (active.Contains(sensor)) {
moel@1
   110
        deactivating.Add(sensor);
moel@1
   111
      }     
moel@1
   112
    }
moel@1
   113
moel@384
   114
    private void ReadminiNG(int number) {
moel@57
   115
      int offset = 1 + number * 65;
moel@57
   116
moel@57
   117
      if (data[offset + 61] != ENDFLAG)
moel@57
   118
        return;
moel@57
   119
moel@57
   120
      for (int i = 0; i < 2; i++) {
moel@57
   121
        Sensor sensor = miniNGTemperatures[number * 2 + i];
moel@57
   122
        if (data[offset + 7 + i] > 0) {
moel@63
   123
          sensor.Value = 0.5f * data[offset + 7 + i] + 
moel@63
   124
            sensor.Parameters[0].Value;
moel@57
   125
          ActivateSensor(sensor);
moel@57
   126
        } else {
moel@57
   127
          DeactivateSensor(sensor);
moel@57
   128
        }
moel@57
   129
      }
moel@57
   130
moel@57
   131
      for (int i = 0; i < 2; i++) {
moel@57
   132
        if (miniNGFans[number * 2 + i] == null)
moel@57
   133
          miniNGFans[number * 2 + i] = 
moel@88
   134
            new Sensor("miniNG #" + (number + 1) + " Fan Channel " + (i + 1),
moel@165
   135
            4 + number * 2 + i, SensorType.Fan, this, settings);
moel@57
   136
        
moel@57
   137
        Sensor sensor = miniNGFans[number * 2 + i];
moel@57
   138
moel@57
   139
        sensor.Value = 20.0f * data[offset + 43 + 2 * i];
moel@57
   140
        ActivateSensor(sensor);
moel@57
   141
      }
moel@137
   142
moel@137
   143
      for (int i = 0; i < 2; i++) {
moel@137
   144
        Sensor sensor = miniNGControls[number * 2 + i];
moel@137
   145
        sensor.Value = data[offset + 15 + i];
moel@137
   146
        ActivateSensor(sensor);
moel@137
   147
      }
moel@57
   148
    }
moel@57
   149
moel@1
   150
    private void ReadData() {
moel@384
   151
      FTD2XX.Read(handle, data);
moel@137
   152
      
moel@57
   153
      if (data[0] != STARTFLAG) {
moel@87
   154
        FTD2XX.FT_Purge(handle, FT_PURGE.FT_PURGE_RX);   
moel@1
   155
        return;
moel@1
   156
      }
moel@1
   157
moel@73
   158
      if (data[1] == 255 || data[1] == 88) { // bigNG
moel@57
   159
moel@57
   160
        if (data[274] != protocolVersion) 
moel@57
   161
          return;
moel@57
   162
moel@384
   163
        if (primaryData.Length == 0)
moel@384
   164
          primaryData = new byte[data.Length];
moel@384
   165
        data.CopyTo(primaryData, 0);
moel@57
   166
moel@57
   167
        for (int i = 0; i < digitalTemperatures.Length; i++)
moel@57
   168
          if (data[238 + i] > 0) {
moel@63
   169
            digitalTemperatures[i].Value = 0.5f * data[238 + i] + 
moel@63
   170
              digitalTemperatures[i].Parameters[0].Value;
moel@57
   171
            ActivateSensor(digitalTemperatures[i]);
moel@57
   172
          } else {
moel@57
   173
            DeactivateSensor(digitalTemperatures[i]);
moel@57
   174
          }
moel@57
   175
moel@57
   176
        for (int i = 0; i < analogTemperatures.Length; i++)
moel@57
   177
          if (data[260 + i] > 0) {
moel@63
   178
            analogTemperatures[i].Value = 0.5f * data[260 + i] +
moel@63
   179
              analogTemperatures[i].Parameters[0].Value;
moel@57
   180
            ActivateSensor(analogTemperatures[i]);
moel@57
   181
          } else {
moel@57
   182
            DeactivateSensor(analogTemperatures[i]);
moel@57
   183
          }
moel@57
   184
moel@57
   185
        for (int i = 0; i < sensorhubTemperatures.Length; i++)
moel@57
   186
          if (data[246 + i] > 0) {
moel@63
   187
            sensorhubTemperatures[i].Value = 0.5f * data[246 + i] +
moel@63
   188
              sensorhubTemperatures[i].Parameters[0].Value;
moel@57
   189
            ActivateSensor(sensorhubTemperatures[i]);
moel@57
   190
          } else {
moel@57
   191
            DeactivateSensor(sensorhubTemperatures[i]);
moel@57
   192
          }
moel@57
   193
moel@57
   194
        for (int i = 0; i < sensorhubFlows.Length; i++)
moel@57
   195
          if (data[231 + i] > 0 && data[234] > 0) {
moel@66
   196
            float pulsesPerSecond = (data[231 + i] * 4.0f) / data[234];
moel@63
   197
            float pulsesPerLiter = sensorhubFlows[i].Parameters[0].Value;
moel@57
   198
            sensorhubFlows[i].Value = pulsesPerSecond * 3600 / pulsesPerLiter;
moel@57
   199
            ActivateSensor(sensorhubFlows[i]);
moel@57
   200
          } else {
moel@57
   201
            DeactivateSensor(sensorhubFlows[i]);
moel@57
   202
          }
moel@86
   203
        
moel@57
   204
        for (int i = 0; i < fans.Length; i++) {
moel@57
   205
          float maxRPM = 11.5f * ((data[149 + 2 * i] << 8) | data[148 + 2 * i]);
moel@57
   206
moel@57
   207
          if (fans[i] == null)
moel@134
   208
            fans[i] = new Sensor("Fan Channel " + i, i, SensorType.Fan,
moel@195
   209
              this, new [] { new ParameterDescription("MaxRPM", 
moel@63
   210
                  "Maximum revolutions per minute (RPM) of the fan.", maxRPM)
moel@165
   211
              }, settings);
moel@57
   212
moel@118
   213
          float value;
moel@118
   214
          if ((data[136] & (1 << i)) == 0)  // pwm mode
moel@118
   215
            value = 0.02f * data[137 + i];
moel@63
   216
          else // analog mode
moel@118
   217
            value = 0.01f * data[141 + i];
moel@118
   218
          
moel@118
   219
          fans[i].Value = fans[i].Parameters[0].Value * value;
moel@57
   220
          ActivateSensor(fans[i]);
moel@118
   221
moel@137
   222
          controls[i].Value = 100 * value;
moel@137
   223
          ActivateSensor(controls[i]);
moel@1
   224
        }
moel@1
   225
moel@57
   226
      } else if (data[1] == 253) { // miniNG #1
moel@384
   227
        if (alternativeData.Length == 0)
moel@384
   228
          alternativeData = new byte[data.Length];
moel@384
   229
        data.CopyTo(alternativeData, 0);
moel@1
   230
moel@384
   231
        ReadminiNG(0);        
moel@57
   232
              
moel@137
   233
        if (data[66] == 253)  // miniNG #2
moel@384
   234
          ReadminiNG(1);
moel@57
   235
      } 
moel@1
   236
    }
moel@1
   237
moel@275
   238
    public override HardwareType HardwareType {
moel@165
   239
      get { return HardwareType.TBalancer; }
moel@1
   240
    }
moel@1
   241
moel@275
   242
    public override string GetReport() {
moel@1
   243
      StringBuilder r = new StringBuilder();
moel@1
   244
moel@1
   245
      r.AppendLine("T-Balancer bigNG");
moel@1
   246
      r.AppendLine();
moel@166
   247
      r.Append("Port Index: "); 
moel@166
   248
      r.AppendLine(portIndex.ToString(CultureInfo.InvariantCulture));
moel@1
   249
      r.AppendLine();
moel@57
   250
moel@57
   251
      r.AppendLine("Primary System Information Answer");
moel@1
   252
      r.AppendLine();
moel@1
   253
      r.AppendLine("       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@1
   254
      r.AppendLine();
moel@1
   255
      for (int i = 0; i <= 0x11; i++) {
moel@166
   256
        r.Append(" "); 
moel@166
   257
        r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture)); 
moel@166
   258
        r.Append("  ");
moel@1
   259
        for (int j = 0; j <= 0xF; j++) {
moel@1
   260
          int index = ((i << 4) | j);
moel@57
   261
          if (index < primaryData.Length) {
moel@1
   262
            r.Append(" ");
moel@166
   263
            r.Append(primaryData[index].ToString("X2", CultureInfo.InvariantCulture));
moel@1
   264
          }          
moel@1
   265
        }
moel@1
   266
        r.AppendLine();
moel@1
   267
      }
moel@1
   268
      r.AppendLine();
moel@1
   269
moel@57
   270
      if (alternativeData.Length > 0) {
moel@57
   271
        r.AppendLine("Alternative System Information Answer");
moel@57
   272
        r.AppendLine();
moel@57
   273
        r.AppendLine("       00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@57
   274
        r.AppendLine();
moel@57
   275
        for (int i = 0; i <= 0x11; i++) {
moel@166
   276
          r.Append(" "); 
moel@166
   277
          r.Append((i << 4).ToString("X3", CultureInfo.InvariantCulture)); 
moel@166
   278
          r.Append("  ");
moel@57
   279
          for (int j = 0; j <= 0xF; j++) {
moel@57
   280
            int index = ((i << 4) | j);
moel@57
   281
            if (index < alternativeData.Length) {
moel@57
   282
              r.Append(" ");
moel@166
   283
              r.Append(alternativeData[index].ToString("X2", CultureInfo.InvariantCulture));
moel@57
   284
            }
moel@57
   285
          }
moel@57
   286
          r.AppendLine();
moel@57
   287
        }
moel@57
   288
        r.AppendLine();
moel@57
   289
      }
moel@57
   290
moel@1
   291
      return r.ToString();
moel@1
   292
    }
moel@1
   293
moel@57
   294
    private void DelayedAlternativeRequest() {
moel@87
   295
      System.Threading.Thread.Sleep(500);      
moel@87
   296
      FTD2XX.Write(handle, new byte[] { 0x37 });
moel@57
   297
    }
moel@57
   298
moel@87
   299
    public void Open() {
moel@87
   300
      FTD2XX.FT_Open(portIndex, out handle); 
moel@87
   301
      FTD2XX.FT_SetBaudRate(handle, 19200);
moel@87
   302
      FTD2XX.FT_SetDataCharacteristics(handle, 8, 1, 0);
moel@87
   303
      FTD2XX.FT_SetFlowControl(handle, FT_FLOW_CONTROL.FT_FLOW_RTS_CTS, 0x11,
moel@87
   304
        0x13);
moel@87
   305
      FTD2XX.FT_SetTimeouts(handle, 1000, 1000);
moel@87
   306
      FTD2XX.FT_Purge(handle, FT_PURGE.FT_PURGE_ALL);
moel@87
   307
    }
moel@57
   308
moel@275
   309
    public override void Update() {
moel@87
   310
      while (FTD2XX.BytesToRead(handle) >= 285)
moel@87
   311
        ReadData();
moel@87
   312
      if (FTD2XX.BytesToRead(handle) == 1)
moel@87
   313
        FTD2XX.ReadByte(handle);
moel@87
   314
moel@87
   315
      FTD2XX.Write(handle, new byte[] { 0x38 });
moel@87
   316
      alternativeRequest.BeginInvoke(null, null);
moel@1
   317
    }
moel@1
   318
moel@298
   319
    public override void Close() {
moel@87
   320
      FTD2XX.FT_Close(handle);
moel@298
   321
      base.Close();
moel@1
   322
    }
moel@1
   323
moel@1
   324
  }
moel@1
   325
}