Hardware/LPC/W836XX.cs
changeset 85 ec4ccaa1210d
parent 84 05bf128434c6
child 110 411b72b73d8f
     1.1 --- a/Hardware/LPC/W836XX.cs	Sat Mar 27 13:04:34 2010 +0000
     1.2 +++ b/Hardware/LPC/W836XX.cs	Sat Mar 27 19:55:09 2010 +0000
     1.3 @@ -90,7 +90,7 @@
     1.4           (ushort)(address + ADDRESS_REGISTER_OFFSET), register);
     1.5        return WinRing0.ReadIoPortByte(
     1.6          (ushort)(address + DATA_REGISTER_OFFSET));
     1.7 -    } 
     1.8 +    }
     1.9  
    1.10      private void WriteByte(byte bank, byte register, byte value) {
    1.11        WinRing0.WriteIoPortByte(
    1.12 @@ -195,6 +195,17 @@
    1.13        return vendorId == WINBOND_VENDOR_ID;
    1.14      }
    1.15  
    1.16 +    private ulong SetBit(ulong target, int bit, int value) {
    1.17 +      if ((value & 1) != value)
    1.18 +        throw new ArgumentException("Value must be one bit only.");
    1.19 +
    1.20 +      if (bit < 0 || bit > 63)
    1.21 +        throw new ArgumentException("Bit out of range.");
    1.22 +
    1.23 +      ulong mask = (((ulong)1) << bit);
    1.24 +      return value > 0 ? target | mask : target & ~mask;
    1.25 +    }
    1.26 +
    1.27      public void Update() {
    1.28  
    1.29        foreach (Sensor sensor in voltages) {
    1.30 @@ -244,22 +255,49 @@
    1.31          }
    1.32        }
    1.33  
    1.34 -      long bits = 0;
    1.35 +      ulong bits = 0;
    1.36        for (int i = 0; i < FAN_BIT_REG.Length; i++)
    1.37          bits = (bits << 8) | ReadByte(0, FAN_BIT_REG[i]);
    1.38 +      ulong newBits = bits;
    1.39        foreach (Sensor sensor in fans) {
    1.40          int count = ReadByte(FAN_TACHO_BANK[sensor.Index], 
    1.41            FAN_TACHO_REG[sensor.Index]);
    1.42 +        
    1.43 +        // assemble fan divisor
    1.44          int divisorBits = (int)(
    1.45            (((bits >> FAN_DIV_BIT2[sensor.Index]) & 1) << 2) |
    1.46            (((bits >> FAN_DIV_BIT1[sensor.Index]) & 1) << 1) |
    1.47             ((bits >> FAN_DIV_BIT0[sensor.Index]) & 1));
    1.48          int divisor = 1 << divisorBits;
    1.49 +       
    1.50          float value = (count < 0xff) ? 1.35e6f / (count * divisor) : 0;
    1.51          sensor.Value = value;
    1.52          if (value > 0)
    1.53 -          ActivateSensor(sensor);        
    1.54 -      }     
    1.55 +          ActivateSensor(sensor);
    1.56 +
    1.57 +        // update fan divisor
    1.58 +        if (count > 192 && divisorBits < 7) 
    1.59 +          divisorBits++;
    1.60 +        if (count < 96 && divisorBits > 0)
    1.61 +          divisorBits--;
    1.62 +
    1.63 +        newBits = SetBit(newBits, FAN_DIV_BIT2[sensor.Index], 
    1.64 +          (divisorBits >> 2) & 1);
    1.65 +        newBits = SetBit(newBits, FAN_DIV_BIT1[sensor.Index], 
    1.66 +          (divisorBits >> 1) & 1);
    1.67 +        newBits = SetBit(newBits, FAN_DIV_BIT0[sensor.Index], 
    1.68 +          divisorBits & 1);
    1.69 +      }
    1.70 +     
    1.71 +      // write new fan divisors 
    1.72 +      for (int i = FAN_BIT_REG.Length - 1; i >= 0; i--) {
    1.73 +        byte oldByte = (byte)(bits & 0xFF);
    1.74 +        byte newByte = (byte)(newBits & 0xFF);
    1.75 +        bits = bits >> 8;
    1.76 +        newBits = newBits >> 8;
    1.77 +        if (oldByte != newByte) 
    1.78 +          WriteByte(0, FAN_BIT_REG[i], newByte);        
    1.79 +      }
    1.80      }
    1.81  
    1.82      public string GetReport() {