forked from pa-pa/AskSinPP
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Activity.h
128 lines (105 loc) · 2.91 KB
/
Activity.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//- -----------------------------------------------------------------------------------------------------------------------
// AskSin++
// 2016-10-31 papa Creative Commons - https://creativecommons.org/licenses/by-nc-sa/3.0/de/
//- -----------------------------------------------------------------------------------------------------------------------
#ifndef __ACTIVITY_H__
#define __ACTIVITY_H__
#include <Debug.h>
#include <AlarmClock.h>
#include <Radio.h>
#include <LowPower.h>
namespace as {
class Idle {
public:
static void waitSerial () {
// DPRINT(F("Go sleep - ")); DHEXLN((uint16_t)aclock.next());
Serial.flush();
while (!(UCSR0A & (1 << UDRE0))) { // Wait for empty transmit buffer
UCSR0A |= 1 << TXC0; // mark transmission not complete
}
while (!(UCSR0A & (1 << TXC0))); // Wait for the transmission to complete
}
static void powerSave () {
LowPower.idle(SLEEP_FOREVER,ADC_OFF,TIMER2_OFF,TIMER1_ON,TIMER0_OFF,SPI_ON,USART0_ON,TWI_OFF);
}
};
class Sleep : public Idle {
public:
static uint32_t doSleep (uint32_t ticks) {
radio.setIdle();
uint32_t offset = 0;
if( ticks == 0 ) {
LowPower.powerDown(SLEEP_FOREVER,ADC_OFF,BOD_OFF);
}
else if( ticks > seconds2ticks(8) ) {
LowPower.powerDown(SLEEP_8S,ADC_OFF,BOD_OFF);
offset = seconds2ticks(8);
}
else if (ticks > seconds2ticks(1) ) {
LowPower.powerDown(SLEEP_1S,ADC_OFF,BOD_OFF);
offset = seconds2ticks(1);
}
else if (ticks > millis2ticks(500) ) {
LowPower.powerDown(SLEEP_500MS,ADC_OFF,BOD_OFF);
offset = millis2ticks(500);
}
radio.wakeup();
return offset;
}
static void powerSave () {
aclock.disable();
uint32_t ticks = aclock.next();
if( aclock.isready() == false ) {
if( ticks == 0 || ticks > millis2ticks(500) ) {
uint32_t offset = doSleep(ticks);
aclock.correct(offset);
aclock.enable();
}
else{
aclock.enable();
Idle::powerSave();
}
}
else {
aclock.enable();
}
}
};
class Activity : public Alarm {
bool awake;
public:
Activity () : Alarm(0), awake(false) {
async(true);
}
virtual ~Activity () {}
virtual void trigger (AlarmClock& clock) {
awake = false;
}
// do not sleep for time in ticks
void stayAwake (uint32_t time) {
uint32_t old = aclock.get(*this);
if( old < time ) {
awake = true;
aclock.cancel(*this);
tick = time;
aclock.add(*this);
}
}
template <class Saver>
void savePower () {
if( awake == false ) {
#ifndef NDEBUG
Saver::waitSerial();
#endif
Saver::powerSave();
}
}
void sleepForever () {
while( true ) {
LowPower.powerDown(SLEEP_FOREVER,ADC_OFF,BOD_OFF);
}
}
};
extern Activity activity;
}
#endif