|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542 |
- /*******************************************************************************
- * LowPower Library
- * Version: 1.20
- * Date: 16-12-2011
- * Company: Rocket Scream Electronics
- * Website: www.rocketscream.com
- *
- * This is a lightweight low power library for Arduino. Please check our wiki
- * (www.rocketscream.com/wiki) for more information on using this piece of
- * library.
- *
- * This library is licensed under Creative Commons Attribution-ShareAlike 3.0
- * Unported License.
- *
- * Revision Description
- * ======== ===========
- * 1.20 Remove typo error in idle method for checking whether Timer 0 was
- * turned off.
- * Remove dependecy on WProgram.h which is not required.
- * Tested to work with Arduino IDE 1.0.
- * 1.10 Added #ifndef for sleep_bod_disable() for compatibility with future
- * Arduino IDE release.
- * 1.00 Initial public release.
- *******************************************************************************/
- #include <avr/sleep.h>
- #include <avr/wdt.h>
- #include <avr/power.h>
- #include <avr/interrupt.h>
- #include "LowPower.h"
-
- #ifndef sleep_bod_disable
- #define sleep_bod_disable() \
- do { \
- unsigned char tempreg; \
- __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
- "ori %[tempreg], %[bods_bodse]" "\n\t" \
- "out %[mcucr], %[tempreg]" "\n\t" \
- "andi %[tempreg], %[not_bodse]" "\n\t" \
- "out %[mcucr], %[tempreg]" \
- : [tempreg] "=&d" (tempreg) \
- : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
- [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
- [not_bodse] "i" (~_BV(BODSE))); \
- } while (0)
- #endif
-
- #define lowPowerBodOn(mode) \
- do { \
- set_sleep_mode(mode); \
- cli(); \
- sleep_enable(); \
- sei(); \
- sleep_cpu(); \
- sleep_disable(); \
- sei(); \
- } while (0);
-
- #define lowPowerBodOff(mode)\
- do { \
- set_sleep_mode(mode); \
- cli(); \
- sleep_enable(); \
- sleep_bod_disable(); \
- sei(); \
- sleep_cpu(); \
- sleep_disable(); \
- sei(); \
- } while (0);
-
- /*******************************************************************************
- * Name: idle
- * Description: Putting microcontroller into idle state. Please make sure you
- * understand the implication and result of disabling module.
- *
- * Argument Description
- * ========= ===========
- * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
- * up resource:
- * (a) SLEEP_15MS - 15 ms sleep
- * (b) SLEEP_30MS - 30 ms sleep
- * (c) SLEEP_60MS - 60 ms sleep
- * (d) SLEEP_120MS - 120 ms sleep
- * (e) SLEEP_250MS - 250 ms sleep
- * (f) SLEEP_500MS - 500 ms sleep
- * (g) SLEEP_1S - 1 s sleep
- * (h) SLEEP_2S - 2 s sleep
- * (i) SLEEP_4S - 4 s sleep
- * (j) SLEEP_1S - 8 s sleep
- * (k) SLEEP_FOREVER - Sleep without waking up through WDT
- *
- * 2. adc ADC module disable control:
- * (a) ADC_OFF - Turn off ADC module
- * (b) ADC_ON - Leave ADC module in its default state
- *
- * 3. timer2 Timer 2 module disable control:
- * (a) TIMER2_OFF - Turn off Timer 2 module
- * (b) TIMER2_ON - Leave Timer 2 module in its default state
- *
- * 4. timer1 Timer 1 module disable control:
- * (a) TIMER1_OFF - Turn off Timer 1 module
- * (b) TIMER1_ON - Leave Timer 1 module in its default state
- *
- * 5. timer0 Timer 0 module disable control:
- * (a) TIMER0_OFF - Turn off Timer 0 module
- * (b) TIMER0_ON - Leave Timer 0 module in its default state
- *
- * 6. spi SPI module disable control:
- * (a) ADC_OFF - Turn off ADC module
- * (b) ADC_ON - Leave ADC module in its default state
- *
- * 7. usart0 USART0 module disable control:
- * (a) USART0_OFF - Turn off USART0 module
- * (b) USART0_ON - Leave USART0 module in its default state
- *
- * 8. twi TWI module disable control:
- * (a) TWI_OFF - Turn off TWI module
- * (b) TWI_ON - Leave TWI module in its default state
- *
- *******************************************************************************/
- void LowPowerClass::idle(period_t period, adc_t adc, timer2_t timer2,
- timer1_t timer1, timer0_t timer0,
- spi_t spi, usart0_t usart0, twi_t twi)
- {
- // Temporary clock source variable
- unsigned char clockSource = 0;
-
- if (timer2 == TIMER2_OFF)
- {
- if (TCCR2B & CS22) clockSource |= (1 << CS22);
- if (TCCR2B & CS21) clockSource |= (1 << CS21);
- if (TCCR2B & CS20) clockSource |= (1 << CS20);
-
- // Remove the clock source to shutdown Timer2
- TCCR2B &= ~(1 << CS22);
- TCCR2B &= ~(1 << CS21);
- TCCR2B &= ~(1 << CS20);
-
- power_timer2_disable();
- }
-
- if (adc == ADC_OFF)
- {
- ADCSRA &= ~(1 << ADEN);
- power_adc_disable();
- }
-
- if (timer1 == TIMER1_OFF) power_timer1_disable();
- if (timer0 == TIMER0_OFF) power_timer0_disable();
- if (spi == SPI_OFF) power_spi_disable();
- if (usart0 == USART0_OFF) power_usart0_disable();
- if (twi == TWI_OFF) power_twi_disable();
-
- if (period != SLEEP_FOREVER)
- {
- wdt_enable(period);
- WDTCSR |= (1 << WDIE);
- }
-
- lowPowerBodOn(SLEEP_MODE_IDLE);
-
- if (adc == ADC_OFF)
- {
- power_adc_enable();
- ADCSRA |= (1 << ADEN);
- }
-
- if (timer2 == TIMER2_OFF)
- {
- if (clockSource & CS22) TCCR2B |= (1 << CS22);
- if (clockSource & CS21) TCCR2B |= (1 << CS21);
- if (clockSource & CS20) TCCR2B |= (1 << CS20);
-
- power_timer2_enable();
- }
-
- if (timer1 == TIMER1_OFF) power_timer1_enable();
- if (timer0 == TIMER0_OFF) power_timer0_enable();
- if (spi == SPI_OFF) power_spi_enable();
- if (usart0 == USART0_OFF) power_usart0_enable();
- if (twi == TWI_OFF) power_twi_enable();
- }
-
- /*******************************************************************************
- * Name: adcNoiseReduction
- * Description: Putting microcontroller into ADC noise reduction state. This is
- * a very useful state when using the ADC to achieve best and low
- * noise signal.
- *
- * Argument Description
- * ========= ===========
- * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
- * up resource:
- * (a) SLEEP_15MS - 15 ms sleep
- * (b) SLEEP_30MS - 30 ms sleep
- * (c) SLEEP_60MS - 60 ms sleep
- * (d) SLEEP_120MS - 120 ms sleep
- * (e) SLEEP_250MS - 250 ms sleep
- * (f) SLEEP_500MS - 500 ms sleep
- * (g) SLEEP_1S - 1 s sleep
- * (h) SLEEP_2S - 2 s sleep
- * (i) SLEEP_4S - 4 s sleep
- * (j) SLEEP_1S - 8 s sleep
- * (k) SLEEP_FOREVER - Sleep without waking up through WDT
- *
- * 2. adc ADC module disable control. Turning off the ADC module is
- * basically removing the purpose of this low power mode.
- * (a) ADC_OFF - Turn off ADC module
- * (b) ADC_ON - Leave ADC module in its default state
- *
- * 3. timer2 Timer 2 module disable control:
- * (a) TIMER2_OFF - Turn off Timer 2 module
- * (b) TIMER2_ON - Leave Timer 2 module in its default state
- *
- *******************************************************************************/
- void LowPowerClass::adcNoiseReduction(period_t period, adc_t adc,
- timer2_t timer2)
- {
- // Temporary clock source variable
- unsigned char clockSource = 0;
-
- if (timer2 == TIMER2_OFF)
- {
- if (TCCR2B & CS22) clockSource |= (1 << CS22);
- if (TCCR2B & CS21) clockSource |= (1 << CS21);
- if (TCCR2B & CS20) clockSource |= (1 << CS20);
-
- // Remove the clock source to shutdown Timer2
- TCCR2B &= ~(1 << CS22);
- TCCR2B &= ~(1 << CS21);
- TCCR2B &= ~(1 << CS20);
- }
-
- if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
-
- if (period != SLEEP_FOREVER)
- {
- wdt_enable(period);
- WDTCSR |= (1 << WDIE);
- }
-
- lowPowerBodOn(SLEEP_MODE_ADC);
-
- if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
-
- if (timer2 == TIMER2_OFF)
- {
- if (clockSource & CS22) TCCR2B |= (1 << CS22);
- if (clockSource & CS21) TCCR2B |= (1 << CS21);
- if (clockSource & CS20) TCCR2B |= (1 << CS20);
-
- }
- }
-
- /*******************************************************************************
- * Name: powerDown
- * Description: Putting microcontroller into power down state. This is
- * the lowest current consumption state. Use this together with
- * external pin interrupt to wake up through external event
- * triggering (example: RTC clockout pin, SD card detect pin).
- *
- * Argument Description
- * ========= ===========
- * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
- * up resource:
- * (a) SLEEP_15MS - 15 ms sleep
- * (b) SLEEP_30MS - 30 ms sleep
- * (c) SLEEP_60MS - 60 ms sleep
- * (d) SLEEP_120MS - 120 ms sleep
- * (e) SLEEP_250MS - 250 ms sleep
- * (f) SLEEP_500MS - 500 ms sleep
- * (g) SLEEP_1S - 1 s sleep
- * (h) SLEEP_2S - 2 s sleep
- * (i) SLEEP_4S - 4 s sleep
- * (j) SLEEP_1S - 8 s sleep
- * (k) SLEEP_FOREVER - Sleep without waking up through WDT
- *
- * 2. adc ADC module disable control. Turning off the ADC module is
- * basically removing the purpose of this low power mode.
- * (a) ADC_OFF - Turn off ADC module
- * (b) ADC_ON - Leave ADC module in its default state
- *
- * 3. bod Brown Out Detector (BOD) module disable control:
- * (a) BOD_OFF - Turn off BOD module
- * (b) BOD_ON - Leave BOD module in its default state
- *
- *******************************************************************************/
- void LowPowerClass::powerDown(period_t period, adc_t adc, bod_t bod)
- {
- if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
-
- if (period != SLEEP_FOREVER)
- {
- wdt_enable(period);
- WDTCSR |= (1 << WDIE);
- }
- if (bod == BOD_OFF)
- {
- lowPowerBodOff(SLEEP_MODE_PWR_DOWN);
- }
- else
- {
- lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
- }
-
- if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
- }
-
- /*******************************************************************************
- * Name: powerSave
- * Description: Putting microcontroller into power save state. This is
- * the lowest current consumption state after power down.
- * Use this state together with an external 32.768 kHz crystal (but
- * 8/16 MHz crystal/resonator need to be removed) to provide an
- * asynchronous clock source to Timer 2. Please take note that
- * Timer 2 is also used by the Arduino core for PWM operation.
- * Please refer to wiring.c for explanation. Removal of the external
- * 8/16 MHz crystal/resonator requires the microcontroller to run
- * on its internal RC oscillator which is not so accurate for time
- * critical operation.
- *
- * Argument Description
- * ========= ===========
- * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
- * up resource:
- * (a) SLEEP_15MS - 15 ms sleep
- * (b) SLEEP_30MS - 30 ms sleep
- * (c) SLEEP_60MS - 60 ms sleep
- * (d) SLEEP_120MS - 120 ms sleep
- * (e) SLEEP_250MS - 250 ms sleep
- * (f) SLEEP_500MS - 500 ms sleep
- * (g) SLEEP_1S - 1 s sleep
- * (h) SLEEP_2S - 2 s sleep
- * (i) SLEEP_4S - 4 s sleep
- * (j) SLEEP_1S - 8 s sleep
- * (k) SLEEP_FOREVER - Sleep without waking up through WDT
- *
- * 2. adc ADC module disable control. Turning off the ADC module is
- * basically removing the purpose of this low power mode.
- * (a) ADC_OFF - Turn off ADC module
- * (b) ADC_ON - Leave ADC module in its default state
- *
- * 3. bod Brown Out Detector (BOD) module disable control:
- * (a) BOD_OFF - Turn off BOD module
- * (b) BOD_ON - Leave BOD module in its default state
- *
- * 4. timer2 Timer 2 module disable control:
- * (a) TIMER2_OFF - Turn off Timer 2 module
- * (b) TIMER2_ON - Leave Timer 2 module in its default state
- *
- *******************************************************************************/
- void LowPowerClass::powerSave(period_t period, adc_t adc, bod_t bod,
- timer2_t timer2)
- {
- // Temporary clock source variable
- unsigned char clockSource = 0;
-
- if (timer2 == TIMER2_OFF)
- {
- if (TCCR2B & CS22) clockSource |= (1 << CS22);
- if (TCCR2B & CS21) clockSource |= (1 << CS21);
- if (TCCR2B & CS20) clockSource |= (1 << CS20);
-
- // Remove the clock source to shutdown Timer2
- TCCR2B &= ~(1 << CS22);
- TCCR2B &= ~(1 << CS21);
- TCCR2B &= ~(1 << CS20);
- }
-
- if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
-
- if (period != SLEEP_FOREVER)
- {
- wdt_enable(period);
- WDTCSR |= (1 << WDIE);
- }
-
- if (bod == BOD_OFF)
- {
- lowPowerBodOff(SLEEP_MODE_PWR_SAVE);
- }
- else
- {
- lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
- }
-
- if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
-
- if (timer2 == TIMER2_OFF)
- {
- if (clockSource & CS22) TCCR2B |= (1 << CS22);
- if (clockSource & CS21) TCCR2B |= (1 << CS21);
- if (clockSource & CS20) TCCR2B |= (1 << CS20);
-
- }
- }
-
- /*******************************************************************************
- * Name: powerStandby
- * Description: Putting microcontroller into power standby state.
- *
- * Argument Description
- * ========= ===========
- * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
- * up resource:
- * (a) SLEEP_15MS - 15 ms sleep
- * (b) SLEEP_30MS - 30 ms sleep
- * (c) SLEEP_60MS - 60 ms sleep
- * (d) SLEEP_120MS - 120 ms sleep
- * (e) SLEEP_250MS - 250 ms sleep
- * (f) SLEEP_500MS - 500 ms sleep
- * (g) SLEEP_1S - 1 s sleep
- * (h) SLEEP_2S - 2 s sleep
- * (i) SLEEP_4S - 4 s sleep
- * (j) SLEEP_1S - 8 s sleep
- * (k) SLEEP_FOREVER - Sleep without waking up through WDT
- *
- * 2. adc ADC module disable control. Turning off the ADC module is
- * basically removing the purpose of this low power mode.
- * (a) ADC_OFF - Turn off ADC module
- * (b) ADC_ON - Leave ADC module in its default state
- *
- * 3. bod Brown Out Detector (BOD) module disable control:
- * (a) BOD_OFF - Turn off BOD module
- * (b) BOD_ON - Leave BOD module in its default state
- *
- *******************************************************************************/
- void LowPowerClass::powerStandby(period_t period, adc_t adc, bod_t bod)
- {
- if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
-
- if (period != SLEEP_FOREVER)
- {
- wdt_enable(period);
- WDTCSR |= (1 << WDIE);
- }
-
- if (bod == BOD_OFF)
- {
- lowPowerBodOff(SLEEP_MODE_STANDBY);
- }
- else
- {
- lowPowerBodOn(SLEEP_MODE_STANDBY);
- }
-
- if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
- }
-
- /*******************************************************************************
- * Name: powerExtStandby
- * Description: Putting microcontroller into power extended standby state. This
- * is different from the power standby state as it has the
- * capability to run Timer 2 asynchronously.
- *
- * Argument Description
- * ========= ===========
- * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
- * up resource:
- * (a) SLEEP_15MS - 15 ms sleep
- * (b) SLEEP_30MS - 30 ms sleep
- * (c) SLEEP_60MS - 60 ms sleep
- * (d) SLEEP_120MS - 120 ms sleep
- * (e) SLEEP_250MS - 250 ms sleep
- * (f) SLEEP_500MS - 500 ms sleep
- * (g) SLEEP_1S - 1 s sleep
- * (h) SLEEP_2S - 2 s sleep
- * (i) SLEEP_4S - 4 s sleep
- * (j) SLEEP_1S - 8 s sleep
- * (k) SLEEP_FOREVER - Sleep without waking up through WDT
- *
- * 2. adc ADC module disable control. Turning off the ADC module is
- * basically removing the purpose of this low power mode.
- * (a) ADC_OFF - Turn off ADC module
- * (b) ADC_ON - Leave ADC module in its default state
- *
- * 3. bod Brown Out Detector (BOD) module disable control:
- * (a) BOD_OFF - Turn off BOD module
- * (b) BOD_ON - Leave BOD module in its default state
- *
- * 4. timer2 Timer 2 module disable control:
- * (a) TIMER2_OFF - Turn off Timer 2 module
- * (b) TIMER2_ON - Leave Timer 2 module in its default state
- *
- *******************************************************************************/
- void LowPowerClass::powerExtStandby(period_t period, adc_t adc, bod_t bod,
- timer2_t timer2)
- {
- // Temporary clock source variable
- unsigned char clockSource = 0;
-
- if (timer2 == TIMER2_OFF)
- {
- if (TCCR2B & CS22) clockSource |= (1 << CS22);
- if (TCCR2B & CS21) clockSource |= (1 << CS21);
- if (TCCR2B & CS20) clockSource |= (1 << CS20);
-
- // Remove the clock source to shutdown Timer2
- TCCR2B &= ~(1 << CS22);
- TCCR2B &= ~(1 << CS21);
- TCCR2B &= ~(1 << CS20);
- }
-
- if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
-
- if (period != SLEEP_FOREVER)
- {
- wdt_enable(period);
- WDTCSR |= (1 << WDIE);
- }
- if (bod == BOD_OFF)
- {
- lowPowerBodOff(SLEEP_MODE_EXT_STANDBY);
- }
- else
- {
- lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
- }
-
- if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
-
- if (timer2 == TIMER2_OFF)
- {
- if (clockSource & CS22) TCCR2B |= (1 << CS22);
- if (clockSource & CS21) TCCR2B |= (1 << CS21);
- if (clockSource & CS20) TCCR2B |= (1 << CS20);
- }
- }
-
- /*******************************************************************************
- * Name: ISR (WDT_vect)
- * Description: Watchdog Timer interrupt service routine. This routine is
- * required to allow automatic WDIF and WDIE bit clearance in
- * hardware.
- *
- *******************************************************************************/
- ISR (WDT_vect)
- {
- // WDIE & WDIF is cleared in hardware upon entering this ISR
- wdt_disable();
- }
-
- LowPowerClass LowPower;
|