00001
00025
00026 #include <iom406.h>
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
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();
00059
00062
00063
00064
00065
00066 PinInit();
00067 T0init();
00068 T1init();
00069 PBinit();
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
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)
00094 {
00095 if(CheckCalibRequest)
00096 {
00097 ClrCalibRequest;
00098 DoCalibrate();
00099 }
00100
00101 if(CheckADCScanDone)
00102 {
00103 ClrADCScanDone;
00104
00105
00106 CalculateADCresults();
00107 BalanceCheck();
00108 ChargeCheck();
00109 ThermalCheck();
00110 AlarmModeDisabledCheck();
00111 AlarmConditionsCheck();
00112 MasterSMBusCheck(0);
00113 }
00114
00115 if(CheckQtrSec)
00116 {
00117 ClrQtrSec;
00118 SetGenericTimer(OneQtrSecond, 244);
00119
00120 WdogMgr();
00121
00122
00123 if(Timer32KHz)
00124 {
00125 if(--Timer32KHz == 0)
00126 CCSR = ((1<<XOE)|(1<<ACS));
00127 }
00128
00129 if(++qtrsectick >= 4)
00130 {
00131 qtrsectick = 0;
00132 ThermistorSelect++;
00133 ThermistorSelect &= 0x03;
00134 StartAdc(ThermistorSelect);
00135 }
00136 }
00137
00138 if(CheckAlarmMode)
00139 {
00140 ClrAlarmMode;
00141 AlarmModeDisabledTimer = 0;
00142 }
00143
00144 if(CheckMasterSMBdone)
00145 {
00146 ClrMasterSMBdone;
00147 SMBvariables[SMBV_BattStatus][lobyte] &= ~(0x0F);
00148 MasterSMBusCheck(1);
00149 }
00150 }
00151 else
00152 {
00153 if(!GetGenericTimer(OneQtrSecond))
00154 SetGenericTimer(OneQtrSecond, 244);
00155 }
00156
00157 SMB_CmdInterpreter();
00158 Check50uS();
00159 SetLEDs(LEDs);
00160
00161
00162
00163 }
00164 }
00165
00166
00167
00168
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
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)
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
00223
00224
00225 if(delta > MAX_IMBALANCE)
00226 {
00227 CellToBalance = maxcell;
00228 EnableCellBalancing();
00229 }
00230 else
00231 {
00232 CellToBalance = 0;
00233 DisableCellBalancing();
00234 }
00235 }
00236
00237
00238
00239
00240
00241
00242
00243 void ChargeCheck(void)
00244 {
00245 signed int cell = (signed int) ReadCell(1);
00246 unsigned char charge_percent;
00247
00248
00249 if(cell >= CELL_NOMINALV)
00250 {
00251 if(SMBvariables[SMBV_BattStatus][lobyte] & FULLY_CHARGED)
00252 {
00253 if(Current1Sec() < 0)
00254 {
00255 SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
00256 FCSR = (1<<DFE) | (1<<CFE);
00257 }
00258 else
00259 {
00260 if((cell >= CELL_TOOMUCHV) && (Current1Sec() > 0))
00261 {
00262 FCSR = (1<<DFE) | (1<<PFD);
00263 }
00264 }
00265 }
00266 else
00267 {
00268 FullChargeReached();
00269 SMBvariables[SMBV_BattStatus][lobyte] |= FULLY_CHARGED;
00270
00271 if(Current1Sec() > 0)
00272 {
00273 SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_CHARGE_ALARM;
00274 SMBvariables[SMBV_BattStatus][hibyte] |= OVER_CHARGED_ALARM;
00275 }
00276 }
00277 return;
00278 }
00279 else
00280 if(cell <= CELL_MINV)
00281 {
00282 if(SMBvariables[SMBV_BattStatus][lobyte] & FULLY_DISCHARGED)
00283 {
00284 if(Current1Sec() > 0)
00285 {
00286 SMBvariables[SMBV_BattStatus][lobyte] &= ~DISCHARGING;
00287 FCSR = (1<<DFE) | (1<<CFE);
00288 }
00289 else
00290 {
00291 if((cell <= CELL_TOOLITTLEV) && (Current1Sec() < 0))
00292 {
00293 FCSR = 0;
00294 SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_DISCHARGE_ALARM;
00295 SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
00296 }
00297 }
00298 }
00299 else
00300 {
00301 FullDischargeReached();
00302 SMBvariables[SMBV_BattStatus][lobyte] |= FULLY_DISCHARGED;
00303 SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_DISCHARGE_ALARM;
00304 }
00305 return;
00306 }
00307 else
00308 {
00309 FCSR |= (1<<DFE) | (1<<CFE) | (1<<PFD);
00310 }
00311
00312
00313 charge_percent = RelativeSOC();
00314 cell = Current1Sec();
00315 if(cell <= 0)
00316 {
00317 cell = -cell;
00318
00319
00320 SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
00321
00322
00323 SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_CHARGE_ALARM;
00324
00325
00326 if(charge_percent < 99)
00327 SMBvariables[SMBV_BattStatus][lobyte] &= ~FULLY_CHARGED;
00328
00329
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
00336
00337
00338
00339
00340 }
00341 else
00342 {
00343
00344 SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_DISCHARGE_ALARM;
00345
00346
00347 SMBvariables[SMBV_BattStatus][lobyte] &= ~DISCHARGING;
00348
00349
00350 if( (SMBvariables[SMBV_BattStatus][lobyte] & FULLY_DISCHARGED) &&
00351 (charge_percent > 20) )
00352 SMBvariables[SMBV_BattStatus][lobyte] &= ~FULLY_DISCHARGED;
00353
00354 if(cell == 0)
00355 {
00356 SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_CHARGE_ALARM;
00357 SMBvariables[SMBV_BattStatus][hibyte] &= ~OVER_CHARGED_ALARM;
00358 }
00359 else
00360 {
00361
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
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
00379
00380 }
00381
00382
00383
00384 void ThermalCheck(void)
00385 {
00386 unsigned int temp = GetTemperature();
00387
00388
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
00395 if(temp > MAX_ONCHIP_TEMP)
00396 DoShutdown(SHUTDOWN_REASON_OVERTEMPERATURE);
00397
00398
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422 }
00423
00424
00425
00426
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;
00434 }
00435 }
00436 }
00437
00438
00439
00440 void AlarmConditionsCheck(void)
00441 {
00442
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
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)
00466 {
00467 static unsigned char timer = 0;
00468
00469
00470
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
00487 if(SMBvariables[SMBV_BattStatus][hibyte])
00488 {
00489 if(SMBvariables[SMBV_BattStatus][hibyte] & ~(REMAINING_CAPACITY_ALARM | REMAINING_TIME_ALARM))
00490 {
00491 MasterInsertMsg(CHARGER_ADDR, SMB_M_CMD_ALARMWARNING, SMBvar_int[SMBV_BattStatus]);
00492 }
00493
00494 MasterInsertMsg(HOST_ADDR, SMB_M_CMD_ALARMWARNING, SMBvar_int[SMBV_BattStatus]);
00495 }
00496
00497
00500
00501 if(!(SMBvariables[SMBV_BattMode][hibyte] & CHARGER_MODE))
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)) {
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 {
00512 SMBvar_int[SMBV_ChgCurrent] = 0x0000;
00513 SMBvar_int[SMBV_ChgVoltage] = 0x0000;
00514 }
00515 }
00516
00517
00518 timer = 0;
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
00538
00539
00540
00541
00542 SMCR &= ~(1<<SE);
00543 return;
00544 }
00545
00546
00547
00548 void WdogMgr(void)
00549 {
00551
00552
00553 __watchdog_reset();
00554
00555 return;
00556 }
00557
00558
00559
00560 void DoCalibrate(void)
00561 {
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
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:
00596 __disable_interrupt();
00597 DisableCellBalancing();
00598 calibration_state &= ~CAL_VREF_MASK;
00599 calibration_state |= CAL_VREF_RUN;
00600 if(CalibrateVREF()) {
00601 calibration_state &= ~CAL_VREF_MASK;
00602 calibration_state |= CAL_VREF_OK;
00603 __enable_interrupt();
00604 } else {
00605 calibration_state &= ~CAL_VREF_MASK;
00606 calibration_state |= CAL_VREF_FAIL;
00607 __enable_interrupt();
00608 }
00609 EnableCellBalancing();
00610 break;
00611 case CAL_FAIL:
00612 if (state == NO_CAL) {
00613 break;
00614 } else {
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);
00620 EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (1<<EEPE) | (0<<EERE);
00621 calibration_state &= ~CAL_VREF_MASK;
00622 ReadVrefCalibration();
00623 }
00624 break;
00625 case CAL_OK:
00626 if (state == CAL_FAIL) {
00627 if (ReadVrefCalibration()) {
00628 calibration_state &= ~CAL_VREF_MASK;
00629 calibration_state |= CAL_VREF_OK;
00630 } else {
00631 calibration_state &= ~CAL_VREF_MASK;
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:
00644 __disable_interrupt();
00645 calibration_state &= ~CAL_CC_MASK;
00646 calibration_state |= CAL_CC_RUN;
00647 if(CalibrateCCoffset()) {
00648 calibration_state &= ~CAL_CC_MASK;
00649 calibration_state |= CAL_CC_OK;
00650 __enable_interrupt();
00651 } else {
00652 calibration_state &= ~CAL_CC_MASK;
00653 calibration_state |= CAL_CC_FAIL;
00654 __enable_interrupt();
00655 }
00656 break;
00657 case CAL_FAIL:
00658 if (state == NO_CAL) {
00659 break;
00660 } else {
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);
00666 EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (1<<EEPE) | (0<<EERE);
00667 calibration_state &= ~CAL_CC_MASK;
00668 ReadCCOffsetCalibration();
00669 }
00670 break;
00671 case CAL_OK:
00672 if (state == CAL_FAIL) {
00673 if (ReadCCOffsetCalibration()) {
00674 calibration_state &= ~CAL_CC_MASK;
00675 calibration_state |= CAL_CC_OK;
00676 } else {
00677 calibration_state &= ~CAL_CC_MASK;
00678 }
00679 }
00680 break;
00681 default:
00682 break;
00683 }
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709