main.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00025 //#include "iom406_320.h"
00026 #include <iom406.h>     // IAR headerfile for Mega406 (EW 410)
00027 #include <inavr.h>
00028 
00029 #define MODULE_MAIN
00030 #include "main.h"
00031 #include "analog.h"
00032 #include "calibration.h"
00033 #include "timer.h"
00034 #include "pack.h"
00035 #include "smbus.h"
00036 #include "gpio.h"
00037 #include "safety.h"
00038 #include "pwrmgmt.h"
00039 #include "ee.h"
00040 
00041 
00042 
00043 //Local Prototypes
00044 void BalanceCheck(void);
00045 void ChargeCheck(void);
00046 void ThermalCheck(void);
00047 void AlarmModeDisabledCheck(void);
00048 void AlarmConditionsCheck(void);
00049 void MasterSMBusCheck(unsigned char ResetTimer);
00050 void SleepMgr(void);
00051 void WdogMgr(void);
00052 void DoCalibrate(void);
00053 
00054 
00055 
00056 void InitAll(void)
00057 {
00058   InitSMBus();          //set this up first, as spec req's 1mS wakeup!
00059 
00062 //
00063 //  Wdog_init(WDOG_MODE_RSTINT, WD1sec);                //set rate to slow
00064 
00065 
00066   PinInit();            //set up I/O
00067   T0init();
00068   T1init();
00069   PBinit();             //activate Pushbutton Interrupt
00070   CCinit();             
00071   ADCinit();            
00072   HWProtectinit();
00073   InitSMBvariables();
00074 }
00075 
00076 
00077 
00078 unsigned char qtrsectick = 3;
00079 unsigned char AlarmModeDisabledTimer = 0;
00080 
00081 
00082 //#pragma object_attribute=__c_task
00083 void main(void)
00084 {
00085   InitAll();
00086   ChangePowerMode(POWERMODE_POWERSAVE,0);
00087   __enable_interrupt();
00088 
00089   LEDs = 0x1f;
00090 
00091   for(;;)
00092   {
00093     if(action_flags)    //see what needs to be handled right now
00094     {
00095       if(CheckCalibRequest)
00096       {
00097         ClrCalibRequest;
00098         DoCalibrate();        // Perform requested calibration.
00099       }
00100 
00101       if(CheckADCScanDone)
00102       {
00103         ClrADCScanDone;
00104 
00105         //Runs approx. once per second, AFTER new VADC readings are available.
00106         CalculateADCresults();          // produce scaled results from raw ADC samples
00107         BalanceCheck();                 // see if we need to do any cell balancing
00108         ChargeCheck();                  // monitor charging/discharging
00109         ThermalCheck();                 // watch for over-temperature conditions
00110         AlarmModeDisabledCheck();       // start timer for re-enabling Alarm Mode
00111         AlarmConditionsCheck();         // see if any capacity-related alarm conditions exist
00112         MasterSMBusCheck(0);            // see if anything needs to be sent out
00113       }
00114 
00115       if(CheckQtrSec)
00116       {
00117         ClrQtrSec;
00118         SetGenericTimer(OneQtrSecond, 244);
00119 
00120         WdogMgr();
00121 
00122         //Check if we're timing the startup of the 32KHz oscillator.
00123         if(Timer32KHz)
00124         {
00125           if(--Timer32KHz == 0)
00126             CCSR = ((1<<XOE)|(1<<ACS));
00127         }
00128         
00129         if(++qtrsectick >= 4)
00130         { //execute the following ONCE PER SECOND
00131           qtrsectick = 0;
00132           ThermistorSelect++;
00133           ThermistorSelect &= 0x03;
00134           StartAdc(ThermistorSelect);
00135         }
00136       }
00137 
00138       if(CheckAlarmMode)        //if bit is turned on, start 60-sec timer to re-enable it
00139       {
00140         ClrAlarmMode;                   //clear the ACTION flag, not the bit in BATTERY_MODE.
00141         AlarmModeDisabledTimer = 0;     //clear 60 sec timer
00142       }
00143 
00144       if(CheckMasterSMBdone)
00145       {
00146         ClrMasterSMBdone;
00147         SMBvariables[SMBV_BattStatus][lobyte] &= ~(0x0F);  //clear Error Code after TX
00148         MasterSMBusCheck(1);                               //reset the inter-msg timer
00149       }
00150     }
00151     else //if no ActionFlag bits are set
00152     {
00153       if(!GetGenericTimer(OneQtrSecond))        //this should be running always!
00154         SetGenericTimer(OneQtrSecond, 244);     //restart 250mS timer if it got shut off!
00155     }
00156 
00157     SMB_CmdInterpreter();                       //See if there were any received commands.
00158     Check50uS();                                //this checks whether we are trying to grab the bus.
00159     SetLEDs(LEDs);                              //change the parameter to be whatever you want.
00160 
00161 //    SleepMgr();       //! \todo  This is disabled ONLY for debugging purposes.
00162 
00163   }
00164 }
00165 
00166 
00167 
00168 //Check the individual cell readings and see if they are diverging.
00169 void BalanceCheck(void)
00170 {
00171   unsigned int Vmax = ReadCell(1);
00172   unsigned int temp;
00173   unsigned char maxcell = 1;
00174   unsigned char delta = 0;
00175 
00176   //First determine which cell is the highest, and by how much.
00177   temp = ReadCell(2);
00178   if(temp > Vmax)
00179   {
00180     delta += (temp - Vmax);
00181     Vmax += delta;
00182     maxcell = 2;
00183   }
00184   else
00185   if(temp < (Vmax - delta))
00186   {
00187     delta = (Vmax - temp);
00188   }
00189 
00190   if(PACKSTACK > 2)             //this is in  pack_cfg.h
00191   {
00192     temp = ReadCell(3);
00193     if(temp > Vmax)
00194     {
00195       delta += (temp - Vmax);
00196       Vmax += delta;
00197       maxcell = 3;
00198     }
00199     else
00200     if(temp < (Vmax - delta))
00201     {
00202       delta = (Vmax - temp);
00203     }
00204   }
00205 
00206   if(PACKSTACK > 3)
00207   {
00208     temp = ReadCell(4);
00209     if(temp > Vmax)
00210     {
00211       delta += (temp - Vmax);
00212       Vmax += delta;
00213       maxcell = 4;
00214     }
00215     else
00216     if(temp < (Vmax - delta))
00217     {
00218       delta = (Vmax - temp);
00219     }
00220   }
00221 
00222   //We now know which cell is the highest, and what the delta is.
00223 
00224   //If the imbalance is high enough, start Balancing.
00225   if(delta > MAX_IMBALANCE)
00226   {
00227     CellToBalance = maxcell;    //save which cell is the highest
00228     EnableCellBalancing();
00229   }
00230   else  //ensure that Balancing is OFF.
00231   {
00232     CellToBalance = 0;          //You MUST do this; the ISR enables Balancing, so if
00233     DisableCellBalancing();     //you leave this non-zero, it WILL re-assert balancing.
00234   }
00235 }
00236 
00237 
00238 
00239 
00240 
00241 
00242 
00243 void ChargeCheck(void)  //monitor charging and discharging
00244 {
00245   signed int cell = (signed int) ReadCell(1);   //doesn't really matter which cell...
00246   unsigned char charge_percent;
00247 
00248   //First, the voltage-based assessment.
00249   if(cell >= CELL_NOMINALV)
00250   {
00251     if(SMBvariables[SMBV_BattStatus][lobyte] & FULLY_CHARGED)   //already had reached this point?
00252     {
00253       if(Current1Sec() < 0)     //started discharging yet?
00254       {
00255         SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
00256         FCSR = (1<<DFE) | (1<<CFE);     //enable both FETs
00257       }
00258       else //not discharging yet
00259       {
00260         if((cell >= CELL_TOOMUCHV) && (Current1Sec() > 0))      //still CHARGING??
00261         {
00262           FCSR = (1<<DFE) | (1<<PFD);   //stop charging (CAN STILL DISCHG THRU DIODE!
00263         }
00264       }
00265     }
00266     else                //initial detection of FULL condition
00267     {
00268       FullChargeReached();              //update Capacity figures.
00269       SMBvariables[SMBV_BattStatus][lobyte] |= FULLY_CHARGED;
00270 
00271       if(Current1Sec() > 0)             //still charging...
00272       {
00273         SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_CHARGE_ALARM;
00274         SMBvariables[SMBV_BattStatus][hibyte] |= OVER_CHARGED_ALARM;
00275       }
00276     }
00277     return;             //don't bother running any further tests!
00278   }
00279   else
00280   if(cell <= CELL_MINV)
00281   {
00282     if(SMBvariables[SMBV_BattStatus][lobyte] & FULLY_DISCHARGED)  //already had reached this point?
00283     {
00284       if(Current1Sec() > 0)                                     //started CHARGING yet?
00285       {
00286         SMBvariables[SMBV_BattStatus][lobyte] &= ~DISCHARGING;
00287         FCSR = (1<<DFE) | (1<<CFE);                             //enable both FETs
00288       }
00289       else //not charging yet
00290       {
00291         if((cell <= CELL_TOOLITTLEV) && (Current1Sec() < 0))    //still DISCHARGING??
00292         {
00293           FCSR = 0;     //turn off Chg & Dischg FETS, only Precharge FET enabled.
00294           SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_DISCHARGE_ALARM;
00295           SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
00296         }
00297       }
00298     }
00299     else                //initial detection of EMPTY condition
00300     {
00301       FullDischargeReached();           //update Capacity figures.
00302       SMBvariables[SMBV_BattStatus][lobyte] |= FULLY_DISCHARGED;
00303       SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_DISCHARGE_ALARM;
00304     }
00305     return;             //don't bother running any further tests!
00306   }
00307   else
00308   {
00309     FCSR |= (1<<DFE) | (1<<CFE) | (1<<PFD);
00310   }
00311 
00312   //Next, check the Charging or Discharging current levels for excesses.
00313   charge_percent = RelativeSOC();
00314   cell = Current1Sec();         //neg means discharging, pos means charging
00315   if(cell <= 0)                 //discharging (0 is included due to SELF-discharge)
00316   {
00317     cell = -cell;
00318 
00319     //We must now assert the DISCHARGING flag.
00320     SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
00321 
00322     //If we're discharging, always clear the Charging alarm flag.
00323     SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_CHARGE_ALARM;
00324 
00325     //See if we should clear the FULLY_CHARGED flag yet.
00326     if(charge_percent < 99)
00327       SMBvariables[SMBV_BattStatus][lobyte] &= ~FULLY_CHARGED;
00328 
00329     //Check if need to Terminate Discharge (bit D11)    
00330     if((cell > PACK_DISCHG_MAX) || (charge_percent == 1))
00331       SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_DISCHARGE_ALARM;
00332     else
00333       SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_DISCHARGE_ALARM;
00334 
00335     //Note: we ONLY shut off LOCALLY if the cell V drops below
00336     // the minimum CELL VOLTAGE, and NOT if (charge_percent == 0).
00337     //The reason for this is, by definition, the pack is not drained
00338     // completely until you get down to minimum V. The charge_percent
00339     // figure could be *wrong* or it may be uncalibrated.
00340   }
00341   else //we are Charging
00342   {
00343     //When charging, always clear the Discharging alarm flag.
00344     SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_DISCHARGE_ALARM;
00345 
00346     //We can therefore also clear the DISCHARGING flag.
00347     SMBvariables[SMBV_BattStatus][lobyte] &= ~DISCHARGING;
00348 
00349     //See if we can clear the FULLY_DISCHARGED flag yet.
00350     if( (SMBvariables[SMBV_BattStatus][lobyte] & FULLY_DISCHARGED) &&
00351         (charge_percent > 20) )
00352       SMBvariables[SMBV_BattStatus][lobyte] &= ~FULLY_DISCHARGED;
00353 
00354     if(cell == 0)       //is there NO charge current?
00355     {           // currently never reached, due to 0 included in discharge
00356       SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_CHARGE_ALARM;
00357       SMBvariables[SMBV_BattStatus][hibyte] &= ~OVER_CHARGED_ALARM;
00358     }
00359     else //still charging...
00360     {
00361       //Terminate Charge (bit D14)
00362       if((cell > PACK_MAX_CHG_C) || (charge_percent >= 100))
00363         SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_CHARGE_ALARM;
00364       else
00365         SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_CHARGE_ALARM;
00366 
00367       //Excess charge?
00368       if(charge_percent >= 100)
00369         SMBvariables[SMBV_BattStatus][hibyte] |= OVER_CHARGED_ALARM;
00370       else
00371         SMBvariables[SMBV_BattStatus][hibyte] &= ~OVER_CHARGED_ALARM;
00372     }
00373   }
00374 
00377   //
00378   // if(???)
00379   //   SMBvar_int[SMBV_CycleCount]++;
00380 }
00381 
00382 
00383 
00384 void ThermalCheck(void)
00385 {
00386   unsigned int temp = GetTemperature();
00387 
00388   //check for OverTemp alarm (bit D12)
00389   if(temp > MAX_CELL_TEMPERATURE)
00390     SMBvariables[SMBV_BattStatus][hibyte] |= OVER_TEMP_ALARM;
00391   else
00392     SMBvariables[SMBV_BattStatus][hibyte] &= ~OVER_TEMP_ALARM;
00393 
00394   //If the Host/Charger doesn't respond fast enough, SHUT DOWN LOCALLY.
00395   if(temp > MAX_ONCHIP_TEMP)
00396     DoShutdown(SHUTDOWN_REASON_OVERTEMPERATURE);
00397 
00398 
00401 
00402 /*
00403   if(ReadTemperature(1) > MAX_CELL_TEMPERATURE)
00404     ;
00405 
00406 
00407   if(ReadTemperature(2) > MAX_CELL_TEMPERATURE)
00408     ;
00409 
00410   if(PACKSTACK <= 2)
00411     return;
00412   if(ReadTemperature(3) > MAX_CELL_TEMPERATURE)
00413     ;
00414 
00415 
00416   if(PACKSTACK <= 3)
00417     return;
00418   if(ReadTemperature(4) > MAX_CELL_TEMPERATURE)
00419     ;
00420 */
00421 
00422 }
00423 
00424 
00425 
00426 //This makes sure Alarm Mode is only disabled for 60 seconds max.
00427 void AlarmModeDisabledCheck(void)
00428 {
00429   if(SMBvariables[SMBV_BattMode][hibyte] & ALARM_MODE)
00430   {
00431     if(++AlarmModeDisabledTimer >= 59)
00432     {
00433       SMBvariables[SMBV_BattMode][hibyte] &= ~ALARM_MODE;       //re-enable
00434     }
00435   }
00436 }
00437 
00438 
00439 
00440 void AlarmConditionsCheck(void)         //look for 'other' alarm conditions
00441 {
00442   //Remaining Time (bit D8)
00443   if(SMBvar_int[SMBV_RemTimeAlm] != 0)
00444   {
00445     if(TimeToEmpty(0) < SMBvar_int[SMBV_RemTimeAlm])
00446       SMBvariables[SMBV_BattStatus][hibyte] |= REMAINING_TIME_ALARM;
00447   }
00448   else
00449     SMBvariables[SMBV_BattStatus][hibyte] &= ~REMAINING_TIME_ALARM;
00450 
00451 
00452   //Remaining Capacity (bit D9)
00453   if(SMBvar_int[SMBV_RemCapAlm] != 0)
00454   {
00455     if(RemainingCap() < SMBvar_int[SMBV_RemCapAlm])
00456       SMBvariables[SMBV_BattStatus][hibyte] |= REMAINING_CAPACITY_ALARM;
00457   }
00458   else
00459     SMBvariables[SMBV_BattStatus][hibyte] &= ~REMAINING_CAPACITY_ALARM;
00460 
00461 }
00462 
00463 
00464 
00465 void MasterSMBusCheck(unsigned char ResetTimer) //this gets called once per second (except to assert ResetTimer).
00466 {
00467   static unsigned char timer = 0;
00468 
00469   //When you call SMB_Master(), it will only TX if there's something in the buffer.
00470   //To control this, we only INSERT if it's >10 seconds since last TX.
00471 
00472   if(ResetTimer)
00473   {
00474     timer = 0;
00475     return;
00476   }
00477 
00478   if(++timer < 10)
00479   {
00480     SMB_Master();
00481     return;
00482   }
00483 
00484   if(!(SMBvariables[SMBV_BattMode][hibyte] & ALARM_MODE))
00485   {
00486     //Check if there's a newly-updated BatteryStatus that must be sent ASAP
00487     if(SMBvariables[SMBV_BattStatus][hibyte])
00488     {
00489       if(SMBvariables[SMBV_BattStatus][hibyte] & ~(REMAINING_CAPACITY_ALARM | REMAINING_TIME_ALARM))
00490       { // Need to send this message to BOTH the Host and the Charger.
00491         MasterInsertMsg(CHARGER_ADDR, SMB_M_CMD_ALARMWARNING, SMBvar_int[SMBV_BattStatus]);
00492       }
00493       //All messages are sent to the Host.
00494       MasterInsertMsg(HOST_ADDR, SMB_M_CMD_ALARMWARNING, SMBvar_int[SMBV_BattStatus]);
00495     }
00496 
00497 
00500 
00501     if(!(SMBvariables[SMBV_BattMode][hibyte] & CHARGER_MODE))    // Check that Charger_Mode is enabled, per sbdat110, 5.1.4
00502     {
00503       if(!(SMBvariables[SMBV_BattStatus][lobyte] & FULLY_CHARGED) ||
00504          !(SMBvariables[SMBV_BattStatus][hibyte] & TERMINATE_CHARGE_ALARM) ||
00505          !(SMBvariables[SMBV_BattStatus][hibyte] & OVER_CHARGED_ALARM)) { // it is OK to charge?
00506 
00507         SMBvar_int[SMBV_ChgCurrent] = PACK_CCCV_C;      //
00508         SMBvar_int[SMBV_ChgVoltage] = PACK_CCCV_V;      //
00509         MasterInsertMsg(CHARGER_ADDR, SMB_M_CMD_CHARGINGCURRENT, PACK_CCCV_C);
00510         MasterInsertMsg(CHARGER_ADDR, SMB_M_CMD_CHARGINGVOLTAGE, PACK_CCCV_V);
00511       } else { // it is not ok to charge
00512         SMBvar_int[SMBV_ChgCurrent] = 0x0000;   //
00513         SMBvar_int[SMBV_ChgVoltage] = 0x0000;   //
00514       }
00515     }
00516 
00517 
00518     timer = 0;  //clearing this prevents the same messages from repeatedly being added to the TX buffer.
00519   }
00520 
00521   SMB_Master();
00522 }
00523 
00524 
00525 
00526 
00527 
00528 void SleepMgr(void)
00529 {
00530   SMCR |= (1<<SE);
00531   __sleep();
00532   __no_operation();
00533   __no_operation();
00534   __no_operation();
00535   __no_operation();
00536 
00537   //at this point, we should be asleep.
00538 
00539   // ...
00540 
00541   //at this point, we've just completed running the ISR for whatever interrupt woke us up.
00542   SMCR &= ~(1<<SE);     //According to the datasheet, we should clear the SE bit at wakeup.
00543   return;               //Go back to main loop & see if we need to do anything else before sleeping again.
00544 }
00545 
00546 
00547 
00548 void WdogMgr(void)
00549 {
00551   //        from continually feeding the Wdog.
00552 
00553   __watchdog_reset();
00554 
00555   return;
00556 }
00557 
00558 
00559 
00560 void DoCalibrate(void)
00561 {
00562   // Explanation of the DoCalibrate routine:
00563   // User requests calibration by sending a word write SMBus command 0x3c (OptionalMfgFunction4)
00564   // with the appropriate bits set. This sets CALIBREQUESTED bit flag in action_flags, and the
00565   // 'calibration_state_req' variable contains the received word. A read of OptionalMfgFunction4
00566   // returns the current state contained in the 'calibration_state variable'.
00567   //
00568   // The valibles are both divided into 2-bit fields, which makes room for a total of 8 calibration routines.
00569   // Currently two calibration-routines are implemented in the lower 4 bits of the lowest byte:
00570   // xx xx xx xx xx xx BB AA.
00571   //
00572   // xx = Unused bits, always 00.
00573   // AA = State of vref calibration.
00574   // BB = State of coloumb counter offset calibration.
00575   //
00576   // State codes:
00577   //   00 - No calibration / calibration not requested.
00578   //   01 - Calibration on-going / calibration requested.
00579   //   10 - Calibration FAILED / request to delete calibration.
00580   //   11 - Calibration OK / revert to old calibration if calibration failed and valid values exist
00581   //                         otherwise return to No calibration
00582   //
00583   // See diagram in documentation for details on state transitions. A failed calibration resets the
00584   // values to Atmel factory defaults, but since the values are still in eeprom a reset will load them
00585   // and set calibration_state to calibration OK. A write with Calibration OK will correspondingly restore
00586   // valid calibration values and set state to Calibration OK, or to No calibration if not valid values.
00587   // Note: A write with calibration fail will delete previous calibration values.
00588 
00589   unsigned char state, request;
00590   unsigned int backup_state_req = calibration_state_req;
00591 
00592   state = ((calibration_state & CAL_VREF_MASK) >> CAL_VREF_BIT_POS);
00593   request = ((backup_state_req & CAL_VREF_MASK) >> CAL_VREF_BIT_POS);
00594   switch(request) {
00595   case RUN_CAL:                  // calibration requested
00596     __disable_interrupt();
00597     DisableCellBalancing();
00598     calibration_state &= ~CAL_VREF_MASK; // Clear bits.
00599     calibration_state |=  CAL_VREF_RUN;  // Set state to RUN.
00600     if(CalibrateVREF()) {   // Calibration ok?
00601       calibration_state &= ~CAL_VREF_MASK; // Clear bits.
00602       calibration_state |=  CAL_VREF_OK; // Set state to OK.
00603       __enable_interrupt();
00604     } else {
00605       calibration_state &= ~CAL_VREF_MASK; // Clear bits.
00606       calibration_state |=  CAL_VREF_FAIL; // Set state to FAIL.
00607       __enable_interrupt();
00608     }
00609     EnableCellBalancing();
00610     break;
00611   case CAL_FAIL:             // delete calibration
00612     if (state == NO_CAL) {   // not relevant in state NO_CAL
00613       break;
00614     } else {                 // delete calibration constants
00615       do {} while(EECR & (1<<EEPE));
00616       do {} while(SPMCSR & (1<<SPMEN));
00617       EEAR = EESTORAGE_BGCCR;
00618       EEDR = 0xFF;
00619       EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (0<<EEPE) | (0<<EERE); //arm
00620       EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (1<<EEPE) | (0<<EERE); //go
00621       calibration_state &= ~CAL_VREF_MASK; // Clear bits.
00622       ReadVrefCalibration();
00623    }
00624     break;
00625   case CAL_OK:                 // go to eeprom values if valid values exist
00626     if (state == CAL_FAIL) {   // only valid from CAL_FAIL state
00627       if (ReadVrefCalibration()) {
00628         calibration_state &= ~CAL_VREF_MASK; // Clear bits.
00629         calibration_state |=  CAL_VREF_OK;   // Set state to OK.
00630       } else {
00631         calibration_state &= ~CAL_VREF_MASK; // Clear bits.
00632       }
00633     }
00634     break;
00635   default:
00636     break;
00637   }
00638 
00639 
00640   state = ((calibration_state & CAL_CC_MASK) >> CAL_CC_BIT_POS);
00641   request = ((backup_state_req & CAL_CC_MASK) >> CAL_CC_BIT_POS);
00642   switch(request) {
00643   case RUN_CAL:                // calibration requested
00644     __disable_interrupt();
00645     calibration_state &= ~CAL_CC_MASK;  // Clear bits.
00646     calibration_state |=  CAL_CC_RUN;   // Set state to RUN.
00647     if(CalibrateCCoffset()) {   // Calibration ok?
00648       calibration_state &= ~CAL_CC_MASK; // Clear bits.
00649       calibration_state |=  CAL_CC_OK; // Set state to OK.
00650       __enable_interrupt();
00651     } else {
00652       calibration_state &= ~CAL_CC_MASK; // Clear bits.
00653       calibration_state |=  CAL_CC_FAIL; // Set state to FAIL.
00654       __enable_interrupt();
00655     }
00656     break;
00657   case CAL_FAIL:             // delete calibration
00658     if (state == NO_CAL) {   // not relevant in state NO_CAL
00659       break;
00660     } else {                 // delete calibration valid
00661       do {} while(EECR & (1<<EEPE));
00662       do {} while(SPMCSR & (1<<SPMEN));
00663       EEAR = EESTORAGE_CC_valid;
00664       EEDR = 0xFF;
00665       EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (0<<EEPE) | (0<<EERE); //arm
00666       EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (1<<EEPE) | (0<<EERE); //go
00667       calibration_state &= ~CAL_CC_MASK;   // Clear bits.
00668       ReadCCOffsetCalibration();
00669     }
00670     break;
00671   case CAL_OK:                 // go to eeprom values if valid values exist
00672     if (state == CAL_FAIL) {   // only valid from CAL_FAIL state
00673       if (ReadCCOffsetCalibration()) {
00674         calibration_state &= ~CAL_CC_MASK; // Clear bits.
00675             calibration_state |=  CAL_CC_OK;   // Set state to OK.
00676       } else {
00677         calibration_state &= ~CAL_CC_MASK; // Clear bits.
00678       }
00679     }
00680     break;
00681   default:
00682     break;
00683   }
00684 }
00685 
00686 
00687 
00688 
00689 /*  ASSORTED DOCUMENTATION
00690 
00691 Automatic Cell Balancing
00692 Once per second, a scan is done of all cell voltages.  However, if the cell-balancing
00693 FETs are enabled at this time, they will disrupt the voltage measurements.  To handle
00694 this, the VADC ISR will shut off the balancing FETs during the scan (early enough for
00695 the input RC filters to stabilize to less than 1mV).  At the completion of the cell
00696 voltage scan, if the cells were being balanced the correct balancing FET will be
00697 re-enabled automatically.
00698 
00699 Impedance Measurement
00700 In order to measure a cell's impedance, the cell's voltage must be measured concurrently
00701 with the instantaneous current.  Therefore, a copy of the instantaneous current reading
00702 corresponding to the time when each cell's voltage conversion occurs is stored in the
00703 array cell_current[4].  A mainline routine can then manage this data as appropriate.
00704 Four individual copies are saved in case a CCADC instantaneous interrupt occurs during
00705 a cell voltage reading scan.
00706 
00707 */
00708 
00709 

Generated on Mon Nov 12 15:59:58 2007 for AVR453 Smart Battery Reference Design by  doxygen 1.5.3