AskSin++
AlarmClock.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 //- -----------------------------------------------------------------------------------------------------------------------
5 
6 #ifndef __ALARMCLOCK_H__
7 #define __ALARMCLOCK_H__
8 
9 #include "Debug.h"
10 #include "Alarm.h"
11 
12 
13 namespace as {
14 
15 #ifndef TICKS_PER_SECOND
16  // default 100 ticks per second
17  #define TICKS_PER_SECOND 100UL
18 #endif
19 
20 #define seconds2ticks(tm) ( (tm) * TICKS_PER_SECOND )
21 #define ticks2seconds(tm) ( (tm) / TICKS_PER_SECOND )
22 
23 #define decis2ticks(tm) ( (tm) * TICKS_PER_SECOND / 10 )
24 #define ticks2decis(tm) ( (tm) * 10UL / TICKS_PER_SECOND )
25 
26 #define centis2ticks(tm) ( (tm) * TICKS_PER_SECOND / 100 )
27 #define ticks2centis(tm) ( (tm) * 100UL / TICKS_PER_SECOND )
28 
29 #define millis2ticks(tm) ( (tm) * TICKS_PER_SECOND / 1000 )
30 #define ticks2millis(tm) ( (tm) * 1000UL / TICKS_PER_SECOND )
31 
32 class AlarmClock: protected Link {
33 
34  Link ready;
35 
36 public:
37 
38  void cancel(Alarm& item);
39 
40  AlarmClock& operator --();
41 
42  bool isready () const {
43  return ready.select() != 0;
44  }
45 
46  bool runready() {
47  bool worked = false;
48  while( runsingle()==true ) {
49  worked=true;
50  }
51  return worked;
52  }
53 
54  bool runsingle() {
55  Alarm* a = (Alarm*) ready.unlink();
56  if (a != 0) {
57  a->active(false);
58  a->trigger(*this);
59  return true;
60  }
61  return false;
62  }
63 
64  bool runwait () {
65  return runsingle();
66  }
67 
68  void add(Alarm& item);
69 
70  uint32_t get(const Alarm& item) const;
71 
72  uint32_t next () const {
73  Alarm* n = (Alarm*)select();
74  return n != 0 ? n->tick : 0;
75  }
76 
77  Alarm* first () const {
78  return (Alarm*)select();
79  }
80 
81  // correct the alarms after sleep
82  void correct (uint32_t ticks) {
83  ticks--;
84  Alarm* n = first();
85  if( n != 0 ) {
86  uint32_t nextticks = n->tick-1;
87  n->tick -= nextticks < ticks ? nextticks : ticks;
88  }
89  --(*this);
90  }
91 
92 };
93 
94 
95 extern void callback(void);
96 extern void rtccallback(void);
97 
98 
99 class SysClock : public AlarmClock {
100 public:
101  static SysClock& instance();
102 
103  void init() {
104  #if ARDUINO_ARCH_AVR
105  #define TIMER1_RESOLUTION 65536UL // Timer1 is 16 bit
106  // use Time1 on AVR
107  TCCR1B = _BV(WGM13); // set mode as phase and frequency correct pwm, stop the timer
108  TCCR1A = 0; // clear control register A
109  const unsigned long cycles = (F_CPU / 2000000) * (1000000 / TICKS_PER_SECOND);
110  unsigned short pwmPeriod;
111  unsigned char clockSelectBits;
112 
113  if (cycles < TIMER1_RESOLUTION) {
114  clockSelectBits = _BV(CS10);
115  pwmPeriod = (unsigned short)cycles;
116  }
117  else if (cycles < TIMER1_RESOLUTION * 8) {
118  clockSelectBits = _BV(CS11);
119  pwmPeriod = cycles / 8;
120  }
121  else if (cycles < TIMER1_RESOLUTION * 64) {
122  clockSelectBits = _BV(CS11) | _BV(CS10);
123  pwmPeriod = cycles / 64;
124  }
125  else if (cycles < TIMER1_RESOLUTION * 256) {
126  clockSelectBits = _BV(CS12);
127  pwmPeriod = cycles / 256;
128  }
129  else if (cycles < TIMER1_RESOLUTION * 1024) {
130  clockSelectBits = _BV(CS12) | _BV(CS10);
131  pwmPeriod = cycles / 1024;
132  }
133  else {
134  clockSelectBits = _BV(CS12) | _BV(CS10);
135  pwmPeriod = TIMER1_RESOLUTION - 1;
136  }
137  TCNT1 = 0;
138  ICR1 = pwmPeriod;
139  TCCR1B = _BV(WGM13) | clockSelectBits;
140  #endif
141  #ifdef ARDUINO_ARCH_STM32F1
142  // Setup Timer2 on ARM
143  Timer2.setMode(TIMER_CH2,TIMER_OUTPUT_COMPARE);
144  Timer2.setPeriod(1000000 / TICKS_PER_SECOND); // in microseconds
145  Timer2.setCompare(TIMER_CH2, 1); // overflow might be small
146  #endif
147  enable();
148  }
149 
150  void disable () {
151  #if defined ARDUINO_AVR_ATmega32 || defined(__AVR_ATmega128__)
152  TIMSK &= ~_BV(TOIE1);
153  #elif defined(ARDUINO_ARCH_AVR)
154  TIMSK1 &= ~_BV(TOIE1);
155  #elif defined(ARDUINO_ARCH_STM32F1)
156  Timer2.detachInterrupt(TIMER_CH2);
157  #endif
158  }
159 
160  void enable () {
161  #if defined ARDUINO_AVR_ATmega32|| defined(__AVR_ATmega128__)
162  TIMSK |= _BV(TOIE1);
163  #elif defined(ARDUINO_ARCH_AVR)
164  TIMSK1 |= _BV(TOIE1);
165  #elif defined(ARDUINO_ARCH_STM32F1)
166  Timer2.attachInterrupt(TIMER_CH2,callback);
167  #endif
168  }
169 
170  void add(Alarm& item) {
171  AlarmClock::add(item);
172  }
173 
174  void add(Alarm& item,uint32_t millis) {
175  item.tick = (millis2ticks(millis));
176  add(item);
177  }
178 };
179 
180 extern SysClock sysclock;
181 
182 
183 #ifndef NORTC
184 
185 class RTC : public AlarmClock {
186  uint8_t ovrfl;
187 #if defined(ARDUINO_ARCH_STM32F1) && defined(_RTCLOCK_H_)
188  RTClock rt;
189 #endif
190 public:
191 
192  RTC () : ovrfl(0) {}
193 
194  static RTC& instance();
195 
196  void init () {
197 #if defined ARDUINO_AVR_ATmega32
198  TIMSK &= ~(1<<TOIE2); //Disable timer2 interrupts
199  ASSR |= (1<<AS2); //Enable asynchronous mode
200  TCNT2 = 0; //set initial counter value
201  TCCR2 = (1<<CS22)|(1<<CS20); // mode normal & set prescaller 128
202  while (ASSR & (1<<TCN2UB)); //wait for registers update
203  TIFR |= (1<<TOV2); //clear interrupt flags
204  TIMSK |= (1<<TOIE2); //enable TOV2 interrupt
205 #elif defined(__AVR_ATmega128__)
206  TIMSK &= ~(1<<TOIE2); //Disable timer2 interrupts
207  ASSR |= (1<<AS0); //Enable asynchronous mode
208  TCNT2 = 0; //set initial counter value
209  TCCR2 = (1<<CS22)|(1<<CS20); // mode normal & set prescaller 128
210  while (ASSR & (1<<TCN0UB)); //wait for registers update
211  TIFR |= (1<<TOV2); //clear interrupt flags
212  TIMSK |= (1<<TOIE2); //enable TOV2 interrupt
213 #elif defined(ARDUINO_ARCH_AVR)
214  TIMSK2 = 0; //Disable timer2 interrupts
215  ASSR = (1<<AS2); //Enable asynchronous mode
216  TCNT2 = 0; //set initial counter value
217  TCCR2A = 0; // mode normal
218  TCCR2B = (1<<CS22)|(1<<CS20); //set prescaller 128
219  while (ASSR & ((1<<TCN2UB)|(1<<TCR2BUB))); //wait for registers update
220  TIFR2 = (1<<TOV2); //clear interrupt flags
221  TIMSK2 = (1<<TOIE2); //enable TOV2 interrupt
222 #elif defined(ARDUINO_ARCH_STM32F1) && defined(_RTCLOCK_H_)
223  rt = RTClock(RTCSEL_LSE);
224  rt.attachSecondsInterrupt(rtccallback);
225 #else
226  #warning "RTC not supported"
227 #endif
228  }
229 
230  // return millis done of the current second
231  uint32_t getCurrentMillis () {
232 #ifdef ARDUINO_ARCH_AVR
233  return (TCNT2 * 1000) / 255;
234 #else
235  return 0; // not supported ???
236 #endif
237  }
238 
239  uint32_t getCounter (bool resetovrflow) {
240  if( resetovrflow == true ) {
241  ovrfl = 0;
242  }
243 #ifdef ARDUINO_ARCH_AVR
244  return (256 * ovrfl) + TCNT2;
245 #elif defined(ARDUINO_ARCH_STM32F1) && defined(_RTCLOCK_H_)
246  return rtc_get_count();
247 #else
248  return 0;
249 #endif
250  }
251 
252  void overflow () {
253  ovrfl++;
254  }
255 
256  void debug () {
257  if( select() != 0 ) {
258  DDEC((uint16_t)((Alarm*)select())->tick);
259  DPRINT(F(" "));
260  }
261  }
262 
263  void add(Alarm& item) {
264  AlarmClock::add(item);
265  }
266 
267  void add(Alarm& item,uint32_t millis) {
268  millis += getCurrentMillis();
269  item.tick = (millis / 1000); // seconds to wait
270  add(item);
271  }
272 
273  void add(RTCAlarm& item,uint32_t millis) {
274  // correct the time with the millis of the current second
275  millis += getCurrentMillis();
276  item.tick = (millis / 1000); // seconds to wait
277  item.millis = millis % 1000; // millis to wait
278  add(item);
279  }
280 
281 };
282 
283 extern RTC rtc;
284 #endif
285 
286 }
287 
288 #endif
as::RTCAlarm
Definition: Alarm.h:52
as::Alarm
Definition: Alarm.h:15
as::AlarmClock
Definition: AlarmClock.h:32
as::RTC
Definition: AlarmClock.h:185
as::SysClock
Definition: AlarmClock.h:99