1
+ /* * This file contains implementation of timed sleeping which are common amongst AVR chips.
2
+ *
3
+ * SimpleSleep methods in this file are typically declared as weak so that variants may
4
+ * define their own.
5
+ *
6
+ * Keep ifdef to a minimum, use variant implementation files if there is any substantial difference.
7
+ */
8
+
9
+ #if defined (__AVR__)
10
+
11
+ #include " ../SimpleSleep.h"
12
+
13
+ static void timed_sleep (uint32_t sleepMs, uint8_t mode, uint8_t bod, uint8_t interrupts);
14
+
15
+ __attribute__ ((weak)) void SimpleSleep::sleepDeeply(uint32_t sleepMs)
16
+ {
17
+ // ADC OFF
18
+ uint8_t oldADCSRA = ADCSRA;
19
+ ADCSRA &= ~(1 << ADEN);
20
+
21
+ power_declare_all ();
22
+ power_save_all ();
23
+ power_all_disable ();
24
+
25
+
26
+ // For a timed sleep we may need millis() in order
27
+ // to make up sleep to a multiple of 15mS (min sleep period)
28
+ // so we will need to leave timer0 powered up (obviously
29
+ // during the actual power-down it won't be counting
30
+ // we only need it to count between the power-down periods
31
+ // of which a timed_sleep might be made up of more than one).
32
+ #if power_has_power()
33
+ power_timer0_enable ();
34
+ #endif
35
+
36
+ // sleep with bod off, interrupts on
37
+ timed_sleep (sleepMs, SLEEP_MODE_PWR_DOWN, false , true );
38
+
39
+
40
+ power_restore_all ();
41
+ ADCSRA = oldADCSRA;
42
+ }
43
+
44
+ __attribute__ ((weak)) void SimpleSleep::sleepLightly(uint32_t sleepMs)
45
+ {
46
+ // ADC OFF
47
+ uint8_t oldADCSRA = ADCSRA;
48
+ ADCSRA &= ~(1 << ADEN);
49
+
50
+ // sleep with bod off, interrupts on
51
+ #ifdef SLEEP_MODE_EXT_STANDBY
52
+ timed_sleep (sleepMs, SLEEP_MODE_EXT_STANDBY, false , true );
53
+ #else
54
+ timed_sleep (sleepMs, SLEEP_MODE_ADC, false , true );
55
+ #endif
56
+
57
+ ADCSRA = oldADCSRA;
58
+ }
59
+
60
+ __attribute__ ((weak)) void SimpleSleep::sleepIdle(uint32_t sleepMs)
61
+ {
62
+ timed_sleep (sleepMs, SLEEP_MODE_IDLE, true , true );
63
+ }
64
+
65
+ #if WDT_HAS_INTERRUPT == 1
66
+ volatile uint8_t wdt_triggered = 1 ;
67
+
68
+ ISR (WDT_vect)
69
+ {
70
+ wdt_disable ();
71
+ wdt_triggered = 1 ;
72
+ }
73
+
74
+ static void timed_sleep (uint32_t sleepMs, uint8_t mode, uint8_t bod, uint8_t interrupts)
75
+ {
76
+ do
77
+ {
78
+ // If we are not waiting on the WDT, and there is time still to sleep, setup the WDT (again)
79
+ if (wdt_triggered && sleepMs)
80
+ {
81
+ wdt_triggered = 0 ;
82
+ wdt_enable (wdt_period_for (&sleepMs));
83
+ WDTCSR |= (1 << WDIE);
84
+ }
85
+
86
+ set_sleep_mode (mode);
87
+ cli ();
88
+ sleep_enable ();
89
+ #ifdef sleep_bod_disable
90
+ if (!bod)
91
+ {
92
+ sleep_bod_disable ();
93
+ }
94
+ #else
95
+ (void )(bod); // Silence warning
96
+ #endif
97
+
98
+ // Caution, with interrupts disabled the only way you are likely
99
+ // to wake up is with a reset
100
+ if (interrupts)
101
+ {
102
+ sei ();
103
+ }
104
+
105
+ sleep_cpu ();
106
+ sleep_disable ();
107
+ sei ();
108
+ } while (!wdt_triggered || sleepMs > 0 );
109
+ }
110
+
111
+ #else
112
+
113
+ /* * This implements timed sleep without WDT, instead we force into IDLE mode and just
114
+ * spin-wait until the time is up. millis() must be available.
115
+ *
116
+ */
117
+
118
+ void timed_sleep (uint32_t sleepMs, uint8_t mode, uint8_t bod, uint8_t interrupts)
119
+ {
120
+ mode = SLEEP_MODE_IDLE;
121
+ uint32_t startSleep = millis ();
122
+
123
+ do
124
+ {
125
+ // If we are not waiting on the WDT, and there is time still to sleep, setup the WDT (again)
126
+ if ((millis () - startSleep)>=sleepMs)
127
+ {
128
+ return ;
129
+ }
130
+
131
+
132
+ set_sleep_mode (mode);
133
+ cli ();
134
+ sleep_enable ();
135
+ #ifdef sleep_bod_disable
136
+ if (!bod)
137
+ {
138
+ sleep_bod_disable ();
139
+ }
140
+ #else
141
+ (void )(bod); // Silence warning
142
+ #endif
143
+
144
+ // Caution, with interrupts disabled the only way you are likely
145
+ // to wake up is with a reset
146
+ if (interrupts)
147
+ {
148
+ sei ();
149
+ }
150
+
151
+ sleep_cpu ();
152
+ sleep_disable ();
153
+ sei ();
154
+ } while (sleepMs > 0 );
155
+
156
+ }
157
+ #endif
158
+
159
+ #endif
0 commit comments