Changeset 759

Show
Ignore:
Timestamp:
03/07/00 16:25:20 (9 years ago)
Author:
bobd
Message:

bobd: removed nasty floating-point math, fixed temp3 over & hyst bug.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • lm-sensors/trunk/kernel/chips/via686a.c

    r756 r759  
    9494#define VIA686A_REG_TEMP_OVER(nr)       (regover[(nr) - 1]) 
    9595#define VIA686A_REG_TEMP_HYST(nr)       (reghyst[(nr) - 1]) 
    96 #define VIA686A_REG_TEMP_LOW1   0x4b 
    97 #define VIA686A_REG_TEMP_LOW23  0x49 
     96#define VIA686A_REG_TEMP_LOW1   0x4b // bits 7-6 
     97#define VIA686A_REG_TEMP_LOW23  0x49 // 2 = bits 5-4, 3 = bits 7-6 
    9898 
    9999#define VIA686A_REG_ALARM1 0x41 
     
    102102#define VIA686A_REG_CONFIG 0x40 
    103103 
    104 #define ROUND_INT(val) ((val)<0?((val)-0.5):((val)+0.5)) 
    105  
    106104/* Conversions. Rounding and limit checking is only done on the TO_REG 
    107105   variants. */ 
     
    109107/********* VOLTAGE CONVERSIONS (Bob Dougherty) ********/ 
    110108// From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew): 
    111 // voltagefactor[0]=1.25/2628;         // Vccp 
    112 // voltagefactor[1]=1.25/2628;         // +2.5V 
    113 // voltagefactor[2]=1.67/2628;         // +3.3V 
    114 // voltagefactor[3]=2.6/2628;          // +5V 
    115 // voltagefactor[4]=6.3/2628;          // +12V 
     109// voltagefactor[0]=1.25/2628; (2628/1.25=2102.4)   // Vccp 
     110// voltagefactor[1]=1.25/2628; (2628/1.25=2102.4)   // +2.5V 
     111// voltagefactor[2]=1.67/2628; (2628/1.67=1573.7)   // +3.3V 
     112// voltagefactor[3]=2.6/2628;  (2628/2.60=1010.8)   // +5V 
     113// voltagefactor[4]=6.3/2628;  (2628/6.30=417.14)   // +12V 
    116114// in[i]=(data[i+2]*25.0+133)*voltagefactor[i]; 
     115// That is: 
     116// volts = (25*regVal+133)*factor 
     117// regVal = (volts/factor-133)/25 
    117118//  
    118119// These get us close, but they don't completely agree with what my BIOS says- 
     
    120121extern inline u8 IN_TO_REG(long val, int inNum) 
    121122{ 
    122   // there's an extra /100 hidden in the conversion factors here 
     123  // to avoid floating point, we multiply everything by 100. 
     124  // val is guaranteed to be positive, so we can achieve the effect of rounding 
     125  // by adding 0.5.  Or, to avoid fp math, we do (...*10+5)/10. 
     126  // (note that the *10 is hidden in the /250 rather than /2500 
     127  // At the end, we need to /100 because we *100 everything and we need 
     128  // to /10 because of the rounding thing, so we /1000 
    123129  if (inNum<=1) 
    124     return (u8)SENSORS_LIMIT(ROUND_INT(0.04*(val/0.047565-133)),0,255); 
     130    return (u8)SENSORS_LIMIT(((val*210240-13300)/250+5)/1000,0,255); 
    125131  else if (inNum==2) 
    126     return (u8)SENSORS_LIMIT(ROUND_INT(0.04*(val/0.063546-133)),0,255); 
     132    return (u8)SENSORS_LIMIT(((val*157370-13300)/250+5)/1000,0,255); 
    127133  else if (inNum==3) 
    128     return (u8)SENSORS_LIMIT(ROUND_INT(0.04*(val/0.098935-133)),0,255); 
     134    return (u8)SENSORS_LIMIT(((val*101080-13300)/250+5)/1000,0,255); 
    129135  else  
    130     return (u8)SENSORS_LIMIT(ROUND_INT(0.04*(val/0.23973-133)),0,255); 
     136    return (u8)SENSORS_LIMIT(((val*41714-13300)/250+5)/1000,0,255); 
    131137} 
    132138extern inline long IN_FROM_REG(u8 val, int inNum) 
    133139{ 
    134    // use 2500.0 instead of 25.0 because we nneed to multiply val by 100 
     140  // to avoid floating point, we multiply everything by 100. 
     141  // val is guaranteed to be positive, so we can achieve the effect of rounding 
     142  // by adding 0.5.  Or, to avoid fp math, we do (...*10+5)/10. 
     143  // Since we need to scale up by 100 anyway, we don't need to /100 at the end. 
    135144  if (inNum<=1)  
    136     return (long)ROUND_INT((2500.0*val+133)*0.00047565); 
     145    return (long)(((250000*val+13300)/210240*10+5)/10); // was 210240, 205240 works better 
    137146  else if (inNum==2) 
    138     return (long)ROUND_INT((2500.0*val+133)*0.00063546); 
     147    return (long)(((250000*val+13300)/157370*10+5)/10); // was 157370, 154370 works better 
    139148  else if (inNum==3) 
    140     return (long)ROUND_INT((2500.0*val+133)*0.00098935); 
     149    return (long)(((250000*val+13300)/101080*10+5)/10); 
    141150  else  
    142     return (long)ROUND_INT((2500.0*val+133)*0.0023973); 
     151    return (long)(((250000*val+13300)/41714*10+5)/10); 
    143152} 
    144153 
     
    148157                return 255; 
    149158        rpm = SENSORS_LIMIT(rpm, 1, 1000000); 
    150         return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 
    151                              254); 
     159        return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); 
    152160} 
    153161 
     
    168176// temp = 6.500371171990e-09*val^5 +-4.006529810457e-06*val^4 +9.830610857874e-04*val^3 + 
    169177// -1.187047495730e-01*val^2 +8.700574403605e+00*val +-2.836026823804e+02 
    170 //  
    171 // Alas, neither work well because of precision limits in our math (?!?), so 
    172 // I came up with a pretty good piecewise-2nd-order: 
    173 //  
    174 // For 8-bit readings: 
    175 //   0-59: -0.00831398*val*val + 1.46882437*val - 63.66742250 
    176 //   60:179: 0.00056874*val*val + 0.29665581*val - 23.7538571 
    177 //   180-255: 0.01275451*val*val - 4.39034916*val + 428.14343750 
    178 //  
    179 // For 10-bit readings: 
    180 //   0-283: -0.00051962*val*val + 0.36720609*val - 63.6674225 
    181 //   284:763: 0.00004141*val*val + 0.06853503*val + -22.48959243 
    182 //   764-1023: 0.00087626*val*val + -1.23656143*val + 488.97355989 
    183 //  
    184 // To convert the other way (temp to 8-bit reg val):  
    185 //   <0: 0.01864022*val*val + 2.12242751*val + 290.16637347 
    186 //   0-55: -0.00714790*val*val + 2.60844692*val + 70.67197155 
    187 //   >55: -0.00991559*val*val + 2.48774551*val + 85.21011594 
     178// 
     179// None of the elegant function-fit solutions will work because we aren't allowed  
     180// to use floating point in the kernel, so we'll do boring-old look-up table stuff. 
     181// Here are the unofficial data (provided by Alex van Kaam <darkside@chello.nl>). 
     182// Note that t is the temp at via register values 12-240 (8-bit), 48-960 (10-bit). 
     183static const u8 tempLUT[] = {-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31,\ 
     184-30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15,-15,-14,\ 
     185-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3,-3,-2,-2,-1,-1,0,0,\ 
     1861,1,1,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9,10,10,11,11,12,12,12,13,13,13,14,14,15,15,16,\ 
     18716,16,17,17,18,18,19,19,20,20,21,21,21,22,22,22,23,23,24,24,25,25,26,26,26,27,27,27,28,\ 
     18828,29,29,30,30,30,31,31,32,32,33,33,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,\ 
     18942,42,43,43,44,44,45,45,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,\ 
     19059,59,60,61,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84,85,\ 
     19186,88,89,91,92,94,96,97,99,101,103,105,107,109,110}; 
     192 
     193// Here's the reverse LUT.  I got it by doing a 6-th order poly fit to the data and then 
     194// solving for each temp value from -50 to 110.  (n=161) 
     195static const u16 viaLUT[] = {12,12,13,14,14,15,16,16,17,18,18,19,20,20,21,22,23,23,24,\ 
     19625,26,27,28,29,30,31,32,33,35,36,37,39,40,41,43,45,46,48,49,51,53,55,57,59,60,62,64,66,\ 
     19769,71,73,75,77,79,82,84,86,88,91,93,95,98,100,103,105,107,110,112,115,117,119,122,124,\ 
     198126,129,131,134,136,138,140,143,145,147,150,152,154,156,158,160,162,164,166,168,170,\ 
     199172,174,176,178,180,182,183,185,187,188,190,192,193,195,196,198,199,200,202,203,204,\ 
     200205,207,208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,222,223,224,225,\ 
     201226,226,227,228,228,229,230,230,231,232,232,233,233,234,235,235,236,236,237,237,238,\ 
     202238,239,239,240}; 
    188203 
    189204// Converting temps to register values 
    190205extern inline u8 TEMP_TO_REG(long val) 
    191206{ 
    192   val /= 10; 
    193   if (val<0x00) // val<0 
    194     return (u8)SENSORS_LIMIT(ROUND_INT(0.01864022*val*val + 2.12242751*val + 72.54159337),0,255); 
    195   else if (val<0x37) // val<55 
    196     return (u8)SENSORS_LIMIT(ROUND_INT(-0.00714790*val*val + 2.60844692*val + 70.67197155),0,255); 
    197   else 
    198     return (u8)SENSORS_LIMIT(ROUND_INT(-0.00991559*val*val + 2.48774551*val + 85.21011594),0,255); 
    199  
     207  // No interpolation here. 
     208  if (val<=-500) return (u8)SENSORS_LIMIT(viaLUT[0],0,255); 
     209  if (val>=1100) return (u8)SENSORS_LIMIT(viaLUT[160],0,255); 
     210  // the +5 effective rounds it off properly 
     211  return (u8)SENSORS_LIMIT(viaLUT[(val+5)/10+50],0,255); 
    200212} 
    201213 
     
    203215extern inline long TEMP_FROM_REG(u8 val) 
    204216{ 
    205   if (val<0x47) // val<71 
    206     return (long)ROUND_INT(10.0*(-0.00831398*val*val + 1.46882437*val - 63.66742250)); 
    207   else if (val<0xbf) // val<191 
    208     return (long)ROUND_INT(10.0*(0.00056874*val*val + 0.29665581*val - 23.7538571)); 
    209   else 
    210     return (long)ROUND_INT(10.0*(0.01275451*val*val - 4.39034916*val + 428.14343750)); 
     217  // the LUT starts at 12 (not 0) and ends at 240 (not 255), so that's why we do what we do here. 
     218  return (long)(tempLUT[(val<11)?(0):((val>240)?(228):(val-12))]*10); 
    211219} 
    212220 
     
    214222extern inline long TEMP_FROM_REG10(u16 val) 
    215223{ 
    216   if (val<0x011c)  // val<284 
    217     return (long)ROUND_INT(10.0*(-0.00051962*val*val + 0.36720609*val - 63.6674225)); 
    218   else if (val<0x02fc) //val<764 
    219     return (long)ROUND_INT(10.0*(0.00004141*val*val + 0.06853503*val + -22.48959243)); 
    220   else 
    221     return (long)ROUND_INT(10.0*(0.00087626*val*val + -1.23656143*val + 488.97355989)); 
    222   
     224  u16 eightBits = val>>2; 
     225  u16 twoBits = val&3; 
     226 
     227  if (val<=48) return (long)tempLUT[0]*10;     // via8bit<=12 
     228  if (val>=960) return (long)tempLUT[228]*10; // via8bit>=240 
     229   
     230  if (twoBits==0)  
     231    return (long)tempLUT[eightBits-12]*10; 
     232  else { 
     233    // do some interpolation by multipying the lower and uppers bounds by 25, 50 or 75  
     234    // (depending on which it's closer to), then /100.  But since we need to *10 anyway, we only /10 
     235    // ***FIX THIS*** we should properly round this off 
     236    return (long)(((25*(4-twoBits))*tempLUT[eightBits-12] + (25*twoBits)*tempLUT[eightBits-11])/10); 
     237  } 
    223238} 
    224239 
     
    572587        via686a_write_value(client, VIA686A_REG_FAN_MIN(2), 
    573588                            FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2)); 
    574         for(i = 1; i < 3; i++) { 
     589        for(i = 1; i <= 3; i++) { 
    575590                via686a_write_value(client, VIA686A_REG_TEMP_OVER(i), 
    576591                                    TEMP_TO_REG(VIA686A_INIT_TEMP_OVER)); 
     
    615630                                                 VIA686A_REG_TEMP_HYST(i)); 
    616631                } 
    617                 /* add in lower 2 bits */ 
     632                /* add in lower 2 bits  
     633                   temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1 
     634                   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23 
     635                   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23 
     636                */ 
    618637                data->temp[0] |= (via686a_read_value(client, 
    619638                                   VIA686A_REG_TEMP_LOW1) & 0xc0) >> 6;