mirror of
https://github.com/lm-sensors/lm-sensors.git
synced 2026-10-16 10:49:31 +00:00
fixed temp & voltage conversion- they're still not perfect, but are worth testing
git-svn-id: http://lm-sensors.org/svn/lm-sensors/trunk@756 7894878c-1315-0410-8ee3-d5d059ff63e0
This commit is contained in:
1 parent
8f102882b8
commit
2c149094bd
1 file changed
+128
-26
+128
-26
@@ -4,7 +4,10 @@
|
||||
|
||||
Copyright (c) 1998, 1999,2000 Frodo Looijaard <frodol@dds.nl>,
|
||||
Kyösti Mälkki <kmalkki@cc.hut.fi>,
|
||||
and Mark Studebaker <mdsxyz123@yahoo.com>
|
||||
Mark Studebaker <mdsxyz123@yahoo.com>,
|
||||
and Bob Dougherty <bobd@stanford.edu>
|
||||
(Some conversion-factor data were contributed by Jonathan Teh Soon Yew <j.teh@iname.com>
|
||||
and Alex van Kaam <darkside@chello.nl>.)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -82,7 +85,8 @@ SENSORS_INSMOD_1(via686a);
|
||||
#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr))
|
||||
#define VIA686A_REG_FAN(nr) (0x28 + (nr))
|
||||
|
||||
static const u8 regtemp[] = {0x20, 0x21, 0x19};
|
||||
//static const u8 regtemp[] = {0x20, 0x21, 0x19};
|
||||
static const u8 regtemp[] = {0x20, 0x21, 0x1f};
|
||||
static const u8 regover[] = {0x39, 0x3d, 0x1d};
|
||||
static const u8 reghyst[] = {0x3a, 0x3e, 0x1e};
|
||||
/* temps numbered 1-3 */
|
||||
@@ -97,12 +101,46 @@ static const u8 reghyst[] = {0x3a, 0x3e, 0x1e};
|
||||
#define VIA686A_REG_FANDIV 0x47
|
||||
#define VIA686A_REG_CONFIG 0x40
|
||||
|
||||
#define ROUND_INT(val) ((val)<0?((val)-0.5):((val)+0.5))
|
||||
|
||||
/* Conversions. Rounding and limit checking is only done on the TO_REG
|
||||
variants. */
|
||||
|
||||
/************** VOLTAGE CONVERSIONS FIXME *************/
|
||||
#define IN_TO_REG(val) (SENSORS_LIMIT((((val) * 10 + 8)/16),0,255))
|
||||
#define IN_FROM_REG(val) (((val) * 16) / 10)
|
||||
/********* VOLTAGE CONVERSIONS (Bob Dougherty) ********/
|
||||
// From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew):
|
||||
// voltagefactor[0]=1.25/2628; // Vccp
|
||||
// voltagefactor[1]=1.25/2628; // +2.5V
|
||||
// voltagefactor[2]=1.67/2628; // +3.3V
|
||||
// voltagefactor[3]=2.6/2628; // +5V
|
||||
// voltagefactor[4]=6.3/2628; // +12V
|
||||
// in[i]=(data[i+2]*25.0+133)*voltagefactor[i];
|
||||
//
|
||||
// These get us close, but they don't completely agree with what my BIOS says-
|
||||
// they are all a bit low.
|
||||
extern inline u8 IN_TO_REG(long val, int inNum)
|
||||
{
|
||||
// there's an extra /100 hidden in the conversion factors here
|
||||
if (inNum<=1)
|
||||
return (u8)SENSORS_LIMIT(ROUND_INT(0.04*(val/0.047565-133)),0,255);
|
||||
else if (inNum==2)
|
||||
return (u8)SENSORS_LIMIT(ROUND_INT(0.04*(val/0.063546-133)),0,255);
|
||||
else if (inNum==3)
|
||||
return (u8)SENSORS_LIMIT(ROUND_INT(0.04*(val/0.098935-133)),0,255);
|
||||
else
|
||||
return (u8)SENSORS_LIMIT(ROUND_INT(0.04*(val/0.23973-133)),0,255);
|
||||
}
|
||||
extern inline long IN_FROM_REG(u8 val, int inNum)
|
||||
{
|
||||
// use 2500.0 instead of 25.0 because we nneed to multiply val by 100
|
||||
if (inNum<=1)
|
||||
return (long)ROUND_INT((2500.0*val+133)*0.00047565);
|
||||
else if (inNum==2)
|
||||
return (long)ROUND_INT((2500.0*val+133)*0.00063546);
|
||||
else if (inNum==3)
|
||||
return (long)ROUND_INT((2500.0*val+133)*0.00098935);
|
||||
else
|
||||
return (long)ROUND_INT((2500.0*val+133)*0.0023973);
|
||||
}
|
||||
|
||||
extern inline u8 FAN_TO_REG(long rpm, int div)
|
||||
{
|
||||
@@ -115,13 +153,74 @@ extern inline u8 FAN_TO_REG(long rpm, int div)
|
||||
|
||||
#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div)))
|
||||
|
||||
/********** TEMP CONVERSIONS FIXME ************/
|
||||
#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val)<0?(((val)-5)/10):\
|
||||
((val)+5)/10),0,255))
|
||||
/******** TEMP CONVERSIONS (Bob Dougherty) *********/
|
||||
// linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew)
|
||||
// if(temp<169)
|
||||
// return double(temp)*0.427-32.08;
|
||||
// else if(temp>=169 && temp<=202)
|
||||
// return double(temp)*0.582-58.16;
|
||||
// else
|
||||
// return double(temp)*0.924-127.33;
|
||||
//
|
||||
// A fifth-order polynomial fits the unofficial data (provided by Alex van Kaam <darkside@chello.nl>)
|
||||
// a bit better. It also give more reasonable numbers on my machine (ie. they agree with what my
|
||||
// BIOS tells me). Here's the fifth-order fit to the 10-bit data:
|
||||
// temp = 6.500371171990e-09*val^5 +-4.006529810457e-06*val^4 +9.830610857874e-04*val^3 +
|
||||
// -1.187047495730e-01*val^2 +8.700574403605e+00*val +-2.836026823804e+02
|
||||
//
|
||||
// Alas, neither work well because of precision limits in our math (?!?), so
|
||||
// I came up with a pretty good piecewise-2nd-order:
|
||||
//
|
||||
// For 8-bit readings:
|
||||
// 0-59: -0.00831398*val*val + 1.46882437*val - 63.66742250
|
||||
// 60:179: 0.00056874*val*val + 0.29665581*val - 23.7538571
|
||||
// 180-255: 0.01275451*val*val - 4.39034916*val + 428.14343750
|
||||
//
|
||||
// For 10-bit readings:
|
||||
// 0-283: -0.00051962*val*val + 0.36720609*val - 63.6674225
|
||||
// 284:763: 0.00004141*val*val + 0.06853503*val + -22.48959243
|
||||
// 764-1023: 0.00087626*val*val + -1.23656143*val + 488.97355989
|
||||
//
|
||||
// To convert the other way (temp to 8-bit reg val):
|
||||
// <0: 0.01864022*val*val + 2.12242751*val + 290.16637347
|
||||
// 0-55: -0.00714790*val*val + 2.60844692*val + 70.67197155
|
||||
// >55: -0.00991559*val*val + 2.48774551*val + 85.21011594
|
||||
|
||||
// Converting temps to register values
|
||||
extern inline u8 TEMP_TO_REG(long val)
|
||||
{
|
||||
val /= 10;
|
||||
if (val<0x00) // val<0
|
||||
return (u8)SENSORS_LIMIT(ROUND_INT(0.01864022*val*val + 2.12242751*val + 72.54159337),0,255);
|
||||
else if (val<0x37) // val<55
|
||||
return (u8)SENSORS_LIMIT(ROUND_INT(-0.00714790*val*val + 2.60844692*val + 70.67197155),0,255);
|
||||
else
|
||||
return (u8)SENSORS_LIMIT(ROUND_INT(-0.00991559*val*val + 2.48774551*val + 85.21011594),0,255);
|
||||
|
||||
}
|
||||
|
||||
/* for 8-bit temperature hyst and over registers */
|
||||
#define TEMP_FROM_REG(val) (((val)>0x80?(val)-0x100:(val))*10)
|
||||
extern inline long TEMP_FROM_REG(u8 val)
|
||||
{
|
||||
if (val<0x47) // val<71
|
||||
return (long)ROUND_INT(10.0*(-0.00831398*val*val + 1.46882437*val - 63.66742250));
|
||||
else if (val<0xbf) // val<191
|
||||
return (long)ROUND_INT(10.0*(0.00056874*val*val + 0.29665581*val - 23.7538571));
|
||||
else
|
||||
return (long)ROUND_INT(10.0*(0.01275451*val*val - 4.39034916*val + 428.14343750));
|
||||
}
|
||||
|
||||
/* for 10-bit temperature readings */
|
||||
#define TEMP_FROM_REG10(val) (((val)>0x80?(val)-0x100:(val))*10)
|
||||
extern inline long TEMP_FROM_REG10(u16 val)
|
||||
{
|
||||
if (val<0x011c) // val<284
|
||||
return (long)ROUND_INT(10.0*(-0.00051962*val*val + 0.36720609*val - 63.6674225));
|
||||
else if (val<0x02fc) //val<764
|
||||
return (long)ROUND_INT(10.0*(0.00004141*val*val + 0.06853503*val + -22.48959243));
|
||||
else
|
||||
return (long)ROUND_INT(10.0*(0.00087626*val*val + -1.23656143*val + 488.97355989));
|
||||
|
||||
}
|
||||
|
||||
#define ALARMS_FROM_REG(val) (val)
|
||||
|
||||
@@ -134,6 +233,8 @@ extern inline u8 FAN_TO_REG(long rpm, int div)
|
||||
#define VIA686A_INIT_IN_2 330
|
||||
#define VIA686A_INIT_IN_3 (((500) * 100)/168)
|
||||
#define VIA686A_INIT_IN_4 (((1200) * 10)/38)
|
||||
//#define VIA686A_INIT_IN_3 500
|
||||
//#define VIA686A_INIT_IN_4 1200
|
||||
|
||||
#define VIA686A_INIT_IN_PERCENTAGE 10
|
||||
|
||||
@@ -447,25 +548,25 @@ void via686a_init_client(struct i2c_client *client)
|
||||
via686a_write_value(client, VIA686A_REG_CONFIG, 0x80);
|
||||
|
||||
via686a_write_value(client, VIA686A_REG_IN_MIN(0),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_0));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_0, 0));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MAX(0),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_0));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_0, 0));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MIN(1),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_1));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_1, 1));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MAX(1),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_1));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_1, 1));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MIN(2),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_2));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_2, 2));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MAX(2),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_2));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_2, 2));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MIN(3),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_3));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_3, 3));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MAX(3),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_3));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_3, 3));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MIN(4),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_4));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MIN_4, 4));
|
||||
via686a_write_value(client, VIA686A_REG_IN_MAX(4),
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_4));
|
||||
IN_TO_REG(VIA686A_INIT_IN_MAX_4, 4));
|
||||
via686a_write_value(client, VIA686A_REG_FAN_MIN(1),
|
||||
FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
|
||||
via686a_write_value(client, VIA686A_REG_FAN_MIN(2),
|
||||
@@ -507,7 +608,7 @@ void via686a_update_client(struct i2c_client *client)
|
||||
}
|
||||
for (i = 1; i <= 3; i++) {
|
||||
data->temp[i - 1] = via686a_read_value(client,
|
||||
VIA686A_REG_TEMP(i)) << 2;
|
||||
VIA686A_REG_TEMP(i)) << 2;
|
||||
data->temp_over[i - 1] = via686a_read_value(client,
|
||||
VIA686A_REG_TEMP_OVER(i));
|
||||
data->temp_hyst[i - 1] = via686a_read_value(client,
|
||||
@@ -520,6 +621,7 @@ void via686a_update_client(struct i2c_client *client)
|
||||
VIA686A_REG_TEMP_LOW23) & 0x30) >> 4;
|
||||
data->temp[2] |= (via686a_read_value(client,
|
||||
VIA686A_REG_TEMP_LOW23) & 0xc0) >> 6;
|
||||
|
||||
i = via686a_read_value(client, VIA686A_REG_FANDIV);
|
||||
data->fan_div[0] = (i >> 4) & 0x03;
|
||||
data->fan_div[1] = i >> 6;
|
||||
@@ -556,18 +658,18 @@ void via686a_in(struct i2c_client *client, int operation, int ctl_name,
|
||||
*nrels_mag = 2;
|
||||
else if (operation == SENSORS_PROC_REAL_READ) {
|
||||
via686a_update_client(client);
|
||||
results[0] = IN_FROM_REG(data->in_min[nr]);
|
||||
results[1] = IN_FROM_REG(data->in_max[nr]);
|
||||
results[2] = IN_FROM_REG(data->in[nr]);
|
||||
results[0] = IN_FROM_REG(data->in_min[nr], nr);
|
||||
results[1] = IN_FROM_REG(data->in_max[nr], nr);
|
||||
results[2] = IN_FROM_REG(data->in[nr], nr);
|
||||
*nrels_mag = 3;
|
||||
} else if (operation == SENSORS_PROC_REAL_WRITE) {
|
||||
if (*nrels_mag >= 1) {
|
||||
data->in_min[nr] = IN_TO_REG(results[0]);
|
||||
data->in_min[nr] = IN_TO_REG(results[0], nr);
|
||||
via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
|
||||
data->in_min[nr]);
|
||||
}
|
||||
if (*nrels_mag >= 2) {
|
||||
data->in_max[nr] = IN_TO_REG(results[1]);
|
||||
data->in_max[nr] = IN_TO_REG(results[1], nr);
|
||||
via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
|
||||
data->in_max[nr]);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user