4008-04-07 Release
[avr_bc100.git] / BaseTinyFirmware / IAR / statefunc.c
index e34994f7d704e268184cd4910af2e0d2dbd9fc16..9dbdde18c4cf8c6bcc5a93b03471ea840d4f048d 100644 (file)
  *      AVR463: Charging NiMH Batteries with BC100\r
  *\r
  * \par Documentation\r
- *      For comprehensive code documentation, supported compilers, compiler \r
+ *      For comprehensive code documentation, supported compilers, compiler\r
  *      settings and supported devices see readme.html\r
  *\r
  * \author\r
  *      Atmel Corporation: http://www.atmel.com \n\r
  *      Support email: avr@atmel.com\r
  *\r
- * \r
+ *\r
  * $Name$\r
  * $Revision: 2299 $\r
  * $RCSfile$\r
@@ -60,6 +60,9 @@ unsigned char ErrorFlags;  //!< \brief Holds error flags.
 //! \note See menu.h for definitions of states.\r
 unsigned char ErrorState;\r
 \r
+//! \brief Set to 1 by the watchdog-timeout-ISR\r
+//! \note added by Martin Thomas\r
+volatile unsigned char WatchdogFlag;\r
 \r
 //******************************************************************************\r
 // Functions\r
@@ -88,17 +91,20 @@ unsigned char Initialize(unsigned char inp)
 \r
        // Disable interrupts while setting prescaler.\r
        __disable_interrupt();\r
-       \r
+\r
        CLKPR = (1<<CLKPCE);          // Enable CLKPS bit modification.\r
        CLKPR = 0;                    // Set prescaler 1 => 8 MHz clock frequency.\r
-       \r
+\r
        // Init 1-Wire(R) interface.\r
        OWI_Init(OWIBUS);\r
-       \r
+\r
        // Clear on-chip EEPROM.\r
-       for (page = 0; page < 4; page++)        {\r
+       for (page = 0; page < 4; page++) {\r
                for (i = 0; i < 32; i++) {\r
-                       BattEEPROM[page][i] = 0;\r
+                       // From mthomas GCC addition\r
+                       if (BattEEPROM[page][i] != 0) {\r
+                               BattEEPROM[page][i] = 0;\r
+                       }\r
                }\r
        }\r
 \r
@@ -114,12 +120,12 @@ unsigned char Initialize(unsigned char inp)
                ADC_Wait();\r
                BatteryStatusRefresh();\r
        }\r
-    \r
+\r
        DisableBatteries();\r
-       \r
+\r
        BattActive = 0;               // We have to start somewhere..\r
        ErrorFlags = 0;\r
-       \r
+\r
        // Init complete! Go to ST_BATCON next.\r
        return(ST_BATCON);\r
 }\r
@@ -145,23 +151,23 @@ unsigned char Initialize(unsigned char inp)
 unsigned char BatteryControl(unsigned char inp)\r
 {\r
        unsigned char i;\r
-       \r
+\r
        // Make sure ADC inputs are configured properly! (Will disables batteries.)\r
        if (!JumperCheck()) {\r
                return(ST_ERROR);           // Error. Exit before damage is done!\r
        }\r
-       \r
+\r
        // If neither battery is valid, flag error and go to error state\r
        if ((!BattControl[0].Enabled) && (!BattControl[1].Enabled)) {\r
                SetErrorFlag(ERR_NO_BATTERIES_ENABLED);\r
-               \r
+\r
                return(ST_ERROR);\r
        }\r
 \r
        // Get ADC-readings, try to read EPROM, and start prequalification\r
        // of any uncharged battery.\r
        for (i = 0; i < 2; i++) {\r
-               if (BattControl[i].Enabled) {      \r
+               if (BattControl[i].Enabled) {\r
                        EnableBattery(i);\r
                        ADC_Wait();\r
 \r
@@ -169,7 +175,7 @@ unsigned char BatteryControl(unsigned char inp)
                                if (!BattData.Charged) {\r
                                        BatteryDataRefresh();\r
 \r
-                                       return(ST_PREQUAL);       \r
+                                       return(ST_PREQUAL);\r
                                }\r
                        }\r
                }\r
@@ -221,43 +227,73 @@ unsigned char Sleep(unsigned char inp)
                                return(ST_BATCON);\r
                        }\r
                }\r
-               \r
+\r
                DisableBatteries();  // Disable both batteries before Doze()!\r
        } while (TRUE);\r
 }\r
 \r
+/*! \brief Watchdog interrupt-service-routine\r
+ *\r
+ * Called on watchdog timeout, added by Martin Thomas\r
+ */\r
+#pragma vector = WDT_vect\r
+__interrupt void WDT_ISR(void)\r
+{\r
+       WatchdogFlag = 1;\r
+}\r
+\r
 \r
 /*! \brief Doze off for approx. 8 seconds (Vcc = 5 V)\r
  *\r
  * Waits for ADC-cycles to complete, disables the ADC, then sleeps for\r
  * approx. 8 seconds (Vcc = 5 V) using the watchdog timer.\r
  * On wakeup, ADC is re-enabled.\r
+ * Modification by Martin Thomas:\r
+ *  Do not enter standby mode if PB6 is low (MASTER_INT on BC100)\r
+ *  so SPI communication with the master-controller is still possible\r
+ *  during "doze".\r
  */\r
 void Doze(void)\r
 {\r
+       uint8_t sreg_saved;\r
        // Wait for this ADC cycle to complete, then halt after the next one.\r
        ADC_Wait();\r
        ADCS.Halt = TRUE;\r
        ADCS.Flag = FALSE;\r
-       \r
+\r
        do {\r
-       } while (ADCS.Flag == FALSE);    \r
-       \r
+       } while (ADCS.Flag == FALSE);\r
+\r
        WDTCR = (1<<WDP3)|(1<<WDP0);            // 8.0 seconds at 5 volts VCC.\r
        WDTCR |= (1<<WDIF)|(1<<WDIE)|(1<<WDE);  // Clear flag and enable watchdog.\r
-       MCUCR |= (1<<SE) | (1<<SM1)|(1<<SM0);   // Sleep enable, mode = standby.\r
-       __sleep();                              // Go to sleep, wake up by WDT.\r
-       \r
+\r
+       DDRB  &= ~(1<<PB6);   // MASTER_INT as input\r
+       PORTB |= (1<<PB6);    // enabled internal pullup\r
+       WatchdogFlag = 0;\r
+       if ( PINB & (1<<PB6) ) {\r
+               MCUCR |= (1<<SE) | (1<<SM1) | (1<<SM0); // Sleep enable, mode = standby.\r
+               __sleep();                              // Go to sleep, wake up by WDT.\r
+       }\r
+       else {\r
+               do {\r
+               } while ( !(WatchdogFlag) );\r
+       }\r
+\r
        __watchdog_reset();                     // Clear watchdog reset flag.\r
-       MCUSR &= ~(1<<WDRF);          \r
+       PORTB &= ~(1<<PB6);    // disabled internal pullup\r
+       MCUSR &= ~(1<<WDRF);\r
+\r
+       sreg_saved = SREG;\r
+       cli();\r
        WDTCR |= (1<<WDCE)|(1<<WDE);            // Watchdog change enable.\r
        WDTCR = 0;                              // Turn off watchdog.\r
-       \r
+       SREG = sreg_saved;\r
+\r
        ADCS.Halt = FALSE;                      // Enable consecutive runs of ADC.\r
        ADCSRA |= (1<<ADEN)|(1<<ADSC);          // Enable ADC & start conversion.\r
-       \r
+\r
        // Wait for this cycle to complete.\r
-       ADC_Wait();                             \r
+       ADC_Wait();\r
 }\r
 \r
 \r
@@ -286,10 +322,10 @@ void Doze(void)
 unsigned char Error(unsigned char inp)\r
        {\r
        unsigned char i;\r
-       \r
+\r
        PWM_Stop();           // Stop charging.\r
        DisableBatteries();   // Disable all loads.\r
-       \r
+\r
        do {\r
                Doze();           // Take a nap.\r
 \r
@@ -298,7 +334,7 @@ unsigned char Error(unsigned char inp)
                for (i = 0x01; i!=0; i<<=1) {\r
                        if(i & ErrorFlags) {\r
                                switch (i) {\r
-                               \r
+\r
                                case  ERR_JUMPER_MISMATCH:\r
                                        // Clear flag & recheck.\r
                                        ErrorFlags &= ~i;\r
@@ -333,7 +369,7 @@ unsigned char Error(unsigned char inp)
                                        ErrorFlags &= ~i;\r
                                break;\r
 \r
-                                       \r
+\r
                                default:\r
                                break;\r
                                }\r
@@ -374,12 +410,12 @@ void SetErrorFlag(unsigned char Flag)
 unsigned char JumperCheck(void)\r
 {\r
         DisableBatteries();       // Disconnect, or loads may be destroyed!\r
-        \r
+\r
         PWM_Start();              // Start PWM (controls the buck charger).\r
-       \r
+\r
         // Use general timer: shouldn't take longer than (6 x 255) / 2500 ~= 0.62s.\r
         Time_Set(TIMER_GEN,0,1,0);\r
-       \r
+\r
        do {\r
                // If the PWM output voltage saturates the ADC, stop PWM output and\r
                // report a failure.\r
@@ -392,7 +428,7 @@ unsigned char JumperCheck(void)
                // typical value are below our set maximum, everything is OK.\r
                if (abs((signed int)(ADCS.VIN - VIN_VBAT_DIFF_TYP - ADCS.VBAT)) <\r
                                     VIN_VBAT_DIFF_MAX ) {\r
-                                \r
+\r
                        PWM_Stop();\r
                        return(TRUE);\r
                }\r
@@ -409,11 +445,11 @@ unsigned char JumperCheck(void)
                        PWM_Stop();\r
                        return(FALSE);\r
                }\r
-               \r
+\r
       // Wait for ADC conversions to complete\r
                ADC_Wait();\r
        } while (Time_Left(TIMER_GEN));\r
-       \r
+\r
 \r
        // If we end up here, the measurements took too long.\r
        PWM_Stop();\r