FastArduino  v1.7
C++ library to build fast but small Arduino/AVR projects
analog_input.h
Go to the documentation of this file.
1 // Copyright 2016-2021 Jean-Francois Poilpret
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
16 
21 #ifndef ANALOGINPUT_HH
22 #define ANALOGINPUT_HH
23 
24 #include "boards/board_traits.h"
25 #include "time.h"
26 
30 namespace analog
31 {
32  //TODO LATER: add class (or namespace?) with general methods enable/disable ADC...
33 
48  template<board::AnalogPin APIN_, typename SAMPLE_TYPE_ = uint16_t,
49  board::AnalogReference AREF_ = board::AnalogReference::AVCC,
50  board::AnalogClock MAXFREQ_ = board::AnalogClock::MAX_FREQ_200KHz>
52  {
53  public:
58  static constexpr const board::AnalogPin APIN = APIN_;
62  static constexpr const board::AnalogReference AREF = AREF_;
66  using SAMPLE_TYPE = SAMPLE_TYPE_;
71  static constexpr const board::AnalogClock MAXFREQ = MAXFREQ_;
72 
73  private:
75  using TRAIT = board_traits::AnalogPin_trait<APIN>;
76  using GLOBAL_TRAIT = board_traits::GlobalAnalogPin_trait;
77  using AREF_TRAIT = board_traits::AnalogReference_trait<AREF>;
78  using TYPE_TRAIT = board_traits::AnalogSampleType_trait<SAMPLE_TYPE>;
79  using FREQ_TRAIT = board_traits::AnalogClock_trait<MAXFREQ>;
80 
81  static constexpr const uint16_t BG_STABILIZATION_DELAY_US = 400;
82 
83  public:
84  AnalogInput() = default;
85  AnalogInput(const THIS&) = delete;
86  THIS& operator=(const THIS&) = delete;
87 
91  using TYPE = SAMPLE_TYPE;
92 
97  static constexpr const uint8_t PRESCALER = FREQ_TRAIT::PRESCALER;
98 
106  {
107  // First ensure that any pending sampling is finished
108  GLOBAL_TRAIT::ADCSRA_.loop_until_bit_clear(ADSC);
109  // Setup multiplexer selection and start conversion
110  GLOBAL_TRAIT::ADMUX_ = AREF_TRAIT::MASK | TYPE_TRAIT::ADLAR1 | TRAIT::MUX_MASK1;
111  GLOBAL_TRAIT::ADCSRB_ = TRAIT::MUX_MASK2 | TYPE_TRAIT::ADLAR2;
112 
113  // The following delay is necessary for bandgap ADC, strangely 70us should be enough (datasheet)
114  // but this works only when no other ADC is used "at the same time"
115  // In this situation, a delay of minimum 400us seems necessary to ensure bandgap reference voltage is stabilized
116  if (TRAIT::IS_BANDGAP) time::delay_us(BG_STABILIZATION_DELAY_US);
117 
118  GLOBAL_TRAIT::ADCSRA_ = bits::BV8(ADEN, ADSC) | TRAIT::MUX_MASK2 | FREQ_TRAIT::PRESCALER_MASK;
119  // Wait until sampling is done
120  GLOBAL_TRAIT::ADCSRA_.loop_until_bit_clear(ADSC);
121  // Should we synchronize ADC reading?
122  return TYPE_TRAIT::ADC_;
123  }
124  };
125 
134  template<board::AnalogPin BANDGAP_ = board::AnalogPin::BANDGAP>
136  : public AnalogInput<BANDGAP_, uint16_t, board::AnalogReference::AVCC, board::AnalogClock::MAX_FREQ_50KHz>
137  {
138  public:
142  static constexpr const board::AnalogPin BANDGAP = BANDGAP_;
143 
144  private:
145  using TRAIT = board_traits::AnalogPin_trait<BANDGAP>;
146  static_assert(TRAIT::IS_BANDGAP, "BANDGAP_ parameter must be a bandgap ADC input");
147  static constexpr const uint16_t REFERENCE_MV = TRAIT::BANDGAP_VOLTAGE_MV;
148 
149  public:
150  PowerVoltage() = default;
151  PowerVoltage(const PowerVoltage<BANDGAP_>&) = delete;
152  PowerVoltage<BANDGAP_>& operator=(const PowerVoltage<BANDGAP_>&) = delete;
153 
159  uint16_t voltage_mV()
160  {
161  // Get sample
162  uint16_t rate = this->template sample();
163  // Do the maths to find out Vcc from rate:
164  return REFERENCE_MV * 1024L / rate;
165  }
166  };
167 
168  //TODO LATER: need ISR also
169  // Find better class name
170  //TODO Implement mechanism to ensure only DeferredAnalogInput can be registered (need sth like one AnalogInputManager?))
171  // template<board::AnalogPin APIN, board::AnalogReference AREF = board::AnalogReference::AVCC, typename SAMPLE_TYPE = uint16_t>
172  // class DeferredAnalogInput
173  // {
174  // public:
175  // DeferredAnalogInput();
176  // void start();
177  // void stop();
178  // SAMPLE_TYPE sample();
179  // //Other API? eg sample_ready? sample_changed?
180 
181  // private:
182  // SAMPLE_TYPE sample_;
183  // };
184 }
185 
186 #endif /* ANALOGINPUT_HH */
187 
board::AnalogPin
AnalogPin
Defines all available analog input pins of ATmega644, with reference to Arduino MEGA pins.
Definition: atmega_xx4.h:187
board::AnalogReference
AnalogReference
Defines available voltage references of ATmega644, used for analog input.
Definition: atmega_xx4.h:167
analog::AnalogInput::AREF
static constexpr const board::AnalogReference AREF
The analog reference to use for that analog input.
Definition: analog_input.h:62
analog::AnalogInput::APIN
static constexpr const board::AnalogPin APIN
The analog pin for this AnalogInput; this may also not be a real pin but an internal sensor (e....
Definition: analog_input.h:58
analog::AnalogInput
API that handles a given analog input pin of the target MCU.
Definition: analog_input.h:52
analog::AnalogInput::PRESCALER
static constexpr const uint8_t PRESCALER
The prescaler used by ADC circuitry, calculated from MAXFREQ template parameter.
Definition: analog_input.h:97
bits::BV8
static constexpr uint8_t BV8(uint8_t bit)
Create a uint8_t bitmask for the given bit number.
Definition: bits.h:41
board::MASK
constexpr uint8_t MASK() INLINE
Determine the bit mask representing the given DigitalPin inside its port.
Definition: gpio.h:45
time::delay_us
void delay_us(uint16_t us) INLINE
Delay program execution for the given amount of microseconds.
Definition: time.h:334
analog::PowerVoltage
API that uses bandgap feature to calculate current voltage fed to the MCU.
Definition: analog_input.h:137
time.h
Simple time utilities.
analog::PowerVoltage::BANDGAP
static constexpr const board::AnalogPin BANDGAP
The bandgap analog pin of the MCU target, used for this PowerVoltage.
Definition: analog_input.h:142
analog::AnalogInput::sample
SAMPLE_TYPE sample()
Start an analog-digital conversion for this analog input pin and return sample value.
Definition: analog_input.h:105
analog::AnalogInput< board::AnalogPin::BANDGAP, uint16_t, board::AnalogReference::AVCC, board::AnalogClock::MAX_FREQ_50KHz >::TYPE
SAMPLE_TYPE TYPE
The type of samples returned by sample().
Definition: analog_input.h:91
analog::AnalogInput::MAXFREQ
static constexpr const board::AnalogClock MAXFREQ
The maximum input clock frequency of the ADC circuit; higher frequencies imply lower precision of sam...
Definition: analog_input.h:71
board::AnalogClock
AnalogClock
Defines available clocks of ATmega644, used for analog input.
Definition: atmega_xx4.h:155
analog::AnalogInput< board::AnalogPin::BANDGAP, uint16_t, board::AnalogReference::AVCC, board::AnalogClock::MAX_FREQ_50KHz >::SAMPLE_TYPE
uint16_t SAMPLE_TYPE
The type of samples returned by sample().
Definition: analog_input.h:66
analog
Defines all API to manipulate analog input/output.
Definition: analog_comparator.h:78
analog::PowerVoltage::voltage_mV
uint16_t voltage_mV()
Get the voltage, in mV, feeding the MCU.
Definition: analog_input.h:159