PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

LowPower.cpp 17KB

3 yıl önce
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. /*******************************************************************************
  2. * LowPower Library
  3. * Version: 1.20
  4. * Date: 16-12-2011
  5. * Company: Rocket Scream Electronics
  6. * Website: www.rocketscream.com
  7. *
  8. * This is a lightweight low power library for Arduino. Please check our wiki
  9. * (www.rocketscream.com/wiki) for more information on using this piece of
  10. * library.
  11. *
  12. * This library is licensed under Creative Commons Attribution-ShareAlike 3.0
  13. * Unported License.
  14. *
  15. * Revision Description
  16. * ======== ===========
  17. * 1.20 Remove typo error in idle method for checking whether Timer 0 was
  18. * turned off.
  19. * Remove dependecy on WProgram.h which is not required.
  20. * Tested to work with Arduino IDE 1.0.
  21. * 1.10 Added #ifndef for sleep_bod_disable() for compatibility with future
  22. * Arduino IDE release.
  23. * 1.00 Initial public release.
  24. *******************************************************************************/
  25. #include <avr/sleep.h>
  26. #include <avr/wdt.h>
  27. #include <avr/power.h>
  28. #include <avr/interrupt.h>
  29. #include "LowPower.h"
  30. #ifndef sleep_bod_disable
  31. #define sleep_bod_disable() \
  32. do { \
  33. unsigned char tempreg; \
  34. __asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
  35. "ori %[tempreg], %[bods_bodse]" "\n\t" \
  36. "out %[mcucr], %[tempreg]" "\n\t" \
  37. "andi %[tempreg], %[not_bodse]" "\n\t" \
  38. "out %[mcucr], %[tempreg]" \
  39. : [tempreg] "=&d" (tempreg) \
  40. : [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
  41. [bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
  42. [not_bodse] "i" (~_BV(BODSE))); \
  43. } while (0)
  44. #endif
  45. #define lowPowerBodOn(mode) \
  46. do { \
  47. set_sleep_mode(mode); \
  48. cli(); \
  49. sleep_enable(); \
  50. sei(); \
  51. sleep_cpu(); \
  52. sleep_disable(); \
  53. sei(); \
  54. } while (0);
  55. #define lowPowerBodOff(mode)\
  56. do { \
  57. set_sleep_mode(mode); \
  58. cli(); \
  59. sleep_enable(); \
  60. sleep_bod_disable(); \
  61. sei(); \
  62. sleep_cpu(); \
  63. sleep_disable(); \
  64. sei(); \
  65. } while (0);
  66. /*******************************************************************************
  67. * Name: idle
  68. * Description: Putting microcontroller into idle state. Please make sure you
  69. * understand the implication and result of disabling module.
  70. *
  71. * Argument Description
  72. * ========= ===========
  73. * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
  74. * up resource:
  75. * (a) SLEEP_15MS - 15 ms sleep
  76. * (b) SLEEP_30MS - 30 ms sleep
  77. * (c) SLEEP_60MS - 60 ms sleep
  78. * (d) SLEEP_120MS - 120 ms sleep
  79. * (e) SLEEP_250MS - 250 ms sleep
  80. * (f) SLEEP_500MS - 500 ms sleep
  81. * (g) SLEEP_1S - 1 s sleep
  82. * (h) SLEEP_2S - 2 s sleep
  83. * (i) SLEEP_4S - 4 s sleep
  84. * (j) SLEEP_1S - 8 s sleep
  85. * (k) SLEEP_FOREVER - Sleep without waking up through WDT
  86. *
  87. * 2. adc ADC module disable control:
  88. * (a) ADC_OFF - Turn off ADC module
  89. * (b) ADC_ON - Leave ADC module in its default state
  90. *
  91. * 3. timer2 Timer 2 module disable control:
  92. * (a) TIMER2_OFF - Turn off Timer 2 module
  93. * (b) TIMER2_ON - Leave Timer 2 module in its default state
  94. *
  95. * 4. timer1 Timer 1 module disable control:
  96. * (a) TIMER1_OFF - Turn off Timer 1 module
  97. * (b) TIMER1_ON - Leave Timer 1 module in its default state
  98. *
  99. * 5. timer0 Timer 0 module disable control:
  100. * (a) TIMER0_OFF - Turn off Timer 0 module
  101. * (b) TIMER0_ON - Leave Timer 0 module in its default state
  102. *
  103. * 6. spi SPI module disable control:
  104. * (a) ADC_OFF - Turn off ADC module
  105. * (b) ADC_ON - Leave ADC module in its default state
  106. *
  107. * 7. usart0 USART0 module disable control:
  108. * (a) USART0_OFF - Turn off USART0 module
  109. * (b) USART0_ON - Leave USART0 module in its default state
  110. *
  111. * 8. twi TWI module disable control:
  112. * (a) TWI_OFF - Turn off TWI module
  113. * (b) TWI_ON - Leave TWI module in its default state
  114. *
  115. *******************************************************************************/
  116. void LowPowerClass::idle(period_t period, adc_t adc, timer2_t timer2,
  117. timer1_t timer1, timer0_t timer0,
  118. spi_t spi, usart0_t usart0, twi_t twi)
  119. {
  120. // Temporary clock source variable
  121. unsigned char clockSource = 0;
  122. if (timer2 == TIMER2_OFF)
  123. {
  124. if (TCCR2B & CS22) clockSource |= (1 << CS22);
  125. if (TCCR2B & CS21) clockSource |= (1 << CS21);
  126. if (TCCR2B & CS20) clockSource |= (1 << CS20);
  127. // Remove the clock source to shutdown Timer2
  128. TCCR2B &= ~(1 << CS22);
  129. TCCR2B &= ~(1 << CS21);
  130. TCCR2B &= ~(1 << CS20);
  131. power_timer2_disable();
  132. }
  133. if (adc == ADC_OFF)
  134. {
  135. ADCSRA &= ~(1 << ADEN);
  136. power_adc_disable();
  137. }
  138. if (timer1 == TIMER1_OFF) power_timer1_disable();
  139. if (timer0 == TIMER0_OFF) power_timer0_disable();
  140. if (spi == SPI_OFF) power_spi_disable();
  141. if (usart0 == USART0_OFF) power_usart0_disable();
  142. if (twi == TWI_OFF) power_twi_disable();
  143. if (period != SLEEP_FOREVER)
  144. {
  145. wdt_enable(period);
  146. WDTCSR |= (1 << WDIE);
  147. }
  148. lowPowerBodOn(SLEEP_MODE_IDLE);
  149. if (adc == ADC_OFF)
  150. {
  151. power_adc_enable();
  152. ADCSRA |= (1 << ADEN);
  153. }
  154. if (timer2 == TIMER2_OFF)
  155. {
  156. if (clockSource & CS22) TCCR2B |= (1 << CS22);
  157. if (clockSource & CS21) TCCR2B |= (1 << CS21);
  158. if (clockSource & CS20) TCCR2B |= (1 << CS20);
  159. power_timer2_enable();
  160. }
  161. if (timer1 == TIMER1_OFF) power_timer1_enable();
  162. if (timer0 == TIMER0_OFF) power_timer0_enable();
  163. if (spi == SPI_OFF) power_spi_enable();
  164. if (usart0 == USART0_OFF) power_usart0_enable();
  165. if (twi == TWI_OFF) power_twi_enable();
  166. }
  167. /*******************************************************************************
  168. * Name: adcNoiseReduction
  169. * Description: Putting microcontroller into ADC noise reduction state. This is
  170. * a very useful state when using the ADC to achieve best and low
  171. * noise signal.
  172. *
  173. * Argument Description
  174. * ========= ===========
  175. * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
  176. * up resource:
  177. * (a) SLEEP_15MS - 15 ms sleep
  178. * (b) SLEEP_30MS - 30 ms sleep
  179. * (c) SLEEP_60MS - 60 ms sleep
  180. * (d) SLEEP_120MS - 120 ms sleep
  181. * (e) SLEEP_250MS - 250 ms sleep
  182. * (f) SLEEP_500MS - 500 ms sleep
  183. * (g) SLEEP_1S - 1 s sleep
  184. * (h) SLEEP_2S - 2 s sleep
  185. * (i) SLEEP_4S - 4 s sleep
  186. * (j) SLEEP_1S - 8 s sleep
  187. * (k) SLEEP_FOREVER - Sleep without waking up through WDT
  188. *
  189. * 2. adc ADC module disable control. Turning off the ADC module is
  190. * basically removing the purpose of this low power mode.
  191. * (a) ADC_OFF - Turn off ADC module
  192. * (b) ADC_ON - Leave ADC module in its default state
  193. *
  194. * 3. timer2 Timer 2 module disable control:
  195. * (a) TIMER2_OFF - Turn off Timer 2 module
  196. * (b) TIMER2_ON - Leave Timer 2 module in its default state
  197. *
  198. *******************************************************************************/
  199. void LowPowerClass::adcNoiseReduction(period_t period, adc_t adc,
  200. timer2_t timer2)
  201. {
  202. // Temporary clock source variable
  203. unsigned char clockSource = 0;
  204. if (timer2 == TIMER2_OFF)
  205. {
  206. if (TCCR2B & CS22) clockSource |= (1 << CS22);
  207. if (TCCR2B & CS21) clockSource |= (1 << CS21);
  208. if (TCCR2B & CS20) clockSource |= (1 << CS20);
  209. // Remove the clock source to shutdown Timer2
  210. TCCR2B &= ~(1 << CS22);
  211. TCCR2B &= ~(1 << CS21);
  212. TCCR2B &= ~(1 << CS20);
  213. }
  214. if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
  215. if (period != SLEEP_FOREVER)
  216. {
  217. wdt_enable(period);
  218. WDTCSR |= (1 << WDIE);
  219. }
  220. lowPowerBodOn(SLEEP_MODE_ADC);
  221. if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
  222. if (timer2 == TIMER2_OFF)
  223. {
  224. if (clockSource & CS22) TCCR2B |= (1 << CS22);
  225. if (clockSource & CS21) TCCR2B |= (1 << CS21);
  226. if (clockSource & CS20) TCCR2B |= (1 << CS20);
  227. }
  228. }
  229. /*******************************************************************************
  230. * Name: powerDown
  231. * Description: Putting microcontroller into power down state. This is
  232. * the lowest current consumption state. Use this together with
  233. * external pin interrupt to wake up through external event
  234. * triggering (example: RTC clockout pin, SD card detect pin).
  235. *
  236. * Argument Description
  237. * ========= ===========
  238. * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
  239. * up resource:
  240. * (a) SLEEP_15MS - 15 ms sleep
  241. * (b) SLEEP_30MS - 30 ms sleep
  242. * (c) SLEEP_60MS - 60 ms sleep
  243. * (d) SLEEP_120MS - 120 ms sleep
  244. * (e) SLEEP_250MS - 250 ms sleep
  245. * (f) SLEEP_500MS - 500 ms sleep
  246. * (g) SLEEP_1S - 1 s sleep
  247. * (h) SLEEP_2S - 2 s sleep
  248. * (i) SLEEP_4S - 4 s sleep
  249. * (j) SLEEP_1S - 8 s sleep
  250. * (k) SLEEP_FOREVER - Sleep without waking up through WDT
  251. *
  252. * 2. adc ADC module disable control. Turning off the ADC module is
  253. * basically removing the purpose of this low power mode.
  254. * (a) ADC_OFF - Turn off ADC module
  255. * (b) ADC_ON - Leave ADC module in its default state
  256. *
  257. * 3. bod Brown Out Detector (BOD) module disable control:
  258. * (a) BOD_OFF - Turn off BOD module
  259. * (b) BOD_ON - Leave BOD module in its default state
  260. *
  261. *******************************************************************************/
  262. void LowPowerClass::powerDown(period_t period, adc_t adc, bod_t bod)
  263. {
  264. if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
  265. if (period != SLEEP_FOREVER)
  266. {
  267. wdt_enable(period);
  268. WDTCSR |= (1 << WDIE);
  269. }
  270. if (bod == BOD_OFF)
  271. {
  272. lowPowerBodOff(SLEEP_MODE_PWR_DOWN);
  273. }
  274. else
  275. {
  276. lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
  277. }
  278. if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
  279. }
  280. /*******************************************************************************
  281. * Name: powerSave
  282. * Description: Putting microcontroller into power save state. This is
  283. * the lowest current consumption state after power down.
  284. * Use this state together with an external 32.768 kHz crystal (but
  285. * 8/16 MHz crystal/resonator need to be removed) to provide an
  286. * asynchronous clock source to Timer 2. Please take note that
  287. * Timer 2 is also used by the Arduino core for PWM operation.
  288. * Please refer to wiring.c for explanation. Removal of the external
  289. * 8/16 MHz crystal/resonator requires the microcontroller to run
  290. * on its internal RC oscillator which is not so accurate for time
  291. * critical operation.
  292. *
  293. * Argument Description
  294. * ========= ===========
  295. * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
  296. * up resource:
  297. * (a) SLEEP_15MS - 15 ms sleep
  298. * (b) SLEEP_30MS - 30 ms sleep
  299. * (c) SLEEP_60MS - 60 ms sleep
  300. * (d) SLEEP_120MS - 120 ms sleep
  301. * (e) SLEEP_250MS - 250 ms sleep
  302. * (f) SLEEP_500MS - 500 ms sleep
  303. * (g) SLEEP_1S - 1 s sleep
  304. * (h) SLEEP_2S - 2 s sleep
  305. * (i) SLEEP_4S - 4 s sleep
  306. * (j) SLEEP_1S - 8 s sleep
  307. * (k) SLEEP_FOREVER - Sleep without waking up through WDT
  308. *
  309. * 2. adc ADC module disable control. Turning off the ADC module is
  310. * basically removing the purpose of this low power mode.
  311. * (a) ADC_OFF - Turn off ADC module
  312. * (b) ADC_ON - Leave ADC module in its default state
  313. *
  314. * 3. bod Brown Out Detector (BOD) module disable control:
  315. * (a) BOD_OFF - Turn off BOD module
  316. * (b) BOD_ON - Leave BOD module in its default state
  317. *
  318. * 4. timer2 Timer 2 module disable control:
  319. * (a) TIMER2_OFF - Turn off Timer 2 module
  320. * (b) TIMER2_ON - Leave Timer 2 module in its default state
  321. *
  322. *******************************************************************************/
  323. void LowPowerClass::powerSave(period_t period, adc_t adc, bod_t bod,
  324. timer2_t timer2)
  325. {
  326. // Temporary clock source variable
  327. unsigned char clockSource = 0;
  328. if (timer2 == TIMER2_OFF)
  329. {
  330. if (TCCR2B & CS22) clockSource |= (1 << CS22);
  331. if (TCCR2B & CS21) clockSource |= (1 << CS21);
  332. if (TCCR2B & CS20) clockSource |= (1 << CS20);
  333. // Remove the clock source to shutdown Timer2
  334. TCCR2B &= ~(1 << CS22);
  335. TCCR2B &= ~(1 << CS21);
  336. TCCR2B &= ~(1 << CS20);
  337. }
  338. if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
  339. if (period != SLEEP_FOREVER)
  340. {
  341. wdt_enable(period);
  342. WDTCSR |= (1 << WDIE);
  343. }
  344. if (bod == BOD_OFF)
  345. {
  346. lowPowerBodOff(SLEEP_MODE_PWR_SAVE);
  347. }
  348. else
  349. {
  350. lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
  351. }
  352. if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
  353. if (timer2 == TIMER2_OFF)
  354. {
  355. if (clockSource & CS22) TCCR2B |= (1 << CS22);
  356. if (clockSource & CS21) TCCR2B |= (1 << CS21);
  357. if (clockSource & CS20) TCCR2B |= (1 << CS20);
  358. }
  359. }
  360. /*******************************************************************************
  361. * Name: powerStandby
  362. * Description: Putting microcontroller into power standby state.
  363. *
  364. * Argument Description
  365. * ========= ===========
  366. * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
  367. * up resource:
  368. * (a) SLEEP_15MS - 15 ms sleep
  369. * (b) SLEEP_30MS - 30 ms sleep
  370. * (c) SLEEP_60MS - 60 ms sleep
  371. * (d) SLEEP_120MS - 120 ms sleep
  372. * (e) SLEEP_250MS - 250 ms sleep
  373. * (f) SLEEP_500MS - 500 ms sleep
  374. * (g) SLEEP_1S - 1 s sleep
  375. * (h) SLEEP_2S - 2 s sleep
  376. * (i) SLEEP_4S - 4 s sleep
  377. * (j) SLEEP_1S - 8 s sleep
  378. * (k) SLEEP_FOREVER - Sleep without waking up through WDT
  379. *
  380. * 2. adc ADC module disable control. Turning off the ADC module is
  381. * basically removing the purpose of this low power mode.
  382. * (a) ADC_OFF - Turn off ADC module
  383. * (b) ADC_ON - Leave ADC module in its default state
  384. *
  385. * 3. bod Brown Out Detector (BOD) module disable control:
  386. * (a) BOD_OFF - Turn off BOD module
  387. * (b) BOD_ON - Leave BOD module in its default state
  388. *
  389. *******************************************************************************/
  390. void LowPowerClass::powerStandby(period_t period, adc_t adc, bod_t bod)
  391. {
  392. if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
  393. if (period != SLEEP_FOREVER)
  394. {
  395. wdt_enable(period);
  396. WDTCSR |= (1 << WDIE);
  397. }
  398. if (bod == BOD_OFF)
  399. {
  400. lowPowerBodOff(SLEEP_MODE_STANDBY);
  401. }
  402. else
  403. {
  404. lowPowerBodOn(SLEEP_MODE_STANDBY);
  405. }
  406. if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
  407. }
  408. /*******************************************************************************
  409. * Name: powerExtStandby
  410. * Description: Putting microcontroller into power extended standby state. This
  411. * is different from the power standby state as it has the
  412. * capability to run Timer 2 asynchronously.
  413. *
  414. * Argument Description
  415. * ========= ===========
  416. * 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
  417. * up resource:
  418. * (a) SLEEP_15MS - 15 ms sleep
  419. * (b) SLEEP_30MS - 30 ms sleep
  420. * (c) SLEEP_60MS - 60 ms sleep
  421. * (d) SLEEP_120MS - 120 ms sleep
  422. * (e) SLEEP_250MS - 250 ms sleep
  423. * (f) SLEEP_500MS - 500 ms sleep
  424. * (g) SLEEP_1S - 1 s sleep
  425. * (h) SLEEP_2S - 2 s sleep
  426. * (i) SLEEP_4S - 4 s sleep
  427. * (j) SLEEP_1S - 8 s sleep
  428. * (k) SLEEP_FOREVER - Sleep without waking up through WDT
  429. *
  430. * 2. adc ADC module disable control. Turning off the ADC module is
  431. * basically removing the purpose of this low power mode.
  432. * (a) ADC_OFF - Turn off ADC module
  433. * (b) ADC_ON - Leave ADC module in its default state
  434. *
  435. * 3. bod Brown Out Detector (BOD) module disable control:
  436. * (a) BOD_OFF - Turn off BOD module
  437. * (b) BOD_ON - Leave BOD module in its default state
  438. *
  439. * 4. timer2 Timer 2 module disable control:
  440. * (a) TIMER2_OFF - Turn off Timer 2 module
  441. * (b) TIMER2_ON - Leave Timer 2 module in its default state
  442. *
  443. *******************************************************************************/
  444. void LowPowerClass::powerExtStandby(period_t period, adc_t adc, bod_t bod,
  445. timer2_t timer2)
  446. {
  447. // Temporary clock source variable
  448. unsigned char clockSource = 0;
  449. if (timer2 == TIMER2_OFF)
  450. {
  451. if (TCCR2B & CS22) clockSource |= (1 << CS22);
  452. if (TCCR2B & CS21) clockSource |= (1 << CS21);
  453. if (TCCR2B & CS20) clockSource |= (1 << CS20);
  454. // Remove the clock source to shutdown Timer2
  455. TCCR2B &= ~(1 << CS22);
  456. TCCR2B &= ~(1 << CS21);
  457. TCCR2B &= ~(1 << CS20);
  458. }
  459. if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
  460. if (period != SLEEP_FOREVER)
  461. {
  462. wdt_enable(period);
  463. WDTCSR |= (1 << WDIE);
  464. }
  465. if (bod == BOD_OFF)
  466. {
  467. lowPowerBodOff(SLEEP_MODE_EXT_STANDBY);
  468. }
  469. else
  470. {
  471. lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
  472. }
  473. if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
  474. if (timer2 == TIMER2_OFF)
  475. {
  476. if (clockSource & CS22) TCCR2B |= (1 << CS22);
  477. if (clockSource & CS21) TCCR2B |= (1 << CS21);
  478. if (clockSource & CS20) TCCR2B |= (1 << CS20);
  479. }
  480. }
  481. /*******************************************************************************
  482. * Name: ISR (WDT_vect)
  483. * Description: Watchdog Timer interrupt service routine. This routine is
  484. * required to allow automatic WDIF and WDIE bit clearance in
  485. * hardware.
  486. *
  487. *******************************************************************************/
  488. ISR (WDT_vect)
  489. {
  490. // WDIE & WDIF is cleared in hardware upon entering this ISR
  491. wdt_disable();
  492. }
  493. LowPowerClass LowPower;