SFBPower.h

Go to the documentation of this file.
00001 /*
00002   SFBPower.h Power control and monitoring routines for the SFB.
00003   Copyright (C) 2009 The Regents of the University of New Mexico.  All rights reserved.
00004 
00005   This library is free software; you can redistribute it and/or
00006   modify it under the terms of the GNU Lesser General Public
00007   License as published by the Free Software Foundation; either
00008   version 2.1 of the License, or (at your option) any later version.
00009 
00010   This library is distributed in the hope that it will be useful,
00011   but WITHOUT ANY WARRANTY; without even the implied warranty of
00012   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013   Lesser General Public License for more details.
00014 
00015   You should have received a copy of the GNU General Public License
00016   along with this library; if not, write to the Free Software
00017   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
00018   USA
00019 
00020   $Id$
00021 */
00022 
00030 #ifndef SFBPOWER_H
00031 #define SFBPOWER_H
00032 
00033 #include "SFBTypes.h"     /* For u8 */
00034 #include "SFBConstants.h" /* For FACE_COUNT */
00035 #include "SFBAssert.h"    /* For API_ASSERT_MAX */
00036 
00037 extern int powerDraw();
00038 
00039 extern int powerDraw(u32 face);
00040 
00041 extern int rawPower(u32 face);
00042 
00060 extern s32 faceVoltage(u32 face, bool smoothed = true) ; 
00061 
00079 extern s32 railVoltage(bool smoothed = true) ;
00080 
00081 extern int rawVoltage();
00082 
00088 extern void powerOut(u32 face, int on);  
00089 
00090 extern void powerIn(u32 face, int on);
00091 
00092 /* Set all outbound power ON */
00093 extern void initPowerOuts();
00094 
00099 extern void invalidateCalibrationData();
00100 
00101 enum ADCSampleIndices {
00102   NORTH_VSENSE_ADC_IDX,
00103   SOUTH_VSENSE_ADC_IDX,
00104   EAST_VSENSE_ADC_IDX,
00105   WEST_VSENSE_ADC_IDX,
00106   VEE_VSENSE_ADC_IDX,
00107   VSENSE_IDX_COUNT,
00108 
00109   VCC_VSENSE_ADC_IDX = VSENSE_IDX_COUNT,
00110   
00111   NORTH_ISENSE_ADC_IDX,
00112   SOUTH_ISENSE_ADC_IDX,
00113   EAST_ISENSE_ADC_IDX,
00114   WEST_ISENSE_ADC_IDX,
00115   ADC_IDX_COUNT
00116 };
00117 
00118 #define ADC_NOMINAL_MV_PER_COUNT 3.22581
00119 #define ADC_FACE_RATIO 10.0
00120 #define ADC_VCC_RATIO 2.0
00121 
00122 #define NOMINAL_COUNTS_FOR_MV_FACE(mv) ((u32) (0.5+((mv)/ADC_NOMINAL_MV_PER_COUNT/ADC_FACE_RATIO)))
00123 #define NOMINAL_COUNTS_FOR_MV_VCC(mv) ((u32) (0.5+((mv)/ADC_NOMINAL_MV_PER_COUNT/ADC_VCC_RATIO)))
00124 #define NOMINAL_MV_FOR_COUNT_FACE(count) ((u32) (0.5+((count)*ADC_NOMINAL_MV_PER_COUNT*ADC_FACE_RATIO)))
00125 
00126 #define EXTRA_SLOPE_BITS 6
00127 #define UNCALIBRATED_SLOPE_FACE ((u32) ((ADC_NOMINAL_MV_PER_COUNT*ADC_FACE_RATIO)*(1<<EXTRA_SLOPE_BITS)))
00128 #define UNCALIBRATED_CUTOFF 300
00129 #define UNCALIBRATED_INTERCEPT_FACE (UNCALIBRATED_CUTOFF*UNCALIBRATED_SLOPE_FACE)
00130 
00131 #define CUTOFF_INDEX 0
00132 #define CUTOFF_BITS 5
00133 #define CUTOFF_CENTER 16
00134 #define CUTOFF_CT_PER_VALUE 10
00135 #define CUTOFF_OFFSET 300
00136 
00137 #define INTERCEPT_INDEX (CUTOFF_INDEX+CUTOFF_BITS)
00138 #define INTERCEPT_BITS 5
00139 #define INTERCEPT_CENTER 16
00140 #define INTERCEPT_MV_PER_VALUE 25
00141 #define INTERCEPT_OFFSET -300
00142 
00143 #define SLOPE0_INDEX (INTERCEPT_INDEX+INTERCEPT_BITS)
00144 #define SLOPE0_BITS 7
00145 #define SLOPE0_CENTER 64
00146 #define SLOPE0_SCALED_MV_PER_CT_PER_VALUE 10
00147 #define SLOPE0_OFFSET (UNCALIBRATED_SLOPE_FACE+SLOPE0_CENTER*SLOPE0_SCALED_MV_PER_CT_PER_VALUE)
00148 
00149 #define SLOPE1_INDEX (SLOPE0_INDEX+SLOPE0_BITS)
00150 #define SLOPE1_BITS 7
00151 #define SLOPE1_CENTER 64
00152 #define SLOPE1_SCALED_MV_PER_CT_PER_VALUE 10
00153 #define SLOPE1_OFFSET (UNCALIBRATED_SLOPE_FACE+SLOPE1_CENTER*SLOPE1_SCALED_MV_PER_CT_PER_VALUE)
00154 
00155 struct xcalib {
00156   u32 cutoff;
00157   s32 slope[2];
00158   s32 intercept[2];
00159 
00160   /* Here for 'default datasheet' behavior */
00161   void init() {
00162     init(0, UNCALIBRATED_SLOPE_FACE, UNCALIBRATED_SLOPE_FACE, 0);
00163   }
00164 
00165   void init(u32 c, s32 m0, s32 m1, s32 b) {
00166     cutoff = c;
00167     slope[0] = m0;
00168     intercept[0] = ((NOMINAL_MV_FOR_COUNT_FACE(c)+b)<<EXTRA_SLOPE_BITS)-m0*c;
00169     slope[1] = m1;
00170     intercept[1] = ((NOMINAL_MV_FOR_COUNT_FACE(c)+b)<<EXTRA_SLOPE_BITS)-m1*c;
00171   }
00172 };
00173 extern xcalib adcCalibs[VSENSE_IDX_COUNT];
00174 
00175 struct calibData {
00176 
00177   u32 data;
00178   inline u32 getBits(u32 bitIdx, u32 bits) {
00179     return (data>>bitIdx)&((1<<bits)-1);
00180   }
00181   void putBits(u32 bitIdx, u32 bits,u32 value) {
00182     u32 nbits = ((1<<bits)-1); 
00183     data &= ~(nbits<<bitIdx);
00184     data |= (value&nbits)<<bitIdx;
00185   }
00186   void init(u32 cutoff, u32 intercept, u32 slope0, u32 slope1) {
00187     putBits(CUTOFF_INDEX,CUTOFF_BITS,cutoff);
00188     putBits(INTERCEPT_INDEX,INTERCEPT_BITS,intercept);
00189     putBits(SLOPE0_INDEX,SLOPE0_BITS,slope0);
00190     putBits(SLOPE1_INDEX,SLOPE1_BITS,slope1);
00191   }
00192   void getFields(u32 & cutoff, u32 & intercept, u32 & slope0, u32 & slope1) {
00193     cutoff = getBits(CUTOFF_INDEX,CUTOFF_BITS);
00194     intercept = getBits(INTERCEPT_INDEX,INTERCEPT_BITS);
00195     slope0 = getBits(SLOPE0_INDEX,SLOPE0_BITS);
00196     slope1 = getBits(SLOPE1_INDEX,SLOPE1_BITS);
00197   }
00198   inline s32 getValue(u32 bitIdx, u32 bits, s32 center, s32 amtPerValue, s32 offset) {
00199     s32 value = getBits(bitIdx,bits);
00200     return (value-center)*amtPerValue+offset;
00201   }
00202   s32 getCutoffCt() { 
00203     return getValue(CUTOFF_INDEX,CUTOFF_BITS,CUTOFF_CENTER,CUTOFF_CT_PER_VALUE,CUTOFF_OFFSET);
00204   }
00205   s32 getInterceptMv() { 
00206     return
00207       getValue(INTERCEPT_INDEX,INTERCEPT_BITS,INTERCEPT_CENTER,INTERCEPT_MV_PER_VALUE,INTERCEPT_OFFSET);
00208   }
00209   s32 getSlopeScaledMvPerCt(u32 which) ;
00210 
00211   void initXcalib(xcalib & x) ;
00212 };
00213 
00214 extern void initxcalibsFromGene(u32 gene[VSENSE_IDX_COUNT]) ;
00215 
00218 #define VOLTAGE_CALIBRATION_SIZE_BYTES (VSENSE_IDX_COUNT*3)
00219 
00220 #define ADC_SCALE_BITS 6   /* This is fixed by the AD0DRx hardware; can't be changed efficiently */
00221 #define WEIGHT_BITS 5  /* Could be 5 for a ton of smoothing, or 3..1 for less (0 would be redundant) */
00222 #define UPDATE_SMOOTHED_BUFFER(u16buf,adcScaledData) \
00223   ((u16buf) = (u16) (((((u32)(u16buf))<<WEIGHT_BITS)-(u16buf)+(adcScaledData))>>WEIGHT_BITS))
00224 
00225 static inline s32 mapADCCounts(u16 scaledCount, s32 slope, s32 intercept) {
00226   return (((scaledCount*slope)>>ADC_SCALE_BITS)+intercept)>>EXTRA_SLOPE_BITS;
00227 }
00228 
00229 extern void unpackCalibrationData(u32 gene[VSENSE_IDX_COUNT], u8 bytes[VOLTAGE_CALIBRATION_SIZE_BYTES]) ;
00230 
00231 extern void loadCalibrationData() ;
00232 
00233 extern u16 adcLatestSample[ADC_IDX_COUNT];
00234 
00235 extern u16 adcSmooth[ADC_IDX_COUNT];
00236 
00237 static inline u16 getADCSample(u32 sampleIdx, bool smoothed) {
00238   API_ASSERT_MAX(sampleIdx,ADC_IDX_COUNT);
00239   return smoothed?adcSmooth[sampleIdx]:adcLatestSample[sampleIdx];
00240 }
00241 
00242 #define POWER_SENSING_FLAG_CODE 0xffff  /* Can't occur in nature: ADC always gives 6 LSBs==0 */
00243 static inline bool powerSensingEnabled() {
00244   return adcLatestSample[NORTH_ISENSE_ADC_IDX] != POWER_SENSING_FLAG_CODE;
00245 }
00246 extern void setPowerSensingEnabled(bool enable) ;
00247 
00253 extern void initADC();
00256 #endif /* SFBPOWER_H */

Generated on Sun Oct 18 09:58:55 2009 for SFB by doxygen 1.5.9