moel@14: /*
moel@14:   
moel@14:   Version: MPL 1.1/GPL 2.0/LGPL 2.1
moel@14: 
moel@14:   The contents of this file are subject to the Mozilla Public License Version
moel@14:   1.1 (the "License"); you may not use this file except in compliance with
moel@14:   the License. You may obtain a copy of the License at
moel@14:  
moel@14:   http://www.mozilla.org/MPL/
moel@14: 
moel@14:   Software distributed under the License is distributed on an "AS IS" basis,
moel@14:   WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
moel@14:   for the specific language governing rights and limitations under the License.
moel@14: 
moel@14:   The Original Code is the Open Hardware Monitor code.
moel@14: 
moel@14:   The Initial Developer of the Original Code is 
moel@14:   Michael Möller <m.moeller@gmx.ch>.
moel@14:   Portions created by the Initial Developer are Copyright (C) 2009-2010
moel@14:   the Initial Developer. All Rights Reserved.
moel@14: 
moel@14:   Contributor(s):
moel@14: 
moel@14:   Alternatively, the contents of this file may be used under the terms of
moel@14:   either the GNU General Public License Version 2 or later (the "GPL"), or
moel@14:   the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
moel@14:   in which case the provisions of the GPL or the LGPL are applicable instead
moel@14:   of those above. If you wish to allow use of your version of this file only
moel@14:   under the terms of either the GPL or the LGPL, and not to allow others to
moel@14:   use your version of this file under the terms of the MPL, indicate your
moel@14:   decision by deleting the provisions above and replace them with the notice
moel@14:   and other provisions required by the GPL or the LGPL. If you do not delete
moel@14:   the provisions above, a recipient may use your version of this file under
moel@14:   the terms of any one of the MPL, the GPL or the LGPL.
moel@14:  
moel@14: */
moel@14: 
moel@14: using System;
moel@1: using System.Collections.Generic;
moel@1: using System.Drawing;
moel@1: using System.Text;
moel@1: 
moel@1: namespace OpenHardwareMonitor.Hardware.LPC {
moel@31:   public class W83627 : Winbond, IHardware {
moel@31:    
moel@13:     private Sensor[] temperatures;
moel@13:     private Sensor[] fans;
moel@13:     private Sensor[] voltages;
moel@13: 
moel@13:     private float[] voltageGains;
moel@31:     private string[] fanNames;
moel@13: 
moel@13:     // Hardware Monitor Registers
moel@31:     private const byte VOLTAGE_BASE_REG = 0x20;   
moel@13:     private const byte TEMPERATURE_BASE_REG = 0x50;
moel@13:     private const byte TEMPERATURE_SYS_REG = 0x27;
moel@13: 
moel@13:     private byte[] FAN_TACHO_REG = new byte[] { 0x28, 0x29, 0x2A, 0x3F, 0x53 };
moel@31:     private byte[] FAN_TACHO_BANK = new byte[] { 0, 0, 0, 0, 5 };       
moel@13:     private byte[] FAN_BIT_REG = new byte[] { 0x47, 0x4B, 0x4C, 0x59, 0x5D };
moel@13:     private byte[] FAN_DIV_BIT0 = new byte[] { 36, 38, 30, 8, 10 };
moel@13:     private byte[] FAN_DIV_BIT1 = new byte[] { 37, 39, 31, 9, 11 };
moel@13:     private byte[] FAN_DIV_BIT2 = new byte[] { 5, 6, 7, 23, 15 };
moel@13: 
moel@31:     public W83627(Chip chip, byte revision, ushort address) 
moel@31:       : base(chip, revision, address)
moel@31:     {
moel@31:      
moel@13:       temperatures = new Sensor[3];
moel@13:       temperatures[0] = new Sensor("CPU", 0, SensorType.Temperature, this);
moel@13:       temperatures[1] = new Sensor("Auxiliary", 1, SensorType.Temperature, this);
moel@13:       temperatures[2] = new Sensor("System", 2, SensorType.Temperature, this);
moel@13: 
moel@19:       switch (chip) {
moel@31:         case Chip.W83627DHG:
moel@31:         case Chip.W83627DHGP: 
moel@31:           fanNames = new string[] { "System", "CPU #1", "Auxiliary #1", 
moel@31:             "CPU #2", "Auxiliary #2" };
moel@31:           voltageGains = new float[] { 0.008f, 1, 1, 0.016f, 1, 1, 1, 0.016f };
moel@31:           voltages = new Sensor[3];
moel@31:           voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
moel@31:           voltages[1] = new Sensor("+3.3V", 3, SensorType.Voltage, this);
moel@31:           voltages[2] = new Sensor("Battery", 7, SensorType.Voltage, this);
moel@31:           break;
moel@31:         case Chip.W83627HF: 
moel@31:           fanNames = new string[] { "Fan #1", "Fan #2", "Fan #3" };
moel@31:           voltageGains = new float[] { 0.016f, 1, 0.016f, 1, 1, 1, 1, 0.016f };
moel@31:           voltages = new Sensor[3];
moel@31:           voltages[0] = new Sensor("CPU VCore", 0, SensorType.Voltage, this);
moel@31:           voltages[1] = new Sensor("+3.3V", 2, SensorType.Voltage, this);
moel@31:           voltages[2] = new Sensor("Battery", 7, SensorType.Voltage, this);
moel@31:           break;
moel@31:         default: fanNames = new string[0];
moel@31:           break;
moel@19:       }
moel@31:       
moel@31:       fans = new Sensor[fanNames.Length];
moel@31:       for (int i = 0; i < fanNames.Length; i++)
moel@31:         fans[i] = new Sensor(fanNames[i], i, SensorType.Fan, this);
moel@31:     }    
moel@1: 
moel@13:     public void Update() {
moel@13:       foreach (Sensor sensor in voltages) {
moel@13:         if (sensor.Index < 7) {
moel@13:           int value = ReadByte(0, (byte)(VOLTAGE_BASE_REG + sensor.Index));
moel@13:           sensor.Value = voltageGains[sensor.Index] * value;
moel@13:           if (sensor.Value > 0)
moel@13:             ActivateSensor(sensor);
moel@13:           else
moel@13:             DeactivateSensor(sensor);
moel@13:         } else {
moel@13:           // Battery voltage
moel@13:           bool valid = (ReadByte(0, 0x5D) & 0x01) > 0;
moel@13:           if (valid) {
moel@13:             sensor.Value = voltageGains[sensor.Index] * 
moel@13:               ReadByte(5, 0x51);
moel@13:             ActivateSensor(sensor);
moel@13:           } else
moel@13:             DeactivateSensor(sensor);
moel@13:         }
moel@13:       }
moel@1: 
moel@13:       foreach (Sensor sensor in temperatures) {
moel@13:         int value;
moel@13:         if (sensor.Index < 2) {
moel@26:           value = (sbyte)ReadByte((byte)(sensor.Index + 1), TEMPERATURE_BASE_REG);
moel@13:           value = (value << 1) | ReadByte((byte)(sensor.Index + 1),
moel@13:             (byte)(TEMPERATURE_BASE_REG + 1)) >> 7;
moel@13:         } else {
moel@26:           value = (sbyte)ReadByte(0, TEMPERATURE_SYS_REG) << 1;
moel@13:         }
moel@13:         sensor.Value = value / 2.0f;
moel@26:         if (value < 0xFE)
moel@13:           ActivateSensor(sensor);
moel@13:         else
moel@13:           DeactivateSensor(sensor);
moel@13:       }
moel@13: 
moel@13:       long bits = 0;
moel@13:       for (int i = 0; i < FAN_BIT_REG.Length; i++)
moel@13:         bits = (bits << 8) | ReadByte(0, FAN_BIT_REG[i]);
moel@13:       foreach (Sensor sensor in fans) {
moel@13:         int count = ReadByte(FAN_TACHO_BANK[sensor.Index], 
moel@13:           FAN_TACHO_REG[sensor.Index]);
moel@13:         int divisorBits = (int)(
moel@13:           (((bits >> FAN_DIV_BIT2[sensor.Index]) & 1) << 2) |
moel@13:           (((bits >> FAN_DIV_BIT1[sensor.Index]) & 1) << 1) |
moel@13:            ((bits >> FAN_DIV_BIT0[sensor.Index]) & 1));
moel@13:         int divisor = 1 << divisorBits;
moel@13:         sensor.Value = (count < 0xff) ? 1.35e6f / (count * divisor) : 0;
moel@13:         ActivateSensor(sensor);        
moel@13:       }     
moel@13:     }
moel@1:   }
moel@1: }