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