atMETEO
An ATmega based weather station
timer.h
Go to the documentation of this file.
1 /*
2  * atMETEO - An ATmega based weather station
3  * Copyright (C) 2014-2015 Christian Fetzer
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18  */
19 
20 #pragma once
21 
38 #include <inttypes.h> // AVR toolchain doesn't offer cinttypes header
39 
40 #include <avr/io.h>
41 #include <avr/interrupt.h>
42 
43 #include "lib/utils.h"
44 
45 #include "interrupt.h"
46 
47 // Ensure compatibility with older ATmega processors
48 #ifndef TIMSK1
49  #define TIMSK1 TIMSK
51 #endif
52 #ifndef TICIE1
53  #define TICIE1 ICIE1
55 #endif
56 
57 #ifndef F_CPU
58 #error "F_CPU not defined for timer.h"
59 #endif
60 
61 namespace Avr
62 {
63 
76 template <uint16_t prescaler>
77 struct TimerUtils
78 {
93  static constexpr uint8_t clockSelect()
94  {
95  static_assert(prescaler == 1 || prescaler == 8 || prescaler == 64 ||
96  prescaler == 256 || prescaler == 1024,
97  "Invalid prescaler (1, 8, 64, 256, 1024)");
98  return prescaler == 1 ? (1 << CS10) :
99  prescaler == 8 ? (1 << CS11) :
100  prescaler == 64 ? (1 << CS11) | (1 << CS10) :
101  prescaler == 256 ? (1 << CS12) :
102  prescaler == 1024 ? (1 << CS12) | (1 << CS10) : 0;
103  }
104 
120  template <uint16_t us>
121  static constexpr uint16_t usToTicks()
122  {
123  return ((uint64_t)F_CPU * us) / (1000000UL * prescaler);
124  }
125 };
126 
127 namespace internal
128 {
129 
141 {
142  CLASS_IRQ(InputCaptureInterrupt, TIMER1_CAPT_vect);
143  static TimerInputCaptureBase* s_baseInstance;
144 
145  virtual void _pulseWidthReceived(uint16_t) = 0;
146 };
147 TimerInputCaptureBase *TimerInputCaptureBase::s_baseInstance = nullptr;
148 
149 void TimerInputCaptureBase::InputCaptureInterrupt()
150 {
151  s_baseInstance->_pulseWidthReceived(TCNT1);
152  TCNT1 = 0;
153 
154  // Flip edge detection
155  Sensors::bitFlip(TCCR1B, ICES1);
156 }
157 
158 } // namespace internal
159 
184 template <uint16_t prescaler, class TObserver>
186  : private internal::TimerInputCaptureBase, private TObserver
187 {
188 public:
195  {
196  return s_instance;
197  }
198 
199 private:
200  static TimerInputCapture s_instance;
201 
203  {
205 
206  // Input capture edge select: start with rising edge
207  Sensors::bitSet(TCCR1B, ICES1);
208 
209  // Enable input capture
211 
212  s_baseInstance = this;
213  }
214 
215  void _pulseWidthReceived(uint16_t pulseWidth)
216  {
217  s_instance.pulseWidthReceived(pulseWidth);
218  }
219 };
220 
221 template <uint16_t prescaler, class TObserver>
224  // \addtogroup libtarget_timer
226 
227 } // namespace Avr
static TimerInputCapture & instance()
Returns the Avr::TimerInputCapture instance.
Definition: timer.h:194
static constexpr uint8_t clockSelect()
Calculates the clock select value for the given prescaler.
Definition: timer.h:93
C++ wrapper for accessing the built-in input capture facility for measuring the width of external pul...
Definition: timer.h:185
static constexpr uint16_t usToTicks()
Converts us to ticks for the given CPU frequency and prescaler.
Definition: timer.h:121
void bitFlip(T &value, uint8_t bit)
Flips the bit in the given value.
Definition: utils.h:79
#define TICIE1
Timer 1 Input Capture Interrupt Enable.
Definition: timer.h:54
Bit manipulation utilities.
Compile time calculation of clock select and conversion of time (in us) to system clock ticks given t...
Definition: timer.h:77
#define TIMSK1
Timer/Counter Interrupt Mask Register.
Definition: timer.h:50
Namespace containing all symbols of the AVR C++ utilities library.
Definition: adc.h:48
void bitSet(T &value, uint8_t bit)
Sets the bit in the given value to 1.
Definition: utils.h:54
#define CLASS_IRQ(name, vector)
Creates an interrupt service routine as static member function of a class.
Definition: interrupt.h:65
Utilities for interrupt service routines.
Internal base class for Avr::TimerInputCapture.
Definition: timer.h:140