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