00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00030 #ifndef SFBPOWER_H
00031 #define SFBPOWER_H
00032
00033 #include "SFBTypes.h"
00034 #include "SFBConstants.h"
00035 #include "SFBAssert.h"
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
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
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
00221 #define WEIGHT_BITS 5
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
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