Hardware/TBalancer/TBalancer.cs
author moel.mich
Sat, 11 Aug 2012 21:48:54 +0000
changeset 379 7af3aaeb42e9
parent 298 96263190189a
child 384 76f859f4aea1
permissions -rw-r--r--
Added a few checks and delays to the driver loading code to increase the chance of loading the driver.
     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 }