- Main Page
- Related Pages
- Data Structures
- Files

# statefunc.c

Go to the documentation of this file.

    00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
    00034 #include <ioavr.h>
    00035 #include <inavr.h>
    00036 #include <stdlib.h>
    00037
    00038 #include "structs.h"
    00039 #include "enums.h"
    00040
    00041 #include "ADC.h"
    00042 #include "statefunc.h"
    00043 #include "battery.h"
    00044 #include "charge.h"
    00045 #include "main.h"
    00046 #include "menu.h"
    00047 #include "OWI.h"
    00048 #include "PWM.h"
    00049 #include "time.h"
    00050 #include "USI.h"
    00051
    00052
    00053 //******************************************************************************
    00054 // Variables
    00055 //******************************************************************************
    00056 unsigned char ErrorFlags;
    00057
    00058
    00061 unsigned char ErrorState;
    00062
    00063
    00064 //******************************************************************************
    00065 // Functions
    00066 //******************************************************************************
    00085 unsigned char Initialize(unsigned char inp)
    00086 {
    00087         unsigned char i, page;
    00088
    00089         // Disable interrupts while setting prescaler.
    00090         __disable_interrupt();
    00091
    00092         CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.
    00093         CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.
    00094
    00095         // Init 1-Wire(R) interface.
    00096         OWI_Init(OWIBUS);
    00097
    00098         // Clear on-chip EEPROM.
    00099         for (page = 0; page < 4; page++)        {
    00100                 for (i = 0; i < 32; i++) {
    00101                         BattEEPROM[page][i] = 0;
    00102                 }
    00103         }
    00104
    00105         DDRB = (1<<PB4) | (1<<PB5);   // Set battery enable pins as outputs.
    00106         DisableBatteries();
    00107         SPI_Init(SPIMODE);
    00108         ADC_Init();
    00109         Time_Init();
    00110
    00111         // Attempt to get ADC-readings (also gets RID-data) from both batteries.
    00112         for (i = 0; i < 2; i++) {
    00113                 EnableBattery(i);
    00114                 ADC_Wait();
    00115                 BatteryStatusRefresh();
    00116         }
    00117
    00118         DisableBatteries();
    00119
    00120         BattActive = 0;               // We have to start somewhere..
    00121         ErrorFlags = 0;
    00122
    00123         // Init complete! Go to ST_BATCON next.
    00124         return(ST_BATCON);
    00125 }
    00126
    00127
    00145 unsigned char BatteryControl(unsigned char inp)
    00146 {
    00147         unsigned char i;
    00148
    00149         // Make sure ADC inputs are configured properly! (Will disables batteries.)
    00150         if (!JumperCheck()) {
    00151                 return(ST_ERROR);           // Error. Exit before damage is done!
    00152         }
    00153
    00154         // If neither battery is valid, flag error and go to error state
    00155         if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {
    00156                 SetErrorFlag(ERR_NO_BATTERIES_ENABLED);
    00157
    00158                 return(ST_ERROR);
    00159         }
    00160
    00161         // Get ADC-readings, try to read EPROM, and start prequalification
    00162         // of any uncharged battery.
    00163         for (i = 0; i < 2; i++) {
    00164                 if (BattControl[i].Enabled) {
    00165                         EnableBattery(i);
    00166                         ADC_Wait();
    00167
    00168                         if (BatteryStatusRefresh()) {
    00169                                 if (!BattData.Charged) {
    00170                                         BatteryDataRefresh();
    00171
    00172                                         return(ST_PREQUAL);
    00173                                 }
    00174                         }
    00175                 }
    00176         }
    00177
    00178         // If we end up here, one or two batteries are found and fully charged.
    00179         // Disconnect, so we don't drain them, and go to sleep.
    00180         DisableBatteries();
    00181
    00182         return(ST_SLEEP);
    00183 }
    00184
    00185
    00192 unsigned char Discharge(unsigned char inp)
    00193 {
    00194         return(ST_BATCON);  // Supply voltage restored, start charging
    00195 }
    00196
    00197
    00208 unsigned char Sleep(unsigned char inp)
    00209 {
    00210         unsigned char i;
    00211
    00212         do {
    00213                 Doze();               // Take a nap (~8 seconds).
    00214
    00215                 // If any batteries need charging, go to ST_BATCON.
    00216                 // Otherwise, keep sleeping.
    00217                 for (i = 0; i < 2; i++) {
    00218                         EnableBattery(i);
    00219                         ADC_Wait();
    00220                         if ((BatteryStatusRefresh()) && (!BattData.Charged)) {
    00221                                 return(ST_BATCON);
    00222                         }
    00223                 }
    00224
    00225                 DisableBatteries();  // Disable both batteries before Doze()!
    00226         } while (TRUE);
    00227 }
    00228
    00229
    00236 void Doze(void)
    00237 {
    00238         // Wait for this ADC cycle to complete, then halt after the next one.
    00239         ADC_Wait();
    00240         ADCS.Halt = TRUE;
    00241         ADCS.Flag = FALSE;
    00242
    00243         do {
    00244         } while (ADCS.Flag == FALSE);
    00245
    00246         WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.
    00247         WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.
    00248         MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.
    00249         __sleep();                              // Go to sleep, wake up by WDT.
    00250
    00251         __watchdog_reset();                     // Clear watchdog reset flag.
    00252         MCUSR &= ~(1<<WDRF);
    00253         WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.
    00254         WDTCR = 0;                              // Turn off watchdog.
    00255
    00256         ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.
    00257         ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.
    00258
    00259         // Wait for this cycle to complete.
    00260         ADC_Wait();
    00261 }
    00262
    00263
    00286 unsigned char Error(unsigned char inp)
    00287         {
    00288         unsigned char i;
    00289
    00290         PWM_Stop();           // Stop charging.
    00291         DisableBatteries();   // Disable all loads.
    00292
    00293         do {
    00294                 Doze();           // Take a nap.
    00295
    00296                 // For each bit in ErrorFlags, starting with LSB, handle
    00297                 // associated error, if the flag is set.
    00298                 for (i = 0x01; i!=0; i<<=1) {
    00299                         if(i & ErrorFlags) {
    00300                                 switch (i) {
    00301
    00302                                 case  ERR_JUMPER_MISMATCH:
    00303                                         // Clear flag & recheck.
    00304                                         ErrorFlags &= ~i;
    00305                                         JumperCheck();
    00306                                 break;
    00307
    00308
    00309                                 case  ERR_NO_BATTERIES_ENABLED:
    00310                                         // Clear if any battery gets enabled.
    00311                                         if ((BattControl[0].Enabled) || (BattControl[1].Enabled)) {
    00312                                                         ErrorFlags &= ~i;
    00313                                         }
    00314                                 break;
    00315
    00316
    00317                                 case  ERR_PWM_CONTROL:
    00318                                         // Clear flag.
    00319                                         ErrorFlags &= ~i;
    00320                                 break;
    00321
    00322
    00323                                 case  ERR_BATTERY_TEMPERATURE:
    00324                                         // Clear flag.
    00325                                         ErrorFlags &= ~i;
    00326                                 break;
    00327
    00328
    00329                                 case  ERR_BATTERY_EXHAUSTED:
    00330                                         // Try the other battery.
    00331                                         BattData.Exhausted = FALSE;
    00332                                         BattActive = (BattActive + 1) % 2;
    00333                                         ErrorFlags &= ~i;
    00334                                 break;
    00335
    00336
    00337                                 default:
    00338                                 break;
    00339                                 }
    00340                         }
    00341                 }
    00342         } while (ErrorFlags);
    00343
    00344         return(ST_INIT);
    00345 }
    00346
    00347
    00356 void SetErrorFlag(unsigned char Flag)
    00357 {
    00358         ErrorFlags |= Flag;
    00359         ErrorState = CurrentState;
    00360 }
    00361
    00362
    00374 unsigned char JumperCheck(void)
    00375 {
    00376          DisableBatteries();       // Disconnect, or loads may be destroyed!
    00377
    00378          PWM_Start();              // Start PWM (controls the buck charger).
    00379
    00380          // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.
    00381          Time_Set(TIMER_GEN,0,1,0);
    00382
    00383         do {
    00384                 // If the PWM output voltage saturates the ADC, stop PWM output and
    00385                 // report a failure.
    00386                 if (ADCS.rawVBAT == 1023) {
    00387                         PWM_Stop();
    00388                         return(FALSE);
    00389                 }
    00390
    00391                 // If the absolute difference between measured (VIN - VBAT) and the
    00392                 // typical value are below our set maximum, everything is OK.
    00393                 if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <
    00394                                      VIN_VBAT_DIFF_MAX ) {
    00395
    00396                         PWM_Stop();
    00397                         return(TRUE);
    00398                 }
    00399
    00400                 // Charge current is too high -> check load and jumper J405 and J406.
    00401                 if (abs(ADCS.IBAT) > 100) {
    00402                         PWM_Stop();
    00403                         return(FALSE);
    00404                 }
    00405
    00406                 // If the PWM output can't be increased high enough -> check jumpers
    00407                 // J400-J404, J407 and J408.
    00408                 if (!PWM_IncrementDutyCycle()) {
    00409                         PWM_Stop();
    00410                         return(FALSE);
    00411                 }
    00412
    00413       // Wait for ADC conversions to complete
    00414                 ADC_Wait();
    00415         } while (Time_Left(TIMER_GEN));
    00416
    00417
    00418         // If we end up here, the measurements took too long.
    00419         PWM_Stop();
    00420         return(FALSE);
    00421 }