Hardware/LPC/IT87XX.cs
author moel.mich
Thu, 11 Nov 2010 21:22:24 +0000
changeset 241 52007c404f32
parent 228 458a6c3de579
child 247 6dc755f1970e
permissions -rw-r--r--
Fixed a problem, where the MainForm location and size was lost when the application is started minimized and exited without ever showing the form. This caused MainForm_Load to be never called (location and size was not loaded), but the default size and location were still saved. The new implementation only saves the location and size when one of the two is changed.
moel@16
     1
/*
moel@16
     2
  
moel@16
     3
  Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@16
     4
moel@16
     5
  The contents of this file are subject to the Mozilla Public License Version
moel@16
     6
  1.1 (the "License"); you may not use this file except in compliance with
moel@16
     7
  the License. You may obtain a copy of the License at
moel@16
     8
 
moel@16
     9
  http://www.mozilla.org/MPL/
moel@16
    10
moel@16
    11
  Software distributed under the License is distributed on an "AS IS" basis,
moel@16
    12
  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@16
    13
  for the specific language governing rights and limitations under the License.
moel@16
    14
moel@16
    15
  The Original Code is the Open Hardware Monitor code.
moel@16
    16
moel@16
    17
  The Initial Developer of the Original Code is 
moel@16
    18
  Michael Möller <m.moeller@gmx.ch>.
moel@16
    19
  Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@16
    20
  the Initial Developer. All Rights Reserved.
moel@16
    21
moel@16
    22
  Contributor(s):
moel@16
    23
moel@16
    24
  Alternatively, the contents of this file may be used under the terms of
moel@16
    25
  either the GNU General Public License Version 2 or later (the "GPL"), or
moel@16
    26
  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@16
    27
  in which case the provisions of the GPL or the LGPL are applicable instead
moel@16
    28
  of those above. If you wish to allow use of your version of this file only
moel@16
    29
  under the terms of either the GPL or the LGPL, and not to allow others to
moel@16
    30
  use your version of this file under the terms of the MPL, indicate your
moel@16
    31
  decision by deleting the provisions above and replace them with the notice
moel@16
    32
  and other provisions required by the GPL or the LGPL. If you do not delete
moel@16
    33
  the provisions above, a recipient may use your version of this file under
moel@16
    34
  the terms of any one of the MPL, the GPL or the LGPL.
moel@16
    35
 
moel@16
    36
*/
moel@16
    37
moel@166
    38
using System.Globalization;
moel@16
    39
using System.Text;
moel@16
    40
moel@16
    41
namespace OpenHardwareMonitor.Hardware.LPC {
moel@165
    42
  internal class IT87XX : ISuperIO {
moel@130
    43
       
moel@195
    44
    private readonly ushort address;
moel@195
    45
    private readonly Chip chip;
moel@195
    46
    private readonly byte version;
moel@16
    47
moel@228
    48
    private readonly ushort gpioAddress;
moel@228
    49
    private readonly int gpioCount;
moel@228
    50
moel@78
    51
    private readonly ushort addressReg;
moel@78
    52
    private readonly ushort dataReg;
moel@78
    53
moel@195
    54
    private readonly float?[] voltages = new float?[0];
moel@195
    55
    private readonly float?[] temperatures = new float?[0];
moel@195
    56
    private readonly float?[] fans = new float?[0];
moel@170
    57
moel@170
    58
    private readonly float voltageGain;
moel@16
    59
   
moel@16
    60
    // Consts
moel@16
    61
    private const byte ITE_VENDOR_ID = 0x90;
moel@16
    62
       
moel@16
    63
    // Environment Controller
moel@16
    64
    private const byte ADDRESS_REGISTER_OFFSET = 0x05;
moel@16
    65
    private const byte DATA_REGISTER_OFFSET = 0x06;
moel@16
    66
moel@16
    67
    // Environment Controller Registers    
moel@16
    68
    private const byte CONFIGURATION_REGISTER = 0x00;
moel@16
    69
    private const byte TEMPERATURE_BASE_REG = 0x29;
moel@16
    70
    private const byte VENDOR_ID_REGISTER = 0x58;
moel@16
    71
    private const byte FAN_TACHOMETER_16_BIT_ENABLE_REGISTER = 0x0c;
moel@195
    72
    private readonly byte[] FAN_TACHOMETER_REG = 
moel@16
    73
      new byte[] { 0x0d, 0x0e, 0x0f, 0x80, 0x82 };
moel@195
    74
    private readonly byte[] FAN_TACHOMETER_EXT_REG =
moel@16
    75
      new byte[] { 0x18, 0x19, 0x1a, 0x81, 0x83 };
moel@78
    76
    private const byte VOLTAGE_BASE_REG = 0x20;
moel@78
    77
moel@78
    78
    private byte ReadByte(byte register, out bool valid) {
moel@236
    79
      Ring0.WriteIoPort(addressReg, register);
moel@236
    80
      byte value = Ring0.ReadIoPort(dataReg);
moel@236
    81
      valid = register == Ring0.ReadIoPort(addressReg);
moel@78
    82
      return value;
moel@228
    83
    }
moel@16
    84
moel@228
    85
    public byte? ReadGPIO(int index) {
moel@228
    86
      if (index >= gpioCount)
moel@228
    87
        return null;
moel@228
    88
moel@236
    89
      return Ring0.ReadIoPort((ushort)(gpioAddress + index));
moel@228
    90
    }
moel@228
    91
moel@228
    92
    public void WriteGPIO(int index, byte value) {
moel@228
    93
      if (index >= gpioCount)
moel@228
    94
        return;
moel@228
    95
moel@236
    96
      Ring0.WriteIoPort((ushort)(gpioAddress + index), value);
moel@228
    97
    }
moel@228
    98
moel@228
    99
    public IT87XX(Chip chip, ushort address, ushort gpioAddress, byte version) {
moel@16
   100
      
moel@16
   101
      this.address = address;
moel@130
   102
      this.chip = chip;
moel@145
   103
      this.version = version;
moel@78
   104
      this.addressReg = (ushort)(address + ADDRESS_REGISTER_OFFSET);
moel@78
   105
      this.dataReg = (ushort)(address + DATA_REGISTER_OFFSET);
moel@228
   106
      this.gpioAddress = gpioAddress;
moel@228
   107
moel@16
   108
      // Check vendor id
moel@78
   109
      bool valid;
moel@78
   110
      byte vendorId = ReadByte(VENDOR_ID_REGISTER, out valid);       
moel@78
   111
      if (!valid || vendorId != ITE_VENDOR_ID)
moel@16
   112
        return;
moel@16
   113
moel@16
   114
      // Bit 0x10 of the configuration register should always be 1
moel@78
   115
      if ((ReadByte(CONFIGURATION_REGISTER, out valid) & 0x10) == 0)
moel@78
   116
        return;
moel@78
   117
      if (!valid)
moel@16
   118
        return;
moel@16
   119
moel@130
   120
      voltages = new float?[9];
moel@130
   121
      temperatures = new float?[3];
moel@130
   122
      fans = new float?[5];
moel@170
   123
moel@170
   124
      // The IT8721F uses a 12mV resultion ADC, all others 16mV
moel@170
   125
      if (chip == Chip.IT8721F) {
moel@170
   126
        voltageGain = 0.012f;
moel@170
   127
      } else {
moel@170
   128
        voltageGain = 0.016f;
moel@170
   129
      }
moel@228
   130
moel@228
   131
      // Set the number of GPIO sets
moel@228
   132
      switch (chip) {
moel@228
   133
        case Chip.IT8712F:
moel@228
   134
        case Chip.IT8716F:
moel@228
   135
        case Chip.IT8718F:
moel@228
   136
        case Chip.IT8726F:
moel@228
   137
          gpioCount = 5;
moel@228
   138
          break;
moel@228
   139
        case Chip.IT8720F:
moel@228
   140
        case Chip.IT8721F:
moel@228
   141
          gpioCount = 8;
moel@228
   142
          break;
moel@228
   143
      }
moel@16
   144
    }
moel@16
   145
moel@130
   146
    public Chip Chip { get { return chip; } }
moel@130
   147
    public float?[] Voltages { get { return voltages; } }
moel@130
   148
    public float?[] Temperatures { get { return temperatures; } }
moel@130
   149
    public float?[] Fans { get { return fans; } }
moel@16
   150
moel@130
   151
    public string GetReport() {
moel@16
   152
      StringBuilder r = new StringBuilder();
moel@16
   153
moel@31
   154
      r.AppendLine("LPC " + this.GetType().Name);
moel@16
   155
      r.AppendLine();
moel@16
   156
      r.Append("Chip ID: 0x"); r.AppendLine(chip.ToString("X"));
moel@166
   157
      r.Append("Chip Version: 0x"); r.AppendLine(
moel@166
   158
        version.ToString("X", CultureInfo.InvariantCulture));
moel@166
   159
      r.Append("Base Address: 0x"); r.AppendLine(
moel@166
   160
        address.ToString("X4", CultureInfo.InvariantCulture));
moel@228
   161
      r.Append("GPIO Address: 0x"); r.AppendLine(
moel@228
   162
        gpioAddress.ToString("X4", CultureInfo.InvariantCulture));
moel@16
   163
      r.AppendLine();
moel@162
   164
moel@236
   165
      if (!Ring0.WaitIsaBusMutex(100))
moel@162
   166
        return r.ToString();
moel@162
   167
moel@16
   168
      r.AppendLine("Environment Controller Registers");
moel@16
   169
      r.AppendLine();
moel@16
   170
      r.AppendLine("      00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F");
moel@16
   171
      r.AppendLine();
moel@16
   172
      for (int i = 0; i <= 0xA; i++) {
moel@166
   173
        r.Append(" "); 
moel@166
   174
        r.Append((i << 4).ToString("X2", CultureInfo.InvariantCulture)); 
moel@166
   175
        r.Append("  ");
moel@16
   176
        for (int j = 0; j <= 0xF; j++) {
moel@16
   177
          r.Append(" ");
moel@78
   178
          bool valid;
moel@78
   179
          byte value = ReadByte((byte)((i << 4) | j), out valid);
moel@195
   180
          r.Append(
moel@195
   181
            valid ? value.ToString("X2", CultureInfo.InvariantCulture) : "??");
moel@16
   182
        }
moel@16
   183
        r.AppendLine();
moel@16
   184
      }
moel@16
   185
      r.AppendLine();
moel@16
   186
moel@228
   187
      r.AppendLine("GPIO Registers");
moel@228
   188
      r.AppendLine();
moel@228
   189
      for (int i = 0; i < gpioCount; i++) {
moel@228
   190
        r.Append(" ");
moel@228
   191
        r.Append(ReadGPIO(i).Value.ToString("X2",
moel@228
   192
          CultureInfo.InvariantCulture));
moel@228
   193
      }
moel@228
   194
      r.AppendLine();
moel@228
   195
      r.AppendLine();
moel@228
   196
moel@236
   197
      Ring0.ReleaseIsaBusMutex();
moel@162
   198
moel@16
   199
      return r.ToString();
moel@16
   200
    }
moel@16
   201
moel@130
   202
    public void Update() {
moel@236
   203
      if (!Ring0.WaitIsaBusMutex(10))
moel@162
   204
        return;
moel@16
   205
moel@130
   206
      for (int i = 0; i < voltages.Length; i++) {
moel@78
   207
        bool valid;
moel@170
   208
        
moel@170
   209
        float value = 
moel@170
   210
          voltageGain * ReadByte((byte)(VOLTAGE_BASE_REG + i), out valid);   
moel@170
   211
moel@130
   212
        if (!valid)
moel@130
   213
          continue;
moel@130
   214
        if (value > 0)
moel@130
   215
          voltages[i] = value;  
moel@130
   216
        else
moel@130
   217
          voltages[i] = null;
moel@130
   218
      }
moel@130
   219
moel@130
   220
      for (int i = 0; i < temperatures.Length; i++) {
moel@130
   221
        bool valid;
moel@130
   222
        sbyte value = (sbyte)ReadByte(
moel@130
   223
          (byte)(TEMPERATURE_BASE_REG + i), out valid);
moel@78
   224
        if (!valid)
moel@78
   225
          continue;
moel@78
   226
moel@130
   227
        if (value < sbyte.MaxValue && value > 0)
moel@130
   228
          temperatures[i] = value;
moel@130
   229
        else
moel@130
   230
          temperatures[i] = null;       
moel@16
   231
      }
moel@16
   232
moel@130
   233
      for (int i = 0; i < fans.Length; i++) {
moel@78
   234
        bool valid;
moel@130
   235
        int value = ReadByte(FAN_TACHOMETER_REG[i], out valid);
moel@78
   236
        if (!valid) 
moel@78
   237
          continue;
moel@130
   238
        value |= ReadByte(FAN_TACHOMETER_EXT_REG[i], out valid) << 8;
moel@78
   239
        if (!valid)
moel@78
   240
          continue;
moel@16
   241
moel@36
   242
        if (value > 0x3f) {
moel@130
   243
          fans[i] = (value < 0xffff) ? 1.35e6f / ((value) * 2) : 0;
moel@16
   244
        } else {
moel@130
   245
          fans[i] = null;
moel@16
   246
        }
moel@162
   247
      }
moel@162
   248
moel@236
   249
      Ring0.ReleaseIsaBusMutex();
moel@126
   250
    }
moel@130
   251
  } 
moel@16
   252
}