Added support for sensor parameters. Fixed Core and Thread count detection for Intel Core i7 CPUs with disabled HyperThreading.
authormoel.mich
Sat, 27 Feb 2010 15:55:17 +0000
changeset 631a7c13ac7348
parent 62 5400e3e383f7
child 64 15181001ee61
Added support for sensor parameters. Fixed Core and Thread count detection for Intel Core i7 CPUs with disabled HyperThreading.
GUI/AboutBox.Designer.cs
GUI/MainForm.Designer.cs
GUI/MainForm.cs
GUI/ParameterForm.Designer.cs
GUI/ParameterForm.cs
GUI/ParameterForm.resx
Hardware/CPU/AMD0FCPU.cs
Hardware/CPU/AMD10CPU.cs
Hardware/CPU/IntelCPU.cs
Hardware/Computer.cs
Hardware/IParameter.cs
Hardware/ISensor.cs
Hardware/LPC/F718XX.cs
Hardware/LPC/IT87XX.cs
Hardware/LPC/W836XX.cs
Hardware/Parameter.cs
Hardware/Sensor.cs
Hardware/TBalancer/TBalancer.cs
OpenHardwareMonitor.csproj
Properties/AssemblyInfo.cs
Utilities/Config.cs
Utilities/Configuration.cs
Utilities/IReadOnlyArray.cs
Utilities/ReadOnlyArray.cs
     1.1 --- a/GUI/AboutBox.Designer.cs	Tue Feb 23 19:45:40 2010 +0000
     1.2 +++ b/GUI/AboutBox.Designer.cs	Sat Feb 27 15:55:17 2010 +0000
     1.3 @@ -122,9 +122,9 @@
     1.4        this.label3.Location = new System.Drawing.Point(86, 36);
     1.5        this.label3.Margin = new System.Windows.Forms.Padding(12, 0, 12, 0);
     1.6        this.label3.Name = "label3";
     1.7 -      this.label3.Size = new System.Drawing.Size(99, 15);
     1.8 +      this.label3.Size = new System.Drawing.Size(132, 15);
     1.9        this.label3.TabIndex = 4;
    1.10 -      this.label3.Text = "Version " + System.Windows.Forms.Application.ProductVersion + " Beta";
    1.11 +      this.label3.Text = "Version 9.0.30729.1 Beta";
    1.12        // 
    1.13        // label4
    1.14        // 
    1.15 @@ -189,6 +189,7 @@
    1.16        this.MaximizeBox = false;
    1.17        this.MinimizeBox = false;
    1.18        this.Name = "AboutBox";
    1.19 +      this.ShowInTaskbar = false;
    1.20        this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
    1.21        this.Text = "About";
    1.22        ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit();
     2.1 --- a/GUI/MainForm.Designer.cs	Tue Feb 23 19:45:40 2010 +0000
     2.2 +++ b/GUI/MainForm.Designer.cs	Sat Feb 27 15:55:17 2010 +0000
     2.3 @@ -103,12 +103,12 @@
     2.4        this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
     2.5        this.timer = new System.Windows.Forms.Timer(this.components);
     2.6        this.splitContainer = new System.Windows.Forms.SplitContainer();
     2.7 +      this.plotPanel = new OpenHardwareMonitor.GUI.PlotPanel();
     2.8        this.notifyContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
     2.9        this.restoreToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem();
    2.10        this.toolStripMenuItem2 = new System.Windows.Forms.ToolStripSeparator();
    2.11        this.exitToolStripMenuItem1 = new System.Windows.Forms.ToolStripMenuItem();
    2.12        this.sensorContextMenuStrip = new System.Windows.Forms.ContextMenuStrip(this.components);
    2.13 -      this.plotPanel = new OpenHardwareMonitor.GUI.PlotPanel();
    2.14        this.columnsContextMenuStrip.SuspendLayout();
    2.15        this.menuStrip.SuspendLayout();
    2.16        this.splitContainer.Panel1.SuspendLayout();
    2.17 @@ -148,6 +148,7 @@
    2.18        this.treeView.TabIndex = 0;
    2.19        this.treeView.Text = "treeView";
    2.20        this.treeView.UseColumns = true;
    2.21 +      this.treeView.NodeMouseDoubleClick += new System.EventHandler<Aga.Controls.Tree.TreeNodeAdvMouseEventArgs>(this.treeView_NodeMouseDoubleClick);
    2.22        this.treeView.Click += new System.EventHandler(this.treeView_Click);
    2.23        // 
    2.24        // sensor
    2.25 @@ -501,6 +502,16 @@
    2.26        this.splitContainer.SplitterWidth = 3;
    2.27        this.splitContainer.TabIndex = 3;
    2.28        // 
    2.29 +      // plotPanel
    2.30 +      // 
    2.31 +      this.plotPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
    2.32 +      this.plotPanel.Dock = System.Windows.Forms.DockStyle.Fill;
    2.33 +      this.plotPanel.Font = new System.Drawing.Font("Segoe UI", 9F);
    2.34 +      this.plotPanel.Location = new System.Drawing.Point(0, 0);
    2.35 +      this.plotPanel.Name = "plotPanel";
    2.36 +      this.plotPanel.Size = new System.Drawing.Size(478, 198);
    2.37 +      this.plotPanel.TabIndex = 0;
    2.38 +      // 
    2.39        // notifyContextMenuStrip
    2.40        // 
    2.41        this.notifyContextMenuStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
    2.42 @@ -535,16 +546,6 @@
    2.43        this.sensorContextMenuStrip.Name = "sensorContextMenuStrip";
    2.44        this.sensorContextMenuStrip.Size = new System.Drawing.Size(61, 4);
    2.45        // 
    2.46 -      // plotPanel
    2.47 -      // 
    2.48 -      this.plotPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
    2.49 -      this.plotPanel.Dock = System.Windows.Forms.DockStyle.Fill;
    2.50 -      this.plotPanel.Font = new System.Drawing.Font("Segoe UI", 9F);
    2.51 -      this.plotPanel.Location = new System.Drawing.Point(0, 0);
    2.52 -      this.plotPanel.Name = "plotPanel";
    2.53 -      this.plotPanel.Size = new System.Drawing.Size(478, 198);
    2.54 -      this.plotPanel.TabIndex = 0;
    2.55 -      // 
    2.56        // MainForm
    2.57        // 
    2.58        this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
     3.1 --- a/GUI/MainForm.cs	Tue Feb 23 19:45:40 2010 +0000
     3.2 +++ b/GUI/MainForm.cs	Sat Feb 27 15:55:17 2010 +0000
     3.3 @@ -63,7 +63,7 @@
     3.4        InitializeComponent();
     3.5        this.Font = SystemFonts.MessageBoxFont;
     3.6        treeView.Font = SystemFonts.MessageBoxFont;
     3.7 -      plotPanel.Font = SystemFonts.MessageBoxFont;      
     3.8 +      plotPanel.Font = SystemFonts.MessageBoxFont;
     3.9        
    3.10        nodeCheckBox.IsVisibleValueNeeded += 
    3.11          new EventHandler<NodeControlValueEventArgs>(
    3.12 @@ -320,6 +320,13 @@
    3.13          if (node != null && node.Sensor != null) {
    3.14  
    3.15            sensorContextMenuStrip.Items.Clear();
    3.16 +          if (node.Sensor.Parameters.Length > 0) {
    3.17 +            ToolStripMenuItem item = new ToolStripMenuItem("Parameters...");
    3.18 +            item.Click += delegate(object obj, EventArgs args) {
    3.19 +              ShowParameterForm(node.Sensor);
    3.20 +            };
    3.21 +            sensorContextMenuStrip.Items.Add(item);
    3.22 +          }
    3.23            if (sensorSystemTray.Contains(node.Sensor)) {
    3.24              ToolStripMenuItem item = new ToolStripMenuItem("Remove From Tray");
    3.25              item.Click += delegate(object obj, EventArgs args) {
    3.26 @@ -398,5 +405,21 @@
    3.27  
    3.28        sensorSystemTray.Remove(sensor);
    3.29      }
    3.30 +
    3.31 +    private void ShowParameterForm(ISensor sensor) {
    3.32 +      ParameterForm form = new ParameterForm();
    3.33 +      form.Parameters = sensor.Parameters;
    3.34 +      form.captionLabel.Text = sensor.Name;
    3.35 +      form.ShowDialog();
    3.36 +    }
    3.37 +
    3.38 +    private void treeView_NodeMouseDoubleClick(object sender, 
    3.39 +      TreeNodeAdvMouseEventArgs e) {
    3.40 +      SensorNode node = e.Node.Tag as SensorNode;
    3.41 +      if (node != null && node.Sensor != null && 
    3.42 +        node.Sensor.Parameters.Length > 0) {
    3.43 +        ShowParameterForm(node.Sensor);
    3.44 +      }
    3.45 +    }
    3.46    }
    3.47  }
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/GUI/ParameterForm.Designer.cs	Sat Feb 27 15:55:17 2010 +0000
     4.3 @@ -0,0 +1,188 @@
     4.4 +namespace OpenHardwareMonitor.GUI {
     4.5 +  partial class ParameterForm {
     4.6 +    /// <summary>
     4.7 +    /// Required designer variable.
     4.8 +    /// </summary>
     4.9 +    private System.ComponentModel.IContainer components = null;
    4.10 +
    4.11 +    /// <summary>
    4.12 +    /// Clean up any resources being used.
    4.13 +    /// </summary>
    4.14 +    /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
    4.15 +    protected override void Dispose(bool disposing) {
    4.16 +      if (disposing && (components != null)) {
    4.17 +        components.Dispose();
    4.18 +      }
    4.19 +      base.Dispose(disposing);
    4.20 +    }
    4.21 +
    4.22 +    #region Windows Form Designer generated code
    4.23 +
    4.24 +    /// <summary>
    4.25 +    /// Required method for Designer support - do not modify
    4.26 +    /// the contents of this method with the code editor.
    4.27 +    /// </summary>
    4.28 +    private void InitializeComponent() {
    4.29 +      this.components = new System.ComponentModel.Container();
    4.30 +      System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
    4.31 +      this.okButton = new System.Windows.Forms.Button();
    4.32 +      this.cancelButton = new System.Windows.Forms.Button();
    4.33 +      this.captionLabel = new System.Windows.Forms.Label();
    4.34 +      this.dataGridView = new System.Windows.Forms.DataGridView();
    4.35 +      this.NameColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
    4.36 +      this.Default = new System.Windows.Forms.DataGridViewCheckBoxColumn();
    4.37 +      this.ValueColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
    4.38 +      this.bindingSource = new System.Windows.Forms.BindingSource(this.components);
    4.39 +      this.descriptionLabel = new System.Windows.Forms.Label();
    4.40 +      ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit();
    4.41 +      ((System.ComponentModel.ISupportInitialize)(this.bindingSource)).BeginInit();
    4.42 +      this.SuspendLayout();
    4.43 +      // 
    4.44 +      // okButton
    4.45 +      // 
    4.46 +      this.okButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
    4.47 +      this.okButton.DialogResult = System.Windows.Forms.DialogResult.OK;
    4.48 +      this.okButton.Location = new System.Drawing.Point(186, 213);
    4.49 +      this.okButton.Name = "okButton";
    4.50 +      this.okButton.Size = new System.Drawing.Size(75, 23);
    4.51 +      this.okButton.TabIndex = 2;
    4.52 +      this.okButton.Text = "OK";
    4.53 +      this.okButton.UseVisualStyleBackColor = true;
    4.54 +      this.okButton.Click += new System.EventHandler(this.okButton_Click);
    4.55 +      // 
    4.56 +      // cancelButton
    4.57 +      // 
    4.58 +      this.cancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
    4.59 +      this.cancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
    4.60 +      this.cancelButton.Location = new System.Drawing.Point(267, 213);
    4.61 +      this.cancelButton.Name = "cancelButton";
    4.62 +      this.cancelButton.Size = new System.Drawing.Size(75, 23);
    4.63 +      this.cancelButton.TabIndex = 3;
    4.64 +      this.cancelButton.Text = "Canel";
    4.65 +      this.cancelButton.UseVisualStyleBackColor = true;
    4.66 +      // 
    4.67 +      // captionLabel
    4.68 +      // 
    4.69 +      this.captionLabel.AutoSize = true;
    4.70 +      this.captionLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
    4.71 +      this.captionLabel.Location = new System.Drawing.Point(12, 9);
    4.72 +      this.captionLabel.Name = "captionLabel";
    4.73 +      this.captionLabel.Size = new System.Drawing.Size(80, 13);
    4.74 +      this.captionLabel.TabIndex = 4;
    4.75 +      this.captionLabel.Text = "captionLabel";
    4.76 +      // 
    4.77 +      // dataGridView
    4.78 +      // 
    4.79 +      this.dataGridView.AllowUserToAddRows = false;
    4.80 +      this.dataGridView.AllowUserToDeleteRows = false;
    4.81 +      this.dataGridView.AllowUserToResizeRows = false;
    4.82 +      this.dataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
    4.83 +                  | System.Windows.Forms.AnchorStyles.Left)
    4.84 +                  | System.Windows.Forms.AnchorStyles.Right)));
    4.85 +      this.dataGridView.AutoGenerateColumns = false;
    4.86 +      this.dataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill;
    4.87 +      this.dataGridView.BackgroundColor = System.Drawing.SystemColors.Window;
    4.88 +      this.dataGridView.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
    4.89 +      this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
    4.90 +      this.dataGridView.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
    4.91 +            this.NameColumn,
    4.92 +            this.Default,
    4.93 +            this.ValueColumn});
    4.94 +      this.dataGridView.DataSource = this.bindingSource;
    4.95 +      dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
    4.96 +      dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Window;
    4.97 +      dataGridViewCellStyle1.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
    4.98 +      dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.ControlText;
    4.99 +      dataGridViewCellStyle1.SelectionBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(240)))), ((int)(((byte)(240)))), ((int)(((byte)(240)))));
   4.100 +      dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.ControlText;
   4.101 +      dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
   4.102 +      this.dataGridView.DefaultCellStyle = dataGridViewCellStyle1;
   4.103 +      this.dataGridView.Location = new System.Drawing.Point(15, 30);
   4.104 +      this.dataGridView.MultiSelect = false;
   4.105 +      this.dataGridView.Name = "dataGridView";
   4.106 +      this.dataGridView.RowHeadersVisible = false;
   4.107 +      this.dataGridView.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect;
   4.108 +      this.dataGridView.ShowRowErrors = false;
   4.109 +      this.dataGridView.Size = new System.Drawing.Size(327, 121);
   4.110 +      this.dataGridView.TabIndex = 0;
   4.111 +      this.dataGridView.RowEnter += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_RowEnter);
   4.112 +      this.dataGridView.CellValidating += new System.Windows.Forms.DataGridViewCellValidatingEventHandler(this.dataGridView_CellValidating);
   4.113 +      this.dataGridView.CellEndEdit += new System.Windows.Forms.DataGridViewCellEventHandler(this.dataGridView_CellEndEdit);
   4.114 +      this.dataGridView.CurrentCellDirtyStateChanged += new System.EventHandler(this.dataGridView_CurrentCellDirtyStateChanged);
   4.115 +      // 
   4.116 +      // NameColumn
   4.117 +      // 
   4.118 +      this.NameColumn.DataPropertyName = "Name";
   4.119 +      this.NameColumn.HeaderText = "Name";
   4.120 +      this.NameColumn.Name = "NameColumn";
   4.121 +      this.NameColumn.ReadOnly = true;
   4.122 +      this.NameColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
   4.123 +      // 
   4.124 +      // Default
   4.125 +      // 
   4.126 +      this.Default.AutoSizeMode = System.Windows.Forms.DataGridViewAutoSizeColumnMode.ColumnHeader;
   4.127 +      this.Default.DataPropertyName = "Default";
   4.128 +      this.Default.HeaderText = "Default";
   4.129 +      this.Default.Name = "Default";
   4.130 +      this.Default.Width = 47;
   4.131 +      // 
   4.132 +      // ValueColumn
   4.133 +      // 
   4.134 +      this.ValueColumn.DataPropertyName = "Value";
   4.135 +      this.ValueColumn.HeaderText = "Value";
   4.136 +      this.ValueColumn.Name = "ValueColumn";
   4.137 +      this.ValueColumn.SortMode = System.Windows.Forms.DataGridViewColumnSortMode.NotSortable;
   4.138 +      // 
   4.139 +      // bindingSource
   4.140 +      // 
   4.141 +      this.bindingSource.AllowNew = false;
   4.142 +      // 
   4.143 +      // descriptionLabel
   4.144 +      // 
   4.145 +      this.descriptionLabel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
   4.146 +                  | System.Windows.Forms.AnchorStyles.Right)));
   4.147 +      this.descriptionLabel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
   4.148 +      this.descriptionLabel.Location = new System.Drawing.Point(15, 154);
   4.149 +      this.descriptionLabel.Name = "descriptionLabel";
   4.150 +      this.descriptionLabel.Padding = new System.Windows.Forms.Padding(2);
   4.151 +      this.descriptionLabel.Size = new System.Drawing.Size(327, 50);
   4.152 +      this.descriptionLabel.TabIndex = 6;
   4.153 +      this.descriptionLabel.Text = "descriptionLabel";
   4.154 +      // 
   4.155 +      // ParameterForm
   4.156 +      // 
   4.157 +      this.AcceptButton = this.okButton;
   4.158 +      this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
   4.159 +      this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
   4.160 +      this.ClientSize = new System.Drawing.Size(354, 248);
   4.161 +      this.Controls.Add(this.descriptionLabel);
   4.162 +      this.Controls.Add(this.dataGridView);
   4.163 +      this.Controls.Add(this.captionLabel);
   4.164 +      this.Controls.Add(this.cancelButton);
   4.165 +      this.Controls.Add(this.okButton);
   4.166 +      this.Name = "ParameterForm";
   4.167 +      this.ShowIcon = false;
   4.168 +      this.ShowInTaskbar = false;
   4.169 +      this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
   4.170 +      this.Text = "Parameters";
   4.171 +      ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit();
   4.172 +      ((System.ComponentModel.ISupportInitialize)(this.bindingSource)).EndInit();
   4.173 +      this.ResumeLayout(false);
   4.174 +      this.PerformLayout();
   4.175 +
   4.176 +    }
   4.177 +
   4.178 +    #endregion
   4.179 +
   4.180 +    private System.Windows.Forms.Button okButton;
   4.181 +    private System.Windows.Forms.Button cancelButton;
   4.182 +    public System.Windows.Forms.Label captionLabel;
   4.183 +    private System.Windows.Forms.DataGridView dataGridView;
   4.184 +    private System.Windows.Forms.Label descriptionLabel;
   4.185 +    private System.Windows.Forms.BindingSource bindingSource;
   4.186 +    private System.Windows.Forms.DataGridViewTextBoxColumn NameColumn;
   4.187 +    private System.Windows.Forms.DataGridViewCheckBoxColumn Default;
   4.188 +    private System.Windows.Forms.DataGridViewTextBoxColumn ValueColumn;
   4.189 +
   4.190 +  }
   4.191 +}
   4.192 \ No newline at end of file
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/GUI/ParameterForm.cs	Sat Feb 27 15:55:17 2010 +0000
     5.3 @@ -0,0 +1,122 @@
     5.4 +using System;
     5.5 +using System.Collections.Generic;
     5.6 +using System.ComponentModel;
     5.7 +using System.Text;
     5.8 +using System.Windows.Forms;
     5.9 +using OpenHardwareMonitor.Hardware;
    5.10 +using OpenHardwareMonitor.Utilities;
    5.11 +
    5.12 +namespace OpenHardwareMonitor.GUI {
    5.13 +  public partial class ParameterForm : Form {
    5.14 +
    5.15 +    private IReadOnlyArray<IParameter> parameters;
    5.16 +    private BindingList<ParameterRow> parameterRows;
    5.17 +
    5.18 +    public ParameterForm() {
    5.19 +      InitializeComponent();
    5.20 +    }
    5.21 +    
    5.22 +    public IReadOnlyArray<IParameter> Parameters {
    5.23 +      get {
    5.24 +        return parameters;
    5.25 +      }
    5.26 +      set {
    5.27 +        parameters = value;
    5.28 +        parameterRows = new BindingList<ParameterRow>();
    5.29 +        foreach (IParameter parameter in parameters)
    5.30 +          parameterRows.Add(new ParameterRow(parameter));
    5.31 +        bindingSource.DataSource = parameterRows;
    5.32 +      }
    5.33 +    }
    5.34 +
    5.35 +    private class ParameterRow : INotifyPropertyChanged {
    5.36 +      public IParameter parameter;
    5.37 +      private float value;
    5.38 +      public bool isDefault;
    5.39 +
    5.40 +      public event PropertyChangedEventHandler PropertyChanged;
    5.41 +
    5.42 +      private void NotifyPropertyChanged(String propertyName) {
    5.43 +        if (PropertyChanged != null) {
    5.44 +          PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    5.45 +        }
    5.46 +      }
    5.47 +
    5.48 +      public ParameterRow(IParameter parameter){
    5.49 +        this.parameter = parameter;
    5.50 +        this.value = parameter.Value;
    5.51 +        this.isDefault = parameter.IsDefault;
    5.52 +      }
    5.53 +
    5.54 +      public string Name {
    5.55 +        get { return parameter.Name; }
    5.56 +      }
    5.57 +
    5.58 +      public float Value {
    5.59 +        get { return value; }
    5.60 +        set {            
    5.61 +          this.isDefault = false;
    5.62 +          this.value = value;
    5.63 +          NotifyPropertyChanged("Default");
    5.64 +          NotifyPropertyChanged("Value");
    5.65 +        }
    5.66 +      }
    5.67 +
    5.68 +      public bool Default {
    5.69 +        get { return isDefault; }
    5.70 +        set {
    5.71 +          isDefault = value;
    5.72 +          if (value)
    5.73 +            this.value = parameter.DefaultValue;
    5.74 +          NotifyPropertyChanged("Default");
    5.75 +          NotifyPropertyChanged("Value");
    5.76 +        }
    5.77 +      }
    5.78 +    }
    5.79 +
    5.80 +    private void dataGridView_RowEnter(object sender, 
    5.81 +      DataGridViewCellEventArgs e) 
    5.82 +    {
    5.83 +      if (e.RowIndex >= 0 && e.RowIndex < parameters.Length)
    5.84 +        descriptionLabel.Text = parameters[e.RowIndex].Description;
    5.85 +      else
    5.86 +        descriptionLabel.Text = "";
    5.87 +    }
    5.88 +
    5.89 +    private void dataGridView_CellValidating(object sender, 
    5.90 +      DataGridViewCellValidatingEventArgs e) 
    5.91 +    {
    5.92 +      float value;
    5.93 +      if (e.ColumnIndex == 2 &&
    5.94 +        !float.TryParse(e.FormattedValue.ToString(), out value)) {
    5.95 +        dataGridView.Rows[e.RowIndex].Cells[0].ErrorText = 
    5.96 +          "Invalid value";
    5.97 +        e.Cancel = true;
    5.98 +      }
    5.99 +    }
   5.100 +
   5.101 +    private void dataGridView_CellEndEdit(object sender,
   5.102 +      DataGridViewCellEventArgs e) {
   5.103 +      dataGridView.Rows[e.RowIndex].Cells[0].ErrorText = "";
   5.104 +    }
   5.105 +
   5.106 +    private void okButton_Click(object sender, EventArgs e) {
   5.107 +      foreach (ParameterRow row in parameterRows) {
   5.108 +        if (row.Default) {
   5.109 +          row.parameter.IsDefault = true;
   5.110 +        } else {
   5.111 +          row.parameter.Value = row.Value;
   5.112 +        }
   5.113 +      }
   5.114 +    }
   5.115 +
   5.116 +    private void dataGridView_CurrentCellDirtyStateChanged(object sender, 
   5.117 +      EventArgs e) {
   5.118 +      if (dataGridView.CurrentCell is DataGridViewCheckBoxCell ||
   5.119 +        dataGridView.CurrentCell is DataGridViewComboBoxCell) 
   5.120 +      {
   5.121 +        dataGridView.CommitEdit(DataGridViewDataErrorContexts.Commit);
   5.122 +      }
   5.123 +    }
   5.124 +  }
   5.125 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/GUI/ParameterForm.resx	Sat Feb 27 15:55:17 2010 +0000
     6.3 @@ -0,0 +1,132 @@
     6.4 +<?xml version="1.0" encoding="utf-8"?>
     6.5 +<root>
     6.6 +  <!-- 
     6.7 +    Microsoft ResX Schema 
     6.8 +    
     6.9 +    Version 2.0
    6.10 +    
    6.11 +    The primary goals of this format is to allow a simple XML format 
    6.12 +    that is mostly human readable. The generation and parsing of the 
    6.13 +    various data types are done through the TypeConverter classes 
    6.14 +    associated with the data types.
    6.15 +    
    6.16 +    Example:
    6.17 +    
    6.18 +    ... ado.net/XML headers & schema ...
    6.19 +    <resheader name="resmimetype">text/microsoft-resx</resheader>
    6.20 +    <resheader name="version">2.0</resheader>
    6.21 +    <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
    6.22 +    <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
    6.23 +    <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
    6.24 +    <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
    6.25 +    <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
    6.26 +        <value>[base64 mime encoded serialized .NET Framework object]</value>
    6.27 +    </data>
    6.28 +    <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
    6.29 +        <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
    6.30 +        <comment>This is a comment</comment>
    6.31 +    </data>
    6.32 +                
    6.33 +    There are any number of "resheader" rows that contain simple 
    6.34 +    name/value pairs.
    6.35 +    
    6.36 +    Each data row contains a name, and value. The row also contains a 
    6.37 +    type or mimetype. Type corresponds to a .NET class that support 
    6.38 +    text/value conversion through the TypeConverter architecture. 
    6.39 +    Classes that don't support this are serialized and stored with the 
    6.40 +    mimetype set.
    6.41 +    
    6.42 +    The mimetype is used for serialized objects, and tells the 
    6.43 +    ResXResourceReader how to depersist the object. This is currently not 
    6.44 +    extensible. For a given mimetype the value must be set accordingly:
    6.45 +    
    6.46 +    Note - application/x-microsoft.net.object.binary.base64 is the format 
    6.47 +    that the ResXResourceWriter will generate, however the reader can 
    6.48 +    read any of the formats listed below.
    6.49 +    
    6.50 +    mimetype: application/x-microsoft.net.object.binary.base64
    6.51 +    value   : The object must be serialized with 
    6.52 +            : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
    6.53 +            : and then encoded with base64 encoding.
    6.54 +    
    6.55 +    mimetype: application/x-microsoft.net.object.soap.base64
    6.56 +    value   : The object must be serialized with 
    6.57 +            : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
    6.58 +            : and then encoded with base64 encoding.
    6.59 +
    6.60 +    mimetype: application/x-microsoft.net.object.bytearray.base64
    6.61 +    value   : The object must be serialized into a byte array 
    6.62 +            : using a System.ComponentModel.TypeConverter
    6.63 +            : and then encoded with base64 encoding.
    6.64 +    -->
    6.65 +  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    6.66 +    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    6.67 +    <xsd:element name="root" msdata:IsDataSet="true">
    6.68 +      <xsd:complexType>
    6.69 +        <xsd:choice maxOccurs="unbounded">
    6.70 +          <xsd:element name="metadata">
    6.71 +            <xsd:complexType>
    6.72 +              <xsd:sequence>
    6.73 +                <xsd:element name="value" type="xsd:string" minOccurs="0" />
    6.74 +              </xsd:sequence>
    6.75 +              <xsd:attribute name="name" use="required" type="xsd:string" />
    6.76 +              <xsd:attribute name="type" type="xsd:string" />
    6.77 +              <xsd:attribute name="mimetype" type="xsd:string" />
    6.78 +              <xsd:attribute ref="xml:space" />
    6.79 +            </xsd:complexType>
    6.80 +          </xsd:element>
    6.81 +          <xsd:element name="assembly">
    6.82 +            <xsd:complexType>
    6.83 +              <xsd:attribute name="alias" type="xsd:string" />
    6.84 +              <xsd:attribute name="name" type="xsd:string" />
    6.85 +            </xsd:complexType>
    6.86 +          </xsd:element>
    6.87 +          <xsd:element name="data">
    6.88 +            <xsd:complexType>
    6.89 +              <xsd:sequence>
    6.90 +                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
    6.91 +                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
    6.92 +              </xsd:sequence>
    6.93 +              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
    6.94 +              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
    6.95 +              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
    6.96 +              <xsd:attribute ref="xml:space" />
    6.97 +            </xsd:complexType>
    6.98 +          </xsd:element>
    6.99 +          <xsd:element name="resheader">
   6.100 +            <xsd:complexType>
   6.101 +              <xsd:sequence>
   6.102 +                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
   6.103 +              </xsd:sequence>
   6.104 +              <xsd:attribute name="name" type="xsd:string" use="required" />
   6.105 +            </xsd:complexType>
   6.106 +          </xsd:element>
   6.107 +        </xsd:choice>
   6.108 +      </xsd:complexType>
   6.109 +    </xsd:element>
   6.110 +  </xsd:schema>
   6.111 +  <resheader name="resmimetype">
   6.112 +    <value>text/microsoft-resx</value>
   6.113 +  </resheader>
   6.114 +  <resheader name="version">
   6.115 +    <value>2.0</value>
   6.116 +  </resheader>
   6.117 +  <resheader name="reader">
   6.118 +    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   6.119 +  </resheader>
   6.120 +  <resheader name="writer">
   6.121 +    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   6.122 +  </resheader>
   6.123 +  <metadata name="NameColumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
   6.124 +    <value>True</value>
   6.125 +  </metadata>
   6.126 +  <metadata name="Default.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
   6.127 +    <value>True</value>
   6.128 +  </metadata>
   6.129 +  <metadata name="ValueColumn.UserAddedColumn" type="System.Boolean, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
   6.130 +    <value>True</value>
   6.131 +  </metadata>
   6.132 +  <metadata name="bindingSource.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
   6.133 +    <value>17, 17</value>
   6.134 +  </metadata>
   6.135 +</root>
   6.136 \ No newline at end of file
     7.1 --- a/Hardware/CPU/AMD0FCPU.cs	Tue Feb 23 19:45:40 2010 +0000
     7.2 +++ b/Hardware/CPU/AMD0FCPU.cs	Sat Feb 27 15:55:17 2010 +0000
     7.3 @@ -79,13 +79,23 @@
     7.4  
     7.5        totalLoad = new Sensor("CPU Total", 0, SensorType.Load, this);
     7.6          
     7.7 +      offset = -49.0f;
     7.8 +
     7.9 +      // AM2+ 65nm +21 offset
    7.10 +      if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c) 
    7.11 +        offset += 21;
    7.12 +
    7.13        coreTemperatures = new Sensor[coreCount];
    7.14        coreLoads = new Sensor[coreCount];
    7.15        for (int i = 0; i < coreCount; i++) {
    7.16          coreTemperatures[i] =
    7.17            new Sensor("Core #" + (i + 1), i, SensorType.Temperature, this);
    7.18 -        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1,
    7.19 -          SensorType.Load, this);
    7.20 +        coreLoads[i] = new Sensor("Core #" + (i + 1), i + 1, null,
    7.21 +          SensorType.Load, this, new ParameterDescription[] {
    7.22 +            new ParameterDescription("Offset", 
    7.23 +              "Temperature offset of the thermal sensor.\n" + 
    7.24 +              "Temperature = Value + Offset.", offset)
    7.25 +          });
    7.26        }
    7.27  
    7.28        cpuLoad = new CPULoad(coreCount, 1);
    7.29 @@ -98,12 +108,6 @@
    7.30        pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID,
    7.31          PCI_AMD_0FH_MISCELLANEOUS_DEVICE_ID, 0);
    7.32  
    7.33 -      offset = -49.0f;
    7.34 -
    7.35 -      // AM2+ 65nm +21 offset
    7.36 -      if (model >= 0x69 && model != 0xc1 && model != 0x6c && model != 0x7c) 
    7.37 -        offset += 21;
    7.38 -
    7.39        Update();                   
    7.40      }
    7.41  
    7.42 @@ -133,7 +137,8 @@
    7.43              uint value;
    7.44              if (WinRing0.ReadPciConfigDwordEx(
    7.45                pciAddress, THERMTRIP_STATUS_REGISTER, out value)) {
    7.46 -              coreTemperatures[i].Value = ((value >> 16) & 0xFF) + offset;
    7.47 +              coreTemperatures[i].Value = ((value >> 16) & 0xFF) + 
    7.48 +                coreTemperatures[i].Parameters[0].Value;
    7.49                ActivateSensor(coreTemperatures[i]);
    7.50              } else {
    7.51                DeactivateSensor(coreTemperatures[i]);
     8.1 --- a/Hardware/CPU/AMD10CPU.cs	Tue Feb 23 19:45:40 2010 +0000
     8.2 +++ b/Hardware/CPU/AMD10CPU.cs	Sat Feb 27 15:55:17 2010 +0000
     8.3 @@ -86,8 +86,10 @@
     8.4        
     8.5        // AMD family 10h processors support only one temperature sensor
     8.6        coreTemperature = new Sensor(
     8.7 -        "Core" + (coreCount > 1 ? " #1 - #" + coreCount : ""), 0, 
     8.8 -        SensorType.Temperature, this);
     8.9 +        "Core" + (coreCount > 1 ? " #1 - #" + coreCount : ""), 0, null,
    8.10 +        SensorType.Temperature, this, new ParameterDescription[] {
    8.11 +            new ParameterDescription("Offset", "Temperature offset.", 0)
    8.12 +          });
    8.13  
    8.14        pciAddress = WinRing0.FindPciDeviceById(PCI_AMD_VENDOR_ID, 
    8.15          PCI_AMD_10H_MISCELLANEOUS_DEVICE_ID, 0);
    8.16 @@ -119,7 +121,8 @@
    8.17          uint value;
    8.18          if (WinRing0.ReadPciConfigDwordEx(pciAddress,
    8.19            REPORTED_TEMPERATURE_CONTROL_REGISTER, out value)) {
    8.20 -          coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f;
    8.21 +          coreTemperature.Value = ((value >> 21) & 0x7FF) / 8.0f +
    8.22 +            coreTemperature.Parameters[0].Value;
    8.23            ActivateSensor(coreTemperature);
    8.24          } else {
    8.25            DeactivateSensor(coreTemperature);
     9.1 --- a/Hardware/CPU/IntelCPU.cs	Tue Feb 23 19:45:40 2010 +0000
     9.2 +++ b/Hardware/CPU/IntelCPU.cs	Sat Feb 27 15:55:17 2010 +0000
     9.3 @@ -40,6 +40,8 @@
     9.4  using System.Drawing;
     9.5  using System.Diagnostics;
     9.6  using System.Reflection;
     9.7 +using System.Runtime.InteropServices;
     9.8 +using System.Threading;
     9.9  using System.Text;
    9.10  
    9.11  namespace OpenHardwareMonitor.Hardware.CPU {
    9.12 @@ -53,15 +55,15 @@
    9.13      private uint stepping;
    9.14  
    9.15      private Sensor[] coreTemperatures;
    9.16 +
    9.17      private Sensor totalLoad;
    9.18      private Sensor[] coreLoads;
    9.19      private Sensor[] coreClocks;
    9.20      private Sensor busClock;
    9.21 -
    9.22 -    private float tjMax = 0;
    9.23      private uint logicalProcessors;
    9.24      private uint logicalProcessorsPerCore;
    9.25      private uint coreCount;
    9.26 +    private ulong affinityMask;
    9.27  
    9.28      private CPULoad cpuLoad;
    9.29  
    9.30 @@ -81,6 +83,10 @@
    9.31          return "CPU Core #" + (i + 1);
    9.32      }
    9.33  
    9.34 +    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    9.35 +    private static extern bool GetProcessAffinityMask(IntPtr handle, 
    9.36 +      out IntPtr processMask, out IntPtr systemMask);
    9.37 +
    9.38      public IntelCPU(string name, uint family, uint model, uint stepping, 
    9.39        uint[,] cpuidData, uint[,] cpuidExtData) {
    9.40        
    9.41 @@ -117,8 +123,30 @@
    9.42          logicalProcessorsPerCore = 1;
    9.43        }
    9.44  
    9.45 +      IntPtr processMask, systemMask;
    9.46 +      GetProcessAffinityMask(Process.GetCurrentProcess().Handle,
    9.47 +        out processMask, out systemMask);
    9.48 +      affinityMask = (ulong)systemMask;
    9.49 +
    9.50 +      // correct values in case HypeThreading is disabled
    9.51 +      if (logicalProcessorsPerCore > 1) {
    9.52 +        ulong affinity = affinityMask;
    9.53 +        int availableLogicalProcessors = 0;
    9.54 +        while (affinity != 0) {
    9.55 +          if ((affinity & 0x1) > 0)
    9.56 +            availableLogicalProcessors++;
    9.57 +          affinity >>= 1;
    9.58 +        }
    9.59 +        while (logicalProcessorsPerCore > 1 &&
    9.60 +          availableLogicalProcessors < logicalProcessors) {
    9.61 +          logicalProcessors >>= 1;
    9.62 +          logicalProcessorsPerCore >>= 1;
    9.63 +        }
    9.64 +      }
    9.65 +
    9.66        coreCount = logicalProcessors / logicalProcessorsPerCore;
    9.67 -      
    9.68 +
    9.69 +      float tjMax;
    9.70        switch (family) {
    9.71          case 0x06: {
    9.72              switch (model) {
    9.73 @@ -170,7 +198,13 @@
    9.74          coreTemperatures = new Sensor[coreCount];
    9.75          for (int i = 0; i < coreTemperatures.Length; i++) {
    9.76            coreTemperatures[i] = new Sensor(CoreString(i), i, tjMax,
    9.77 -            SensorType.Temperature, this);
    9.78 +            SensorType.Temperature, this, new ParameterDescription[] { 
    9.79 +              new ParameterDescription(
    9.80 +                "TjMax", "TjMax temperature of the core.\n" + 
    9.81 +                "Temperature = TjMax - TSlope * Value.", tjMax), 
    9.82 +              new ParameterDescription(
    9.83 +                "TSlope", "Temperature slope of the digital thermal sensor.\n" + 
    9.84 +                "Temperature = TjMax - TSlope * Value.", 1)});
    9.85          }
    9.86        } else {
    9.87          coreTemperatures = new Sensor[0];
    9.88 @@ -237,11 +271,12 @@
    9.89        r.AppendLine("Intel CPU");
    9.90        r.AppendLine();
    9.91        r.AppendFormat("Name: {0}{1}", name, Environment.NewLine);
    9.92 -      r.AppendFormat("Number of cores: {0}{1}", coreCount, 
    9.93 +      r.AppendFormat("Number of Cores: {0}{1}", coreCount, 
    9.94          Environment.NewLine);
    9.95 -      r.AppendFormat("Threads per core: {0}{1}", logicalProcessorsPerCore,
    9.96 +      r.AppendFormat("Threads per Core: {0}{1}", logicalProcessorsPerCore,
    9.97          Environment.NewLine);
    9.98 -      r.AppendFormat("TjMax: {0}{1}", tjMax, Environment.NewLine);
    9.99 +      r.AppendFormat("Affinity Mask: 0x{0}{1}", affinityMask.ToString("X"),
   9.100 +        Environment.NewLine);  
   9.101        r.AppendLine();
   9.102  
   9.103        for (int i = 0; i < coreCount; i++) {
   9.104 @@ -269,7 +304,10 @@
   9.105            // if reading is valid
   9.106            if ((eax & 0x80000000) != 0) {
   9.107              // get the dist from tjMax from bits 22:16
   9.108 -            coreTemperatures[i].Value = tjMax - ((eax & 0x007F0000) >> 16);
   9.109 +            float deltaT = ((eax & 0x007F0000) >> 16);
   9.110 +            float tjMax = coreTemperatures[i].Parameters[0].Value;
   9.111 +            float tSlope = coreTemperatures[i].Parameters[1].Value;
   9.112 +            coreTemperatures[i].Value = tjMax - tSlope * deltaT;
   9.113              ActivateSensor(coreTemperatures[i]);
   9.114            } else {
   9.115              DeactivateSensor(coreTemperatures[i]);
    10.1 --- a/Hardware/Computer.cs	Tue Feb 23 19:45:40 2010 +0000
    10.2 +++ b/Hardware/Computer.cs	Sat Feb 27 15:55:17 2010 +0000
    10.3 @@ -152,9 +152,15 @@
    10.4                new object[] { hardware.Name, hardware.Identifier });
    10.5              foreach (ISensor sensor in hardware.Sensors) {
    10.6                w.WriteLine("|   +- {0} : {1} : {2} : {3}",
    10.7 -                new object[] { sensor.SensorType, sensor.Index, sensor.Name, 
    10.8 -                  string.Format(CultureInfo.InvariantCulture, "{0}", 
    10.9 -                  sensor.Value) });
   10.10 +                sensor.SensorType, sensor.Index, sensor.Name, 
   10.11 +                  string.Format(CultureInfo.InvariantCulture, "{0} : {1} : {2}", 
   10.12 +                  sensor.Value, sensor.Min, sensor.Max) );
   10.13 +              foreach (IParameter parameter in sensor.Parameters) {
   10.14 +                w.WriteLine("|      +- {0} : {1} : {2}",
   10.15 +                  parameter.Name, parameter.IsDefault,   
   10.16 +                  string.Format(CultureInfo.InvariantCulture, "{0} : {1}", 
   10.17 +                    parameter.DefaultValue, parameter.Value) );
   10.18 +              }
   10.19              }
   10.20            }
   10.21          }
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/Hardware/IParameter.cs	Sat Feb 27 15:55:17 2010 +0000
    11.3 @@ -0,0 +1,54 @@
    11.4 +/*
    11.5 +  
    11.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
    11.7 +
    11.8 +  The contents of this file are subject to the Mozilla Public License Version
    11.9 +  1.1 (the "License"); you may not use this file except in compliance with
   11.10 +  the License. You may obtain a copy of the License at
   11.11 + 
   11.12 +  http://www.mozilla.org/MPL/
   11.13 +
   11.14 +  Software distributed under the License is distributed on an "AS IS" basis,
   11.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   11.16 +  for the specific language governing rights and limitations under the License.
   11.17 +
   11.18 +  The Original Code is the Open Hardware Monitor code.
   11.19 +
   11.20 +  The Initial Developer of the Original Code is 
   11.21 +  Michael Möller <m.moeller@gmx.ch>.
   11.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
   11.23 +  the Initial Developer. All Rights Reserved.
   11.24 +
   11.25 +  Contributor(s):
   11.26 +
   11.27 +  Alternatively, the contents of this file may be used under the terms of
   11.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
   11.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   11.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
   11.31 +  of those above. If you wish to allow use of your version of this file only
   11.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
   11.33 +  use your version of this file under the terms of the MPL, indicate your
   11.34 +  decision by deleting the provisions above and replace them with the notice
   11.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
   11.36 +  the provisions above, a recipient may use your version of this file under
   11.37 +  the terms of any one of the MPL, the GPL or the LGPL.
   11.38 + 
   11.39 +*/
   11.40 +
   11.41 +using System;
   11.42 +using System.Collections.Generic;
   11.43 +
   11.44 +namespace OpenHardwareMonitor.Hardware {
   11.45 +
   11.46 +  public interface IParameter {
   11.47 +
   11.48 +    ISensor Sensor { get; }
   11.49 +    string Identifier { get; }
   11.50 +    
   11.51 +    string Name { get; }
   11.52 +    string Description { get; }
   11.53 +    float Value { get; set; }
   11.54 +    float DefaultValue { get; }
   11.55 +    bool IsDefault { get; set; }
   11.56 +  }
   11.57 +}
    12.1 --- a/Hardware/ISensor.cs	Tue Feb 23 19:45:40 2010 +0000
    12.2 +++ b/Hardware/ISensor.cs	Sat Feb 27 15:55:17 2010 +0000
    12.3 @@ -37,6 +37,7 @@
    12.4  
    12.5  using System;
    12.6  using System.Collections.Generic;
    12.7 +using OpenHardwareMonitor.Utilities;
    12.8  
    12.9  namespace OpenHardwareMonitor.Hardware {
   12.10  
   12.11 @@ -55,15 +56,21 @@
   12.12    }
   12.13  
   12.14    public interface ISensor {
   12.15 +
   12.16      IHardware Hardware { get; }
   12.17 +
   12.18      SensorType SensorType { get; }
   12.19      string Identifier { get; }
   12.20      string Name { get; set; }
   12.21      int Index { get; }
   12.22 +
   12.23 +    IReadOnlyArray<IParameter> Parameters { get; }
   12.24 +
   12.25      float? Value { get; }
   12.26      float? Min { get; }
   12.27      float? Max { get; }
   12.28      float? Limit { get; set; }
   12.29 +
   12.30      IEnumerable<ISensorEntry> Plot { get; }
   12.31    }
   12.32  
    13.1 --- a/Hardware/LPC/F718XX.cs	Tue Feb 23 19:45:40 2010 +0000
    13.2 +++ b/Hardware/LPC/F718XX.cs	Sat Feb 27 15:55:17 2010 +0000
    13.3 @@ -70,8 +70,10 @@
    13.4  
    13.5        temperatures = new Sensor[3];
    13.6        for (int i = 0; i < temperatures.Length; i++)
    13.7 -        temperatures[i] = new Sensor("Temperature #" + (i + 1), i,
    13.8 -          SensorType.Temperature, this);
    13.9 +        temperatures[i] = new Sensor("Temperature #" + (i + 1), i, null,
   13.10 +          SensorType.Temperature, this, new ParameterDescription[] {
   13.11 +            new ParameterDescription("Offset", "Temperature offset.", 0)
   13.12 +          });
   13.13  
   13.14        fans = new Sensor[4];
   13.15        for (int i = 0; i < fans.Length; i++)
   13.16 @@ -123,7 +125,7 @@
   13.17        foreach (Sensor sensor in temperatures) {
   13.18          sbyte value = (sbyte)ReadByte((byte)(
   13.19            TEMPERATURE_BASE_REG + 2 * sensor.Index));
   13.20 -        sensor.Value = value;
   13.21 +        sensor.Value = value + sensor.Parameters[0].Value;
   13.22          if (value < sbyte.MaxValue && value > 0)
   13.23            ActivateSensor(sensor);
   13.24          else
    14.1 --- a/Hardware/LPC/IT87XX.cs	Tue Feb 23 19:45:40 2010 +0000
    14.2 +++ b/Hardware/LPC/IT87XX.cs	Sat Feb 27 15:55:17 2010 +0000
    14.3 @@ -90,8 +90,10 @@
    14.4  
    14.5        temperatures = new Sensor[3];
    14.6        for (int i = 0; i < temperatures.Length; i++) 
    14.7 -        temperatures[i] = new Sensor("Temperature #" + (i + 1), i,
    14.8 -          SensorType.Temperature, this);
    14.9 +        temperatures[i] = new Sensor("Temperature #" + (i + 1), i, null,
   14.10 +          SensorType.Temperature, this, new ParameterDescription[] {
   14.11 +            new ParameterDescription("Offset", "Temperature offset.", 0)
   14.12 +          });
   14.13  
   14.14        fans = new Sensor[5];
   14.15        for (int i = 0; i < fans.Length; i++)
   14.16 @@ -150,8 +152,9 @@
   14.17        }
   14.18  
   14.19        foreach (Sensor sensor in temperatures) {
   14.20 -        sbyte value = (sbyte)ReadByte((byte)(TEMPERATURE_BASE_REG + sensor.Index));
   14.21 -        sensor.Value = value;
   14.22 +        sbyte value = 
   14.23 +          (sbyte)ReadByte((byte)(TEMPERATURE_BASE_REG + sensor.Index));
   14.24 +        sensor.Value = value + sensor.Parameters[0].Value;
   14.25          if (value < sbyte.MaxValue && value > 0)
   14.26            ActivateSensor(sensor);
   14.27          else
    15.1 --- a/Hardware/LPC/W836XX.cs	Tue Feb 23 19:45:40 2010 +0000
    15.2 +++ b/Hardware/LPC/W836XX.cs	Sat Feb 27 15:55:17 2010 +0000
    15.3 @@ -73,7 +73,6 @@
    15.4        new string[] {"CPU", "Auxiliary", "System"};
    15.5      private byte[] TEMPERATURE_REG = new byte[] { 0x50, 0x50, 0x27 };
    15.6      private byte[] TEMPERATURE_BANK = new byte[] { 1, 2, 0 };
    15.7 -    private byte[] TEMPERATURE_SEL = new byte[] { 1, 2, 0 };
    15.8  
    15.9      private byte[] FAN_TACHO_REG = new byte[] { 0x28, 0x29, 0x2A, 0x3F, 0x53 };
   15.10      private byte[] FAN_TACHO_BANK = new byte[] { 0, 0, 0, 0, 5 };       
   15.11 @@ -112,26 +111,42 @@
   15.12  
   15.13        available = IsWinbondVendor();
   15.14  
   15.15 +      ParameterDescription[] parameter = new ParameterDescription[] {
   15.16 +        new ParameterDescription("Offset", "Temperature offset.", 0)
   15.17 +      };
   15.18        List<Sensor> list = new List<Sensor>();
   15.19        switch (chip) {
   15.20 -        case Chip.W83627DHG:
   15.21 -          // do not add temperature sensor registers that read PECI agents
   15.22 +        case Chip.W83667HG:
   15.23 +        case Chip.W83667HGB:
   15.24 +          // do not add temperature sensor registers that read PECI
   15.25 +          byte flag = ReadByte(0, TEMPERATURE_SOURCE_SELECT_REG);
   15.26 +          if ((flag & 0x04) == 0)
   15.27 +            list.Add(new Sensor(TEMPERATURE_NAME[0], 0, null,
   15.28 +              SensorType.Temperature, this, parameter));
   15.29 +          if ((flag & 0x40) == 0)
   15.30 +            list.Add(new Sensor(TEMPERATURE_NAME[1], 1, null,
   15.31 +              SensorType.Temperature, this, parameter));
   15.32 +          list.Add(new Sensor(TEMPERATURE_NAME[2], 2, null,
   15.33 +            SensorType.Temperature, this, parameter));
   15.34 +          break;
   15.35 +        case Chip.W83627DHG:        
   15.36 +        case Chip.W83627DHGP:
   15.37 +          // do not add temperature sensor registers that read PECI
   15.38            byte sel = ReadByte(0, TEMPERATURE_SOURCE_SELECT_REG);
   15.39            if ((sel & 0x07) == 0)
   15.40 -            list.Add(new Sensor(TEMPERATURE_NAME[0], 0,
   15.41 -              SensorType.Temperature, this));
   15.42 +            list.Add(new Sensor(TEMPERATURE_NAME[0], 0, null,
   15.43 +              SensorType.Temperature, this, parameter));
   15.44            if ((sel & 0x70) == 0)
   15.45 -            list.Add(new Sensor(TEMPERATURE_NAME[1], 1,
   15.46 -              SensorType.Temperature, this));
   15.47 -          list.Add(new Sensor(TEMPERATURE_NAME[2], 2,
   15.48 -            SensorType.Temperature, this));
   15.49 +            list.Add(new Sensor(TEMPERATURE_NAME[1], 1, null,
   15.50 +              SensorType.Temperature, this, parameter));
   15.51 +          list.Add(new Sensor(TEMPERATURE_NAME[2], 2, null,
   15.52 +            SensorType.Temperature, this, parameter));
   15.53            break;
   15.54          default:
   15.55 -          // no PECI support or extra sensor report register
   15.56 -          for (int i = 0; i < TEMPERATURE_NAME.Length; i++) {
   15.57 -            list.Add(new Sensor(TEMPERATURE_NAME[i], i,
   15.58 -              SensorType.Temperature, this));
   15.59 -          }
   15.60 +          // no PECI support, add all sensors
   15.61 +          for (int i = 0; i < TEMPERATURE_NAME.Length; i++)
   15.62 +            list.Add(new Sensor(TEMPERATURE_NAME[i], i, null,
   15.63 +              SensorType.Temperature, this, parameter));
   15.64            break;
   15.65        }
   15.66        temperatures = list.ToArray();
   15.67 @@ -212,29 +227,15 @@
   15.68        }
   15.69  
   15.70        foreach (Sensor sensor in temperatures) {
   15.71 -        int value;
   15.72 -        switch (chip) {
   15.73 -          case Chip.W83667HG:
   15.74 -          case Chip.W83667HGB:
   15.75 -            WriteByte(0, 0x7D, TEMPERATURE_SEL[sensor.Index]);
   15.76 -            value = ((sbyte)ReadByte(0, 0x7E)) << 1;
   15.77 -            break;
   15.78 -          case Chip.W83627DHGP:
   15.79 -            WriteByte(0, 0x7C, TEMPERATURE_SEL[sensor.Index]);
   15.80 -            value = ((sbyte)ReadByte(0, 0x7D)) << 1;
   15.81 -            break;
   15.82 -          default:
   15.83 -            value = ((sbyte)ReadByte(TEMPERATURE_BANK[sensor.Index],
   15.84 -              TEMPERATURE_REG[sensor.Index])) << 1;
   15.85 -            if (TEMPERATURE_BANK[sensor.Index] > 0) {
   15.86 -              value |= ReadByte(TEMPERATURE_BANK[sensor.Index],
   15.87 -                (byte)(TEMPERATURE_REG[sensor.Index] + 1)) >> 7;
   15.88 -            }            
   15.89 -            break;
   15.90 -        }
   15.91 +        int value = ((sbyte)ReadByte(TEMPERATURE_BANK[sensor.Index],
   15.92 +          TEMPERATURE_REG[sensor.Index])) << 1;
   15.93 +        if (TEMPERATURE_BANK[sensor.Index] > 0) 
   15.94 +          value |= ReadByte(TEMPERATURE_BANK[sensor.Index],
   15.95 +            (byte)(TEMPERATURE_REG[sensor.Index] + 1)) >> 7;
   15.96 +
   15.97          float temperature = value / 2.0f;
   15.98          if (temperature <= 125 && temperature >= -55) {
   15.99 -          sensor.Value = temperature;
  15.100 +          sensor.Value = temperature + sensor.Parameters[0].Value;
  15.101            ActivateSensor(sensor);
  15.102          } else {
  15.103            DeactivateSensor(sensor);
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/Hardware/Parameter.cs	Sat Feb 27 15:55:17 2010 +0000
    16.3 @@ -0,0 +1,118 @@
    16.4 +/*
    16.5 +  
    16.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
    16.7 +
    16.8 +  The contents of this file are subject to the Mozilla Public License Version
    16.9 +  1.1 (the "License"); you may not use this file except in compliance with
   16.10 +  the License. You may obtain a copy of the License at
   16.11 + 
   16.12 +  http://www.mozilla.org/MPL/
   16.13 +
   16.14 +  Software distributed under the License is distributed on an "AS IS" basis,
   16.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   16.16 +  for the specific language governing rights and limitations under the License.
   16.17 +
   16.18 +  The Original Code is the Open Hardware Monitor code.
   16.19 +
   16.20 +  The Initial Developer of the Original Code is 
   16.21 +  Michael Möller <m.moeller@gmx.ch>.
   16.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
   16.23 +  the Initial Developer. All Rights Reserved.
   16.24 +
   16.25 +  Contributor(s):
   16.26 +
   16.27 +  Alternatively, the contents of this file may be used under the terms of
   16.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
   16.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   16.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
   16.31 +  of those above. If you wish to allow use of your version of this file only
   16.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
   16.33 +  use your version of this file under the terms of the MPL, indicate your
   16.34 +  decision by deleting the provisions above and replace them with the notice
   16.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
   16.36 +  the provisions above, a recipient may use your version of this file under
   16.37 +  the terms of any one of the MPL, the GPL or the LGPL.
   16.38 + 
   16.39 +*/
   16.40 +
   16.41 +using System;
   16.42 +using System.Collections.Generic;
   16.43 +
   16.44 +namespace OpenHardwareMonitor.Hardware {
   16.45 +
   16.46 +  public struct ParameterDescription {
   16.47 +    private string name;
   16.48 +    private string description;
   16.49 +    private float defaultValue;    
   16.50 +
   16.51 +    public ParameterDescription(string name, string description, 
   16.52 +      float defaultValue) {
   16.53 +      this.name = name;
   16.54 +      this.description = description;
   16.55 +      this.defaultValue = defaultValue;
   16.56 +    }
   16.57 +
   16.58 +    public string Name { get { return name; } }
   16.59 +
   16.60 +    public string Description { get { return description; } }
   16.61 +
   16.62 +    public float DefaultValue { get { return defaultValue; } }
   16.63 +  }
   16.64 +
   16.65 +  public class Parameter : IParameter {
   16.66 +    private ISensor sensor;
   16.67 +    private ParameterDescription description;
   16.68 +    private float value;
   16.69 +    private bool isDefault;
   16.70 +
   16.71 +    public Parameter(ParameterDescription description, ISensor sensor) {
   16.72 +      this.sensor = sensor;
   16.73 +      this.description = description;
   16.74 +      this.value = Utilities.Config.Get(Identifier, description.DefaultValue);
   16.75 +      this.isDefault = !Utilities.Config.Contains(Identifier);
   16.76 +    }
   16.77 +
   16.78 +    public ISensor Sensor {
   16.79 +      get {
   16.80 +        return sensor;
   16.81 +      }
   16.82 +    }
   16.83 +
   16.84 +    public string Identifier {
   16.85 +      get {
   16.86 +        return sensor.Identifier + "/parameter/" + 
   16.87 +          Name.Replace(" ", "").ToLower();
   16.88 +      }
   16.89 +    }
   16.90 +
   16.91 +    public string Name { get { return description.Name; } }
   16.92 +
   16.93 +    public string Description { get { return description.Description; } }
   16.94 +
   16.95 +    public float Value {
   16.96 +      get {
   16.97 +        return value;
   16.98 +      }
   16.99 +      set {
  16.100 +        this.isDefault = false;
  16.101 +        this.value = value;        
  16.102 +        Utilities.Config.Set(Identifier, value);
  16.103 +      }
  16.104 +    }
  16.105 +
  16.106 +    public float DefaultValue { 
  16.107 +      get { return description.DefaultValue; } 
  16.108 +    }
  16.109 +
  16.110 +    public bool IsDefault {
  16.111 +      get { return isDefault; }
  16.112 +      set {
  16.113 +        this.isDefault = value;
  16.114 +        if (value) {
  16.115 +          this.value = description.DefaultValue;
  16.116 +          Utilities.Config.Remove(Identifier);
  16.117 +        }
  16.118 +      }
  16.119 +    }   
  16.120 +  }
  16.121 +}
    17.1 --- a/Hardware/Sensor.cs	Tue Feb 23 19:45:40 2010 +0000
    17.2 +++ b/Hardware/Sensor.cs	Sat Feb 27 15:55:17 2010 +0000
    17.3 @@ -37,6 +37,7 @@
    17.4  
    17.5  using System;
    17.6  using System.Collections.Generic;
    17.7 +using OpenHardwareMonitor.Utilities;
    17.8  
    17.9  namespace OpenHardwareMonitor.Hardware {
   17.10  
   17.11 @@ -47,6 +48,7 @@
   17.12      private int index;
   17.13      private SensorType sensorType;
   17.14      private IHardware hardware;
   17.15 +    private ReadOnlyArray<IParameter> parameters;
   17.16      private float? value;
   17.17      private float? min;
   17.18      private float? max;
   17.19 @@ -61,25 +63,32 @@
   17.20      private const int MAX_MINUTES = 120;
   17.21     
   17.22      public Sensor(string name, int index, SensorType sensorType,
   17.23 -      IHardware hardware)
   17.24 -      : this(name, index, null, sensorType, hardware) { }
   17.25 +      IHardware hardware) : this(name, index, null, sensorType, hardware, 
   17.26 +      new ParameterDescription[0]) { }
   17.27  
   17.28 -    public Sensor(string name, int index, float? limit, 
   17.29 -      SensorType sensorType, IHardware hardware) 
   17.30 +    public Sensor(string name, int index, float? limit,
   17.31 +      SensorType sensorType, IHardware hardware) : this(name, index, limit, 
   17.32 +      sensorType, hardware, new ParameterDescription[0]) { }    
   17.33 +
   17.34 +    public Sensor(string name, int index, float? limit, SensorType sensorType, 
   17.35 +      IHardware hardware, ParameterDescription[] parameterDescriptions) 
   17.36      {
   17.37        this.defaultName = name;      
   17.38        this.index = index;
   17.39        this.defaultLimit = limit;
   17.40        this.sensorType = sensorType;
   17.41        this.hardware = hardware;
   17.42 -      string configName =
   17.43 -        Utilities.Config.Settings[Identifier + "/name"];
   17.44 +      Parameter[] parameters = new Parameter[parameterDescriptions.Length];
   17.45 +      for (int i = 0; i < parameters.Length; i++ ) 
   17.46 +        parameters[i] = new Parameter(parameterDescriptions[i], this);
   17.47 +      this.parameters = parameters;
   17.48 +
   17.49 +      string configName = Config.Settings[Identifier + "/name"];
   17.50        if (configName != null)
   17.51          this.name = configName;
   17.52        else
   17.53          this.name = name;
   17.54 -      string configLimit =
   17.55 -        Utilities.Config.Settings[Identifier + "/limit"];
   17.56 +      string configLimit = Config.Settings[Identifier + "/limit"];
   17.57        if (configLimit != null && configLimit != "")
   17.58          this.limit = float.Parse(configLimit);
   17.59        else
   17.60 @@ -110,7 +119,7 @@
   17.61            name = value;          
   17.62          else 
   17.63            name = defaultName;
   17.64 -        Utilities.Config.Settings[Identifier + "/name"] = name;
   17.65 +        Config.Settings[Identifier + "/name"] = name;
   17.66        }
   17.67      }
   17.68  
   17.69 @@ -118,6 +127,10 @@
   17.70        get { return index; }
   17.71      }
   17.72  
   17.73 +    public IReadOnlyArray<IParameter> Parameters {
   17.74 +      get { return parameters; }
   17.75 +    }
   17.76 +
   17.77      public float? Value {
   17.78        get { 
   17.79          return value; 
   17.80 @@ -156,11 +169,11 @@
   17.81        set {
   17.82          if (value.HasValue) {
   17.83            limit = value;
   17.84 -          Utilities.Config.Settings[Identifier + "/limit"] =
   17.85 +          Config.Settings[Identifier + "/limit"] =
   17.86              limit.ToString();
   17.87          } else {
   17.88            limit = defaultLimit;
   17.89 -          Utilities.Config.Settings[Identifier + "/limit"] = "";          
   17.90 +          Config.Settings[Identifier + "/limit"] = "";          
   17.91          }        
   17.92        }
   17.93      }
    18.1 --- a/Hardware/TBalancer/TBalancer.cs	Tue Feb 23 19:45:40 2010 +0000
    18.2 +++ b/Hardware/TBalancer/TBalancer.cs	Sat Feb 27 15:55:17 2010 +0000
    18.3 @@ -73,30 +73,37 @@
    18.4        this.icon = Utilities.EmbeddedResources.GetImage("bigng.png");
    18.5        this.protocolVersion = protocolVersion;
    18.6  
    18.7 +      ParameterDescription[] parameter = new ParameterDescription[] {
    18.8 +        new ParameterDescription("Offset", "Temperature offset.", 0)
    18.9 +      };
   18.10        int offset = 0;
   18.11        for (int i = 0; i < digitalTemperatures.Length; i++)
   18.12          digitalTemperatures[i] = new Sensor("Digital Sensor #" + (i + 1),
   18.13 -          offset + i, SensorType.Temperature, this);
   18.14 +          offset + i, null, SensorType.Temperature, this, parameter);
   18.15        offset += digitalTemperatures.Length;
   18.16  
   18.17        for (int i = 0; i < analogTemperatures.Length; i++)
   18.18          analogTemperatures[i] = new Sensor("Analog Sensor #" + (i + 1),
   18.19 -          offset + i, SensorType.Temperature, this);
   18.20 +          offset + i, null, SensorType.Temperature, this, parameter);
   18.21        offset += analogTemperatures.Length;
   18.22  
   18.23        for (int i = 0; i < sensorhubTemperatures.Length; i++)
   18.24          sensorhubTemperatures[i] = new Sensor("Sensorhub Sensor #" + (i + 1),
   18.25 -          offset + i, SensorType.Temperature, this);
   18.26 +          offset + i, null, SensorType.Temperature, this, parameter);
   18.27        offset += sensorhubTemperatures.Length;
   18.28  
   18.29        for (int i = 0; i < sensorhubFlows.Length; i++)
   18.30          sensorhubFlows[i] = new Sensor("Flowmeter #" + (i + 1),
   18.31 -          offset + i, SensorType.Flow, this);
   18.32 +          offset + i, null, SensorType.Flow, this, new ParameterDescription[] {
   18.33 +            new ParameterDescription("Impulse Rate", 
   18.34 +              "The impulse rate of the flowmeter in pulses/L", 509)
   18.35 +          });
   18.36        offset += sensorhubFlows.Length;
   18.37  
   18.38        for (int i = 0; i < miniNGTemperatures.Length; i++)
   18.39 -        miniNGTemperatures[i] = new Sensor("miniNG #" + (i / 2 + 1) + 
   18.40 -          " Sensor #" + (i % 2 + 1), offset + i, SensorType.Temperature, this);
   18.41 +        miniNGTemperatures[i] = new Sensor("miniNG #" + (i / 2 + 1) +
   18.42 +          " Sensor #" + (i % 2 + 1), offset + i, null, SensorType.Temperature, 
   18.43 +          this, parameter);
   18.44        offset += miniNGTemperatures.Length;
   18.45  
   18.46        alternativeRequest = new MethodDelegate(DelayedAlternativeRequest);
   18.47 @@ -138,7 +145,8 @@
   18.48        for (int i = 0; i < 2; i++) {
   18.49          Sensor sensor = miniNGTemperatures[number * 2 + i];
   18.50          if (data[offset + 7 + i] > 0) {
   18.51 -          sensor.Value = 0.5f * data[offset + 7 + i];
   18.52 +          sensor.Value = 0.5f * data[offset + 7 + i] + 
   18.53 +            sensor.Parameters[0].Value;
   18.54            ActivateSensor(sensor);
   18.55          } else {
   18.56            DeactivateSensor(sensor);
   18.57 @@ -179,7 +187,8 @@
   18.58  
   18.59          for (int i = 0; i < digitalTemperatures.Length; i++)
   18.60            if (data[238 + i] > 0) {
   18.61 -            digitalTemperatures[i].Value = 0.5f * data[238 + i];
   18.62 +            digitalTemperatures[i].Value = 0.5f * data[238 + i] + 
   18.63 +              digitalTemperatures[i].Parameters[0].Value;
   18.64              ActivateSensor(digitalTemperatures[i]);
   18.65            } else {
   18.66              DeactivateSensor(digitalTemperatures[i]);
   18.67 @@ -187,7 +196,8 @@
   18.68  
   18.69          for (int i = 0; i < analogTemperatures.Length; i++)
   18.70            if (data[260 + i] > 0) {
   18.71 -            analogTemperatures[i].Value = 0.5f * data[260 + i];
   18.72 +            analogTemperatures[i].Value = 0.5f * data[260 + i] +
   18.73 +              analogTemperatures[i].Parameters[0].Value;
   18.74              ActivateSensor(analogTemperatures[i]);
   18.75            } else {
   18.76              DeactivateSensor(analogTemperatures[i]);
   18.77 @@ -195,7 +205,8 @@
   18.78  
   18.79          for (int i = 0; i < sensorhubTemperatures.Length; i++)
   18.80            if (data[246 + i] > 0) {
   18.81 -            sensorhubTemperatures[i].Value = 0.5f * data[246 + i];
   18.82 +            sensorhubTemperatures[i].Value = 0.5f * data[246 + i] +
   18.83 +              sensorhubTemperatures[i].Parameters[0].Value;
   18.84              ActivateSensor(sensorhubTemperatures[i]);
   18.85            } else {
   18.86              DeactivateSensor(sensorhubTemperatures[i]);
   18.87 @@ -204,7 +215,7 @@
   18.88          for (int i = 0; i < sensorhubFlows.Length; i++)
   18.89            if (data[231 + i] > 0 && data[234] > 0) {
   18.90              float pulsesPerSecond = ((float)data[231 + i]) / data[234];
   18.91 -            const float pulsesPerLiter = 509;
   18.92 +            float pulsesPerLiter = sensorhubFlows[i].Parameters[0].Value;
   18.93              sensorhubFlows[i].Value = pulsesPerSecond * 3600 / pulsesPerLiter;
   18.94              ActivateSensor(sensorhubFlows[i]);
   18.95            } else {
   18.96 @@ -216,12 +227,15 @@
   18.97  
   18.98            if (fans[i] == null)
   18.99              fans[i] = new Sensor("Fan #" + (i + 1), i, maxRPM, SensorType.Fan,
  18.100 -              this);
  18.101 +              this, new ParameterDescription[] {
  18.102 +                new ParameterDescription("MaxRPM", 
  18.103 +                  "Maximum revolutions per minute (RPM) of the fan.", maxRPM)
  18.104 +              });
  18.105  
  18.106 -          if ((data[136] & (1 << i)) == 0)
  18.107 -            fans[i].Value = maxRPM * 0.01f * data[156 + i]; // pwm mode
  18.108 -          else
  18.109 -            fans[i].Value = maxRPM * 0.01f * data[141 + i]; // analog mode
  18.110 +          if ((data[136] & (1 << i)) == 0) // pwm mode
  18.111 +            fans[i].Value = fans[i].Parameters[0].Value * 0.01f * data[156 + i];
  18.112 +          else // analog mode
  18.113 +            fans[i].Value = fans[i].Parameters[0].Value * 0.01f * data[141 + i]; 
  18.114            ActivateSensor(fans[i]);
  18.115          }
  18.116  
    19.1 --- a/OpenHardwareMonitor.csproj	Tue Feb 23 19:45:40 2010 +0000
    19.2 +++ b/OpenHardwareMonitor.csproj	Sat Feb 27 15:55:17 2010 +0000
    19.3 @@ -4,7 +4,7 @@
    19.4      <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    19.5      <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    19.6      <ProjectGuid>{F5E0C1F7-9E9B-46F2-AC88-8C9C1C923880}</ProjectGuid>
    19.7 -    <ProductVersion>9.0.21022</ProductVersion>
    19.8 +    <ProductVersion>9.0.30729</ProductVersion>
    19.9      <SchemaVersion>2.0</SchemaVersion>
   19.10      <OutputType>WinExe</OutputType>
   19.11      <NoStandardLibraries>false</NoStandardLibraries>
   19.12 @@ -58,6 +58,12 @@
   19.13      <Reference Include="System.Xml" />
   19.14    </ItemGroup>
   19.15    <ItemGroup>
   19.16 +    <Compile Include="GUI\ParameterForm.cs">
   19.17 +      <SubType>Form</SubType>
   19.18 +    </Compile>
   19.19 +    <Compile Include="GUI\ParameterForm.Designer.cs">
   19.20 +      <DependentUpon>ParameterForm.cs</DependentUpon>
   19.21 +    </Compile>
   19.22      <Compile Include="GUI\SensorNotifyIcon.cs" />
   19.23      <Compile Include="GUI\SensorSystemTray.cs" />
   19.24      <Compile Include="GUI\TypeNode.cs" />
   19.25 @@ -68,9 +74,11 @@
   19.26      <Compile Include="Hardware\HDD\HDD.cs" />
   19.27      <Compile Include="Hardware\HDD\HDDGroup.cs" />
   19.28      <Compile Include="Hardware\HDD\SMART.cs" />
   19.29 +    <Compile Include="Hardware\IParameter.cs" />
   19.30      <Compile Include="Hardware\LPC\Chip.cs" />
   19.31      <Compile Include="Hardware\LPC\F718XX.cs" />
   19.32      <Compile Include="Hardware\LPC\LPCHardware.cs" />
   19.33 +    <Compile Include="Hardware\Parameter.cs" />
   19.34      <Compile Include="Hardware\SMBIOS\SMBIOSGroup.cs" />
   19.35      <Compile Include="Hardware\LPC\W836XX.cs" />
   19.36      <Compile Include="Hardware\Computer.cs" />
   19.37 @@ -84,7 +92,7 @@
   19.38      <Compile Include="Hardware\ATI\ADL.cs" />
   19.39      <Compile Include="Hardware\ATI\ATIGroup.cs" />
   19.40      <Compile Include="Hardware\ATI\ATIGPU.cs" />
   19.41 -    <Compile Include="Utilities\Configuration.cs" />
   19.42 +    <Compile Include="Utilities\Config.cs" />
   19.43      <Compile Include="Utilities\CrashReport.cs" />
   19.44      <Compile Include="Utilities\EmbeddedResources.cs" />
   19.45      <Compile Include="GUI\HardwareNode.cs" />
   19.46 @@ -104,6 +112,7 @@
   19.47      <Compile Include="Hardware\Nvidia\NvidiaGroup.cs" />
   19.48      <Compile Include="Utilities\HexStringArray.cs" />
   19.49      <Compile Include="Utilities\IconFactory.cs" />
   19.50 +    <Compile Include="Utilities\IReadOnlyArray.cs" />
   19.51      <Compile Include="Utilities\PInvokeDelegateFactory.cs" />
   19.52      <Compile Include="GUI\PlotPanel.cs">
   19.53        <SubType>UserControl</SubType>
   19.54 @@ -119,6 +128,7 @@
   19.55      <Compile Include="Hardware\TBalancer\TBalancer.cs" />
   19.56      <Compile Include="Hardware\TBalancer\TBalancerGroup.cs" />
   19.57      <Compile Include="Hardware\WinRing0.cs" />
   19.58 +    <Compile Include="Utilities\ReadOnlyArray.cs" />
   19.59    </ItemGroup>
   19.60    <ItemGroup>
   19.61      <EmbeddedResource Include="GUI\AboutBox.resx">
   19.62 @@ -157,6 +167,9 @@
   19.63      <EmbeddedResource Include="Resources\smallicon.ico" />
   19.64    </ItemGroup>
   19.65    <ItemGroup>
   19.66 +    <EmbeddedResource Include="GUI\ParameterForm.resx">
   19.67 +      <DependentUpon>ParameterForm.cs</DependentUpon>
   19.68 +    </EmbeddedResource>
   19.69      <EmbeddedResource Include="Resources\flow.png" />
   19.70    </ItemGroup>
   19.71    <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
    20.1 --- a/Properties/AssemblyInfo.cs	Tue Feb 23 19:45:40 2010 +0000
    20.2 +++ b/Properties/AssemblyInfo.cs	Sat Feb 27 15:55:17 2010 +0000
    20.3 @@ -69,5 +69,5 @@
    20.4  // You can specify all the values or you can default the Build and Revision Numbers 
    20.5  // by using the '*' as shown below:
    20.6  // [assembly: AssemblyVersion("1.0.*")]
    20.7 -[assembly: AssemblyVersion("0.1.23.2")]
    20.8 -[assembly: AssemblyFileVersion("0.1.23.2")]
    20.9 +[assembly: AssemblyVersion("0.1.24.0")]
   20.10 +[assembly: AssemblyFileVersion("0.1.24.0")]
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/Utilities/Config.cs	Sat Feb 27 15:55:17 2010 +0000
    21.3 @@ -0,0 +1,179 @@
    21.4 +/*
    21.5 +  
    21.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
    21.7 +
    21.8 +  The contents of this file are subject to the Mozilla Public License Version
    21.9 +  1.1 (the "License"); you may not use this file except in compliance with
   21.10 +  the License. You may obtain a copy of the License at
   21.11 + 
   21.12 +  http://www.mozilla.org/MPL/
   21.13 +
   21.14 +  Software distributed under the License is distributed on an "AS IS" basis,
   21.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   21.16 +  for the specific language governing rights and limitations under the License.
   21.17 +
   21.18 +  The Original Code is the Open Hardware Monitor code.
   21.19 +
   21.20 +  The Initial Developer of the Original Code is 
   21.21 +  Michael Möller <m.moeller@gmx.ch>.
   21.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
   21.23 +  the Initial Developer. All Rights Reserved.
   21.24 +
   21.25 +  Contributor(s):
   21.26 +
   21.27 +  Alternatively, the contents of this file may be used under the terms of
   21.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
   21.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   21.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
   21.31 +  of those above. If you wish to allow use of your version of this file only
   21.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
   21.33 +  use your version of this file under the terms of the MPL, indicate your
   21.34 +  decision by deleting the provisions above and replace them with the notice
   21.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
   21.36 +  the provisions above, a recipient may use your version of this file under
   21.37 +  the terms of any one of the MPL, the GPL or the LGPL.
   21.38 + 
   21.39 +*/
   21.40 +
   21.41 +using System;
   21.42 +using System.Collections.Generic;
   21.43 +using System.Drawing;
   21.44 +using System.IO;
   21.45 +
   21.46 +namespace OpenHardwareMonitor.Utilities {
   21.47 +
   21.48 +  public sealed class Config {
   21.49 +    private static readonly Config instance = new Config();
   21.50 +
   21.51 +    private string fileName;
   21.52 +
   21.53 +    private System.Configuration.Configuration config;
   21.54 +
   21.55 +    private Config() {
   21.56 +      this.fileName = Path.ChangeExtension(
   21.57 +        System.Windows.Forms.Application.ExecutablePath, ".config");
   21.58 +      System.Configuration.ExeConfigurationFileMap fileMap = 
   21.59 +        new System.Configuration.ExeConfigurationFileMap();
   21.60 +      fileMap.ExeConfigFilename = fileName;        
   21.61 +      config = System.Configuration.ConfigurationManager.
   21.62 +        OpenMappedExeConfiguration(fileMap, 
   21.63 +        System.Configuration.ConfigurationUserLevel.None);
   21.64 +    }
   21.65 +
   21.66 +    ~Config() {
   21.67 +      string tempName = Path.ChangeExtension(fileName, ".tmp");
   21.68 +
   21.69 +      if (File.Exists(tempName))
   21.70 +        File.Delete(tempName);
   21.71 +      try {
   21.72 +        config.SaveAs(tempName);
   21.73 +        if (File.Exists(fileName) && File.Exists(tempName))
   21.74 +          File.Delete(fileName);
   21.75 +        File.Move(tempName, fileName);
   21.76 +      } catch (System.Configuration.ConfigurationErrorsException) { }
   21.77 +    }
   21.78 +
   21.79 +    public static Config Settings {
   21.80 +      get {
   21.81 +        return instance;
   21.82 +      }
   21.83 +    }
   21.84 +
   21.85 +    public string this[string name] {
   21.86 +      get {
   21.87 +        System.Configuration.KeyValueConfigurationElement element =
   21.88 +          config.AppSettings.Settings[name];
   21.89 +        if (element != null)
   21.90 +          return element.Value;
   21.91 +        else
   21.92 +          return null;
   21.93 +      }
   21.94 +      set {
   21.95 +        config.AppSettings.Settings.Remove(name);
   21.96 +        config.AppSettings.Settings.Add(name, value);
   21.97 +      }
   21.98 +    }
   21.99 +
  21.100 +    public static bool Contains(string name) {
  21.101 +      System.Configuration.KeyValueConfigurationElement element =
  21.102 +        instance.config.AppSettings.Settings[name];
  21.103 +      return element != null;
  21.104 +    }
  21.105 +
  21.106 +    public static void Remove(string name) {
  21.107 +      instance.config.AppSettings.Settings.Remove(name);
  21.108 +    }
  21.109 +
  21.110 +    public static void Set(string name, bool value) {
  21.111 +      instance[name] = value ? "true" : "false";
  21.112 +    }
  21.113 +
  21.114 +    public static bool Get(string name, bool value) {
  21.115 +      System.Configuration.KeyValueConfigurationElement element =
  21.116 +        instance.config.AppSettings.Settings[name];
  21.117 +      if (element == null)
  21.118 +        return value;
  21.119 +      else
  21.120 +        return element.Value == "true"; 
  21.121 +    }
  21.122 +
  21.123 +    public static void Set(string name, int value) {
  21.124 +      instance[name] = value.ToString();
  21.125 +    }
  21.126 +
  21.127 +    public static int Get(string name, int value) {
  21.128 +      System.Configuration.KeyValueConfigurationElement element =
  21.129 +        instance.config.AppSettings.Settings[name];
  21.130 +      if (element == null)
  21.131 +        return value;
  21.132 +      else {
  21.133 +        int parsedValue;
  21.134 +        if (int.TryParse(element.Value, out parsedValue))
  21.135 +          return parsedValue;
  21.136 +        else
  21.137 +          return value;
  21.138 +      }
  21.139 +    }
  21.140 +
  21.141 +    public static void Set(string name, Color color) {
  21.142 +      instance[name] = color.ToArgb().ToString("X8");
  21.143 +    }
  21.144 +
  21.145 +    public static Color Get(string name, Color value) {
  21.146 +      System.Configuration.KeyValueConfigurationElement element =
  21.147 +        instance.config.AppSettings.Settings[name];
  21.148 +      if (element == null)
  21.149 +        return value;
  21.150 +      else {
  21.151 +        int parsedValue;
  21.152 +        if (int.TryParse(element.Value, 
  21.153 +          System.Globalization.NumberStyles.HexNumber, 
  21.154 +          System.Globalization.CultureInfo.InvariantCulture, out parsedValue))
  21.155 +          return Color.FromArgb(parsedValue);
  21.156 +        else
  21.157 +          return value;
  21.158 +      }
  21.159 +    }
  21.160 +
  21.161 +    public static void Set(string name, float value) {
  21.162 +      instance[name] = value.ToString(
  21.163 +        System.Globalization.CultureInfo.InvariantCulture.NumberFormat); 
  21.164 +    }
  21.165 +
  21.166 +    public static float Get(string name, float value) {
  21.167 +      System.Configuration.KeyValueConfigurationElement element =
  21.168 +        instance.config.AppSettings.Settings[name];
  21.169 +      if (element == null)
  21.170 +        return value;
  21.171 +      else {
  21.172 +        float parsedValue;
  21.173 +        if (float.TryParse(element.Value,
  21.174 +          System.Globalization.NumberStyles.Float,
  21.175 +          System.Globalization.CultureInfo.InvariantCulture, out parsedValue))
  21.176 +          return parsedValue;
  21.177 +        else
  21.178 +          return value;
  21.179 +      }
  21.180 +    }
  21.181 +  }
  21.182 +}
    22.1 --- a/Utilities/Configuration.cs	Tue Feb 23 19:45:40 2010 +0000
    22.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
    22.3 @@ -1,158 +0,0 @@
    22.4 -/*
    22.5 -  
    22.6 -  Version: MPL 1.1/GPL 2.0/LGPL 2.1
    22.7 -
    22.8 -  The contents of this file are subject to the Mozilla Public License Version
    22.9 -  1.1 (the "License"); you may not use this file except in compliance with
   22.10 -  the License. You may obtain a copy of the License at
   22.11 - 
   22.12 -  http://www.mozilla.org/MPL/
   22.13 -
   22.14 -  Software distributed under the License is distributed on an "AS IS" basis,
   22.15 -  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   22.16 -  for the specific language governing rights and limitations under the License.
   22.17 -
   22.18 -  The Original Code is the Open Hardware Monitor code.
   22.19 -
   22.20 -  The Initial Developer of the Original Code is 
   22.21 -  Michael Möller <m.moeller@gmx.ch>.
   22.22 -  Portions created by the Initial Developer are Copyright (C) 2009-2010
   22.23 -  the Initial Developer. All Rights Reserved.
   22.24 -
   22.25 -  Contributor(s):
   22.26 -
   22.27 -  Alternatively, the contents of this file may be used under the terms of
   22.28 -  either the GNU General Public License Version 2 or later (the "GPL"), or
   22.29 -  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   22.30 -  in which case the provisions of the GPL or the LGPL are applicable instead
   22.31 -  of those above. If you wish to allow use of your version of this file only
   22.32 -  under the terms of either the GPL or the LGPL, and not to allow others to
   22.33 -  use your version of this file under the terms of the MPL, indicate your
   22.34 -  decision by deleting the provisions above and replace them with the notice
   22.35 -  and other provisions required by the GPL or the LGPL. If you do not delete
   22.36 -  the provisions above, a recipient may use your version of this file under
   22.37 -  the terms of any one of the MPL, the GPL or the LGPL.
   22.38 - 
   22.39 -*/
   22.40 -
   22.41 -using System;
   22.42 -using System.Collections.Generic;
   22.43 -using System.Drawing;
   22.44 -using System.IO;
   22.45 -
   22.46 -namespace OpenHardwareMonitor.Utilities {
   22.47 -
   22.48 -  public sealed class Config {
   22.49 -    private static readonly Config instance = new Config();
   22.50 -
   22.51 -    private string fileName;
   22.52 -
   22.53 -    private System.Configuration.Configuration config;
   22.54 -
   22.55 -    private Config() {
   22.56 -      this.fileName = Path.ChangeExtension(
   22.57 -        System.Windows.Forms.Application.ExecutablePath, ".config");
   22.58 -      System.Configuration.ExeConfigurationFileMap fileMap = 
   22.59 -        new System.Configuration.ExeConfigurationFileMap();
   22.60 -      fileMap.ExeConfigFilename = fileName;        
   22.61 -      config = System.Configuration.ConfigurationManager.
   22.62 -        OpenMappedExeConfiguration(fileMap, 
   22.63 -        System.Configuration.ConfigurationUserLevel.None);
   22.64 -    }
   22.65 -
   22.66 -    ~Config() {
   22.67 -      string tempName = Path.ChangeExtension(fileName, ".tmp");
   22.68 -
   22.69 -      if (File.Exists(tempName))
   22.70 -        File.Delete(tempName);
   22.71 -      try {
   22.72 -        config.SaveAs(tempName);
   22.73 -        if (File.Exists(fileName) && File.Exists(tempName))
   22.74 -          File.Delete(fileName);
   22.75 -        File.Move(tempName, fileName);
   22.76 -      } catch (System.Configuration.ConfigurationErrorsException) { }
   22.77 -    }
   22.78 -
   22.79 -    public static Config Settings {
   22.80 -      get {
   22.81 -        return instance;
   22.82 -      }
   22.83 -    }
   22.84 -
   22.85 -    public string this[string name] {
   22.86 -      get {
   22.87 -        System.Configuration.KeyValueConfigurationElement element =
   22.88 -          config.AppSettings.Settings[name];
   22.89 -        if (element != null)
   22.90 -          return element.Value;
   22.91 -        else
   22.92 -          return null;
   22.93 -      }
   22.94 -      set {
   22.95 -        config.AppSettings.Settings.Remove(name);
   22.96 -        config.AppSettings.Settings.Add(name, value);
   22.97 -      }
   22.98 -    }
   22.99 -
  22.100 -    public static bool Contains(string name) {
  22.101 -      System.Configuration.KeyValueConfigurationElement element =
  22.102 -        instance.config.AppSettings.Settings[name];
  22.103 -      return element != null;
  22.104 -    }
  22.105 -
  22.106 -    public static void Remove(string name) {
  22.107 -      instance.config.AppSettings.Settings.Remove(name);
  22.108 -    }
  22.109 -
  22.110 -    public static void Set(string name, bool value) {
  22.111 -      instance[name] = value ? "true" : "false";
  22.112 -    }
  22.113 -
  22.114 -    public static bool Get(string name, bool value) {
  22.115 -      System.Configuration.KeyValueConfigurationElement element =
  22.116 -        instance.config.AppSettings.Settings[name];
  22.117 -      if (element == null)
  22.118 -        return value;
  22.119 -      else
  22.120 -        return element.Value == "true"; 
  22.121 -    }
  22.122 -
  22.123 -    public static void Set(string name, int value) {
  22.124 -      instance[name] = value.ToString();
  22.125 -    }
  22.126 -
  22.127 -    public static int Get(string name, int value) {
  22.128 -      System.Configuration.KeyValueConfigurationElement element =
  22.129 -        instance.config.AppSettings.Settings[name];
  22.130 -      if (element == null)
  22.131 -        return value;
  22.132 -      else {
  22.133 -        int parsedValue;
  22.134 -        if (int.TryParse(element.Value, out parsedValue))
  22.135 -          return parsedValue;
  22.136 -        else
  22.137 -          return value;
  22.138 -      }
  22.139 -    }
  22.140 -
  22.141 -    public static void Set(string name, Color color) {
  22.142 -      instance[name] = color.ToArgb().ToString("X8");
  22.143 -    }
  22.144 -
  22.145 -    public static Color Get(string name, Color value) {
  22.146 -      System.Configuration.KeyValueConfigurationElement element =
  22.147 -        instance.config.AppSettings.Settings[name];
  22.148 -      if (element == null)
  22.149 -        return value;
  22.150 -      else {
  22.151 -        int parsedValue;
  22.152 -        if (int.TryParse(element.Value, 
  22.153 -          System.Globalization.NumberStyles.HexNumber, 
  22.154 -          System.Globalization.CultureInfo.InvariantCulture, out parsedValue))
  22.155 -          return Color.FromArgb(parsedValue);
  22.156 -        else
  22.157 -          return value;
  22.158 -      }
  22.159 -    }
  22.160 -  }
  22.161 -}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/Utilities/IReadOnlyArray.cs	Sat Feb 27 15:55:17 2010 +0000
    23.3 @@ -0,0 +1,50 @@
    23.4 +/*
    23.5 +  
    23.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
    23.7 +
    23.8 +  The contents of this file are subject to the Mozilla Public License Version
    23.9 +  1.1 (the "License"); you may not use this file except in compliance with
   23.10 +  the License. You may obtain a copy of the License at
   23.11 + 
   23.12 +  http://www.mozilla.org/MPL/
   23.13 +
   23.14 +  Software distributed under the License is distributed on an "AS IS" basis,
   23.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   23.16 +  for the specific language governing rights and limitations under the License.
   23.17 +
   23.18 +  The Original Code is the Open Hardware Monitor code.
   23.19 +
   23.20 +  The Initial Developer of the Original Code is 
   23.21 +  Michael Möller <m.moeller@gmx.ch>.
   23.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
   23.23 +  the Initial Developer. All Rights Reserved.
   23.24 +
   23.25 +  Contributor(s):
   23.26 +
   23.27 +  Alternatively, the contents of this file may be used under the terms of
   23.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
   23.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   23.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
   23.31 +  of those above. If you wish to allow use of your version of this file only
   23.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
   23.33 +  use your version of this file under the terms of the MPL, indicate your
   23.34 +  decision by deleting the provisions above and replace them with the notice
   23.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
   23.36 +  the provisions above, a recipient may use your version of this file under
   23.37 +  the terms of any one of the MPL, the GPL or the LGPL.
   23.38 + 
   23.39 +*/
   23.40 +
   23.41 +using System;
   23.42 +using System.Collections.Generic;
   23.43 +
   23.44 +namespace OpenHardwareMonitor.Utilities {
   23.45 +
   23.46 +  public interface IReadOnlyArray<T> : IEnumerable<T> {
   23.47 +
   23.48 +    T this[int index] { get; }
   23.49 +
   23.50 +    int Length { get; }
   23.51 +    
   23.52 +  }
   23.53 +}
    24.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    24.2 +++ b/Utilities/ReadOnlyArray.cs	Sat Feb 27 15:55:17 2010 +0000
    24.3 @@ -0,0 +1,70 @@
    24.4 +/*
    24.5 +  
    24.6 +  Version: MPL 1.1/GPL 2.0/LGPL 2.1
    24.7 +
    24.8 +  The contents of this file are subject to the Mozilla Public License Version
    24.9 +  1.1 (the "License"); you may not use this file except in compliance with
   24.10 +  the License. You may obtain a copy of the License at
   24.11 + 
   24.12 +  http://www.mozilla.org/MPL/
   24.13 +
   24.14 +  Software distributed under the License is distributed on an "AS IS" basis,
   24.15 +  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
   24.16 +  for the specific language governing rights and limitations under the License.
   24.17 +
   24.18 +  The Original Code is the Open Hardware Monitor code.
   24.19 +
   24.20 +  The Initial Developer of the Original Code is 
   24.21 +  Michael Möller <m.moeller@gmx.ch>.
   24.22 +  Portions created by the Initial Developer are Copyright (C) 2009-2010
   24.23 +  the Initial Developer. All Rights Reserved.
   24.24 +
   24.25 +  Contributor(s):
   24.26 +
   24.27 +  Alternatively, the contents of this file may be used under the terms of
   24.28 +  either the GNU General Public License Version 2 or later (the "GPL"), or
   24.29 +  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
   24.30 +  in which case the provisions of the GPL or the LGPL are applicable instead
   24.31 +  of those above. If you wish to allow use of your version of this file only
   24.32 +  under the terms of either the GPL or the LGPL, and not to allow others to
   24.33 +  use your version of this file under the terms of the MPL, indicate your
   24.34 +  decision by deleting the provisions above and replace them with the notice
   24.35 +  and other provisions required by the GPL or the LGPL. If you do not delete
   24.36 +  the provisions above, a recipient may use your version of this file under
   24.37 +  the terms of any one of the MPL, the GPL or the LGPL.
   24.38 + 
   24.39 +*/
   24.40 +
   24.41 +using System;
   24.42 +using System.Collections;
   24.43 +using System.Collections.Generic;
   24.44 +
   24.45 +namespace OpenHardwareMonitor.Utilities {
   24.46 +
   24.47 +  public class ReadOnlyArray<T> : IReadOnlyArray<T> {
   24.48 +
   24.49 +    private T[] array;
   24.50 +
   24.51 +    public ReadOnlyArray(T[] array) {
   24.52 +      this.array = array;
   24.53 +    }
   24.54 +
   24.55 +    public T this[int index] {
   24.56 +      get { return array[index]; }
   24.57 +    }
   24.58 +
   24.59 +    public int Length { get { return array.Length; } }
   24.60 +
   24.61 +    public IEnumerator<T> GetEnumerator() {
   24.62 +      return ((IEnumerable<T>)array).GetEnumerator();
   24.63 +    }
   24.64 +
   24.65 +    IEnumerator IEnumerable.GetEnumerator() {
   24.66 +      return array.GetEnumerator();
   24.67 +    }
   24.68 +
   24.69 +    public static implicit operator ReadOnlyArray<T>(T[] array) {
   24.70 +      return new ReadOnlyArray<T>(array);
   24.71 +    }
   24.72 +  }
   24.73 +}