AskSin++
AlarmClock.cpp
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 //- -----------------------------------------------------------------------------------------------------------------------
5 
6 #include "AlarmClock.h"
7 
8 namespace as {
9 
10 SysClock sysclock;
11 
12 void callback(void) {
13  --sysclock;
14 }
15 
16 #ifndef NORTC
17 RTC rtc;
18 void rtccallback () {
19  // DPRINT(".");
20  rtc.overflow();
21  // rtc.debug();
22  --rtc;
23 }
24 #endif
25 
26 #if ARDUINO_ARCH_AVR
27 ISR(TIMER1_OVF_vect) {
28  callback();
29 }
30 #ifndef NORTC
31 ISR(TIMER2_OVF_vect) {
32  rtccallback();
33 }
34 #endif
35 #endif
36 
37 
38 void AlarmClock::cancel(Alarm& item) {
39  ATOMIC_BLOCK( ATOMIC_RESTORESTATE )
40  {
41  item.active(false);
42  Alarm *tmp = (Alarm*) select();
43  Link *vor = this;
44  // search for the alarm to cancel
45  while (tmp != 0) {
46  if (tmp == &item) {
47  vor->unlink();
48  // raise next alarm about item ticks
49  tmp = (Alarm*) item.select();
50  if (tmp != 0) {
51  tmp->tick += item.tick;
52  }
53  return;
54  }
55  vor = tmp;
56  tmp = (Alarm*) tmp->select();
57  }
58  // cancel also in ready queue
59  ready.remove(item);
60  }
61 }
62 
63 AlarmClock& AlarmClock::operator --() {
64  ATOMIC_BLOCK( ATOMIC_RESTORESTATE )
65  {
66  Alarm* alarm = (Alarm*) select();
67  if (alarm != 0) {
68  --alarm->tick;
69  while ((alarm != 0) && (alarm->tick == 0)) {
70  unlink(); // remove expired alarm
71  // run in interrupt
72  if (alarm->async() == true) {
73  alarm->active(false);
74  alarm->trigger(*this);
75  }
76  // run in application
77  else {
78  ready.append(*alarm);
79  }
80  alarm = (Alarm*) select();
81  }
82  }
83  }
84  return *this;
85 }
86 
87 void AlarmClock::add(Alarm& item) {
88  if (item.tick > 0) {
89  ATOMIC_BLOCK( ATOMIC_RESTORESTATE )
90  {
91  item.active(true);
92  Link* prev = this;
93  Alarm* temp = (Alarm*) select();
94  while ((temp != 0) && (temp->tick < item.tick)) {
95  item.tick -= temp->tick;
96  prev = temp;
97  temp = (Alarm*) temp->select();
98  }
99  item.select(temp);
100  prev->select(&item);
101  if (temp != 0) {
102  temp->tick -= item.tick;
103  }
104  }
105  } else {
106  ready.append(item);
107  }
108 }
109 
110 uint32_t AlarmClock::get(const Alarm& item) const {
111  uint32_t aux = 0;
112  Alarm* tmp = (Alarm*) select();
113  while (tmp != 0) {
114  aux += tmp->tick;
115  if (tmp == &item) {
116  return aux;
117  }
118  tmp = (Alarm*) tmp->select();
119  }
120  return 0;
121 }
122 
123 bool RTCAlarm::delayMillis () {
124  if( millis != 0 ) {
125  set(millis2ticks(millis));
126  sysclock.add(*this);
127  millis = 0;
128  return true;
129  }
130  return false;
131 }
132 
133 SysClock& SysClock::instance() { return sysclock; }
134 
135 #ifndef NORTC
136 RTC& RTC::instance() { return rtc; }
137 #endif
138 
139 }