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 
00096 extern bool isPowerOut(u32 face);  
00097 
00098 extern void powerIn(u32 face, int on);
00099 
00100 /* Set all outbound power ON */
00101 extern void initPowerOuts();
00102 
00107 extern void invalidateCalibrationData();
00108 
00109 enum ADCSampleIndices {
00110   NORTH_VSENSE_ADC_IDX,
00111   SOUTH_VSENSE_ADC_IDX,
00112   EAST_VSENSE_ADC_IDX,
00113   WEST_VSENSE_ADC_IDX,
00114   VEE_VSENSE_ADC_IDX,
00115   VSENSE_IDX_COUNT,
00116 
00117   VCC_VSENSE_ADC_IDX = VSENSE_IDX_COUNT,
00118   
00119   NORTH_ISENSE_ADC_IDX,
00120   SOUTH_ISENSE_ADC_IDX,
00121   EAST_ISENSE_ADC_IDX,
00122   WEST_ISENSE_ADC_IDX,
00123   ADC_IDX_COUNT
00124 };
00125 
00126 #define ADC_NOMINAL_MV_PER_COUNT 3.22581
00127 #define ADC_FACE_RATIO 10.0
00128 #define ADC_VCC_RATIO 2.0
00129 
00130 #define NOMINAL_COUNTS_FOR_MV_FACE(mv) ((u32) (0.5+((mv)/ADC_NOMINAL_MV_PER_COUNT/ADC_FACE_RATIO)))
00131 #define NOMINAL_COUNTS_FOR_MV_VCC(mv) ((u32) (0.5+((mv)/ADC_NOMINAL_MV_PER_COUNT/ADC_VCC_RATIO)))
00132 #define NOMINAL_MV_FOR_COUNT_FACE(count) ((u32) (0.5+((count)*ADC_NOMINAL_MV_PER_COUNT*ADC_FACE_RATIO)))
00133 
00134 #define EXTRA_SLOPE_BITS 6
00135 #define UNCALIBRATED_SLOPE_FACE ((u32) ((ADC_NOMINAL_MV_PER_COUNT*ADC_FACE_RATIO)*(1<<EXTRA_SLOPE_BITS)))
00136 #define UNCALIBRATED_CUTOFF 300
00137 #define UNCALIBRATED_INTERCEPT_FACE (UNCALIBRATED_CUTOFF*UNCALIBRATED_SLOPE_FACE)
00138 
00139 #define CUTOFF_INDEX 0
00140 #define CUTOFF_BITS 5
00141 #define CUTOFF_CENTER 16
00142 #define CUTOFF_CT_PER_VALUE 10
00143 #define CUTOFF_OFFSET 300
00144 
00145 #define INTERCEPT_INDEX (CUTOFF_INDEX+CUTOFF_BITS)
00146 #define INTERCEPT_BITS 5
00147 #define INTERCEPT_CENTER 16
00148 #define INTERCEPT_MV_PER_VALUE 25
00149 #define INTERCEPT_OFFSET -300
00150 
00151 #define SLOPE0_INDEX (INTERCEPT_INDEX+INTERCEPT_BITS)
00152 #define SLOPE0_BITS 7
00153 #define SLOPE0_CENTER 64
00154 #define SLOPE0_SCALED_MV_PER_CT_PER_VALUE 10
00155 #define SLOPE0_OFFSET (UNCALIBRATED_SLOPE_FACE+SLOPE0_CENTER*SLOPE0_SCALED_MV_PER_CT_PER_VALUE)
00156 
00157 #define SLOPE1_INDEX (SLOPE0_INDEX+SLOPE0_BITS)
00158 #define SLOPE1_BITS 7
00159 #define SLOPE1_CENTER 64
00160 #define SLOPE1_SCALED_MV_PER_CT_PER_VALUE 10
00161 #define SLOPE1_OFFSET (UNCALIBRATED_SLOPE_FACE+SLOPE1_CENTER*SLOPE1_SCALED_MV_PER_CT_PER_VALUE)
00162 
00163 struct xcalib {
00164   u32 cutoff;
00165   s32 slope[2];
00166   s32 intercept[2];
00167 
00168   /* Here for 'default datasheet' behavior */
00169   void init() {
00170     init(0, UNCALIBRATED_SLOPE_FACE, UNCALIBRATED_SLOPE_FACE, 0);
00171   }
00172 
00173   void init(u32 c, s32 m0, s32 m1, s32 b) {
00174     cutoff = c;
00175     slope[0] = m0;
00176     intercept[0] = ((NOMINAL_MV_FOR_COUNT_FACE(c)+b)<<EXTRA_SLOPE_BITS)-m0*c;
00177     slope[1] = m1;
00178     intercept[1] = ((NOMINAL_MV_FOR_COUNT_FACE(c)+b)<<EXTRA_SLOPE_BITS)-m1*c;
00179   }
00180 };
00181 extern xcalib adcCalibs[VSENSE_IDX_COUNT];
00182 
00183 struct calibData {
00184 
00185   u32 data;
00186   inline u32 getBits(u32 bitIdx, u32 bits) {
00187     return (data>>bitIdx)&((1<<bits)-1);
00188   }
00189   void putBits(u32 bitIdx, u32 bits,u32 value) {
00190     u32 nbits = ((1<<bits)-1); 
00191     data &= ~(nbits<<bitIdx);
00192     data |= (value&nbits)<<bitIdx;
00193   }
00194   void init(u32 cutoff, u32 intercept, u32 slope0, u32 slope1) {
00195     putBits(CUTOFF_INDEX,CUTOFF_BITS,cutoff);
00196     putBits(INTERCEPT_INDEX,INTERCEPT_BITS,intercept);
00197     putBits(SLOPE0_INDEX,SLOPE0_BITS,slope0);
00198     putBits(SLOPE1_INDEX,SLOPE1_BITS,slope1);
00199   }
00200   void getFields(u32 & cutoff, u32 & intercept, u32 & slope0, u32 & slope1) {
00201     cutoff = getBits(CUTOFF_INDEX,CUTOFF_BITS);
00202     intercept = getBits(INTERCEPT_INDEX,INTERCEPT_BITS);
00203     slope0 = getBits(SLOPE0_INDEX,SLOPE0_BITS);
00204     slope1 = getBits(SLOPE1_INDEX,SLOPE1_BITS);
00205   }
00206   inline s32 getValue(u32 bitIdx, u32 bits, s32 center, s32 amtPerValue, s32 offset) {
00207     s32 value = getBits(bitIdx,bits);
00208     return (value-center)*amtPerValue+offset;
00209   }
00210   s32 getCutoffCt() { 
00211     return getValue(CUTOFF_INDEX,CUTOFF_BITS,CUTOFF_CENTER,CUTOFF_CT_PER_VALUE,CUTOFF_OFFSET);
00212   }
00213   s32 getInterceptMv() { 
00214     return
00215       getValue(INTERCEPT_INDEX,INTERCEPT_BITS,INTERCEPT_CENTER,INTERCEPT_MV_PER_VALUE,INTERCEPT_OFFSET);
00216   }
00217   s32 getSlopeScaledMvPerCt(u32 which) ;
00218 
00219   void initXcalib(xcalib & x) ;
00220 };
00221 
00222 extern void initxcalibsFromGene(u32 gene[VSENSE_IDX_COUNT]) ;
00223 
00226 #define VOLTAGE_CALIBRATION_SIZE_BYTES (VSENSE_IDX_COUNT*3)
00227 
00228 #define ADC_SCALE_BITS 6   /* This is fixed by the AD0DRx hardware; can't be changed efficiently */
00229 #define WEIGHT_BITS 5  /* Could be 5 for a ton of smoothing, or 3..1 for less (0 would be redundant) */
00230 #define UPDATE_SMOOTHED_BUFFER(u16buf,adcScaledData) \
00231   ((u16buf) = (u16) (((((u32)(u16buf))<<WEIGHT_BITS)-(u16buf)+(adcScaledData))>>WEIGHT_BITS))
00232 
00233 static inline s32 mapADCCounts(u16 scaledCount, s32 slope, s32 intercept) {
00234   return (((scaledCount*slope)>>ADC_SCALE_BITS)+intercept)>>EXTRA_SLOPE_BITS;
00235 }
00236 
00237 extern void unpackCalibrationData(u32 gene[VSENSE_IDX_COUNT], u8 bytes[VOLTAGE_CALIBRATION_SIZE_BYTES]) ;
00238 
00239 extern void loadCalibrationData() ;
00240 
00241 extern u16 adcLatestSample[ADC_IDX_COUNT];
00242 
00243 extern u16 adcSmooth[ADC_IDX_COUNT];
00244 
00245 static inline u16 getADCSample(u32 sampleIdx, bool smoothed) {
00246   API_ASSERT_MAX(sampleIdx,ADC_IDX_COUNT);
00247   return smoothed?adcSmooth[sampleIdx]:adcLatestSample[sampleIdx];
00248 }
00249 
00250 #define ADC_FLAG_CODE 0x000f /* Can't occur in nature: ADC always gives 6 LSBs==0 */
00251 static inline bool isADCSensingEnabled() {
00252   return adcLatestSample[NORTH_ISENSE_ADC_IDX] != ADC_FLAG_CODE;
00253 }
00254 static inline bool isPowerSensingEnabled() {
00255   return adcLatestSample[SOUTH_ISENSE_ADC_IDX] != ADC_FLAG_CODE;
00256 }
00257 extern void setADCSensingEnabled(bool enable) ;
00258 extern void setPowerSensingEnabled(bool enable) ;
00259 
00265 extern void initADC();
00271 extern void reinitADC();
00274 #endif /* SFBPOWER_H */

Generated on Fri Apr 22 06:54:12 2011 for SFB by doxygen 1.5.9