# 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 */