Control Surface  1.2.0
MIDI Control Surface library for Arduino
FilteredAnalog.hpp
Go to the documentation of this file.
1 #pragma once
2 
4 AH_DIAGNOSTIC_WERROR() // Enable errors on warnings
5 
6 #include <AH/Filters/EMA.hpp>
11 #include <AH/Math/MinMaxFix.hpp>
12 #include <AH/STL/type_traits> // std::enable_if, std::is_constructible
13 #include <AH/STL/utility> // std::forward
15 
17 
22 template <uint8_t FilterShiftFactor, class FilterType, class AnalogType>
24  constexpr static uint8_t value =
25  min(sizeof(FilterType) * CHAR_BIT - ADC_BITS - FilterShiftFactor,
26  sizeof(AnalogType) * CHAR_BIT - ADC_BITS);
27 };
28 
34 template <class MappingFunction, uint8_t Precision = 10,
35  uint8_t FilterShiftFactor = ANALOG_FILTER_SHIFT_FACTOR,
36  class FilterType = ANALOG_FILTER_TYPE, class AnalogType = analog_t,
37  uint8_t IncRes = MaximumFilteredAnalogIncRes<
38  FilterShiftFactor, FilterType, AnalogType>::value>
40  public:
52  AnalogType initial = 0)
53  : analogPin(analogPin), mapFn(std::forward<MappingFunction>(mapFn)),
54  filter(increaseBitDepth<ADC_BITS + IncRes, Precision, AnalogType,
55  AnalogType>(initial)) {}
56 
66  void reset(AnalogType value = 0) {
67  filter.reset(increaseBitDepth<ADC_BITS + IncRes, Precision, AnalogType,
68  AnalogType>(value));
69  }
70 
87  void map(MappingFunction fn) { mapFn = std::forward<MappingFunction>(fn); }
88 
92  MappingFunction &getMappingFunction() { return mapFn; }
96  const MappingFunction &getMappingFunction() const { return mapFn; }
97 
107  bool update() {
108  AnalogType input = getRawValue(); // read the raw analog input value
109  input = filter.filter(input); // apply a low-pass EMA filter
110  input = mapFnHelper(input); // apply the mapping function
111  return hysteresis.update(input); // apply hysteresis, and return true
112  // if the value changed since last time
113  }
114 
125  AnalogType getValue() const { return hysteresis.getValue(); }
126 
134  float getFloatValue() const {
135  return getValue() * (1.0f / (ldexpf(1.0f, Precision) - 1.0f));
136  }
137 
142  AnalogType getRawValue() const {
143  return increaseBitDepth<ADC_BITS + IncRes, ADC_BITS, AnalogType,
144  AnalogType>(ExtIO::analogRead(analogPin));
145  }
146 
150  constexpr static AnalogType getMaxRawValue() {
151  return (1UL << (ADC_BITS + IncRes)) - 1;
152  }
153 
161  static void setupADC() {
162 #if HAS_ANALOG_READ_RESOLUTION
163  analogReadResolution(ADC_BITS);
164 #endif
165  }
166 
167  private:
171  template <typename M = MappingFunction>
172  typename std::enable_if<std::is_constructible<bool, M>::value,
173  AnalogType>::type
174  mapFnHelper(AnalogType input) {
175  return bool(mapFn) ? mapFn(input) : input;
176  }
177 
182  template <typename M = MappingFunction>
183  typename std::enable_if<!std::is_constructible<bool, M>::value,
184  AnalogType>::type
185  mapFnHelper(AnalogType input) {
186  return mapFn(input);
187  }
188 
189  private:
192 
193  static_assert(
194  ADC_BITS + IncRes + FilterShiftFactor <= sizeof(FilterType) * CHAR_BIT,
195  "Error: FilterType is not wide enough to hold the maximum value");
196  static_assert(
197  ADC_BITS + IncRes <= sizeof(AnalogType) * CHAR_BIT,
198  "Error: AnalogType is not wide enough to hold the maximum value");
199  static_assert(
200  Precision <= ADC_BITS + IncRes,
201  "Error: Precision is larger than the increased ADC precision");
202 
204  Hysteresis<ADC_BITS + IncRes - Precision, AnalogType, AnalogType>
206 };
207 
241 template <uint8_t Precision = 10,
242  uint8_t FilterShiftFactor = ANALOG_FILTER_SHIFT_FACTOR,
243  class FilterType = ANALOG_FILTER_TYPE, class AnalogType = analog_t,
244  uint8_t IncRes = MaximumFilteredAnalogIncRes<
245  FilterShiftFactor, FilterType, AnalogType>::value>
247  : public GenericFilteredAnalog<AnalogType (*)(AnalogType), Precision,
248  FilterShiftFactor, FilterType, AnalogType,
249  IncRes> {
250  public:
259  FilteredAnalog(pin_t analogPin, AnalogType initial = 0)
260  : GenericFilteredAnalog<AnalogType (*)(AnalogType), Precision,
261  FilterShiftFactor, FilterType, AnalogType,
262  IncRes>(analogPin, nullptr, initial) {}
263 
266  using MappingFunction = AnalogType (*)(AnalogType);
267 
275  void invert() {
276  constexpr AnalogType maxval = FilteredAnalog::getMaxRawValue();
277  this->map([](AnalogType val) -> AnalogType { return maxval - val; });
278  }
279 };
280 
282 
Warnings.hpp
AH::GenericFilteredAnalog::mapFnHelper
std::enable_if<!std::is_constructible< bool, M >::value, AnalogType >::type mapFnHelper(AnalogType input)
Helper function that applies the mapping function without checking if it's enabled.
Definition: FilteredAnalog.hpp:185
AH::GenericFilteredAnalog::getMappingFunction
const MappingFunction & getMappingFunction() const
Get a reference to the mapping function.
Definition: FilteredAnalog.hpp:96
Hysteresis.hpp
AH::GenericFilteredAnalog::hysteresis
Hysteresis< ADC_BITS+IncRes - Precision, AnalogType, AnalogType > hysteresis
Definition: FilteredAnalog.hpp:205
AH::GenericFilteredAnalog::setupADC
static void setupADC()
Select the configured ADC resolution.
Definition: FilteredAnalog.hpp:161
AH::increaseBitDepth
T_out increaseBitDepth(T_in in)
Increase the bit depth of the given value from Bits_in bits wide to Bits_out bits wide,...
Definition: IncreaseBitDepth.hpp:68
AH::FilteredAnalog< Sender::precision()>::MappingFunction
analog_t(*)(analog_t) MappingFunction
A function pointer to a mapping function to map analog values.
Definition: FilteredAnalog.hpp:266
AH::pin_t
uint16_t pin_t
The type for Arduino pins (and ExtendedIOElement pins).
Definition: Hardware-Types.hpp:17
AH::MaximumFilteredAnalogIncRes
Helper to determine how many of the remaining bits of the filter data types can be used to achieve hi...
Definition: FilteredAnalog.hpp:23
AH::GenericFilteredAnalog
FilteredAnalog base class with generic MappingFunction.
Definition: FilteredAnalog.hpp:39
AH::ANALOG_FILTER_SHIFT_FACTOR
constexpr uint8_t ANALOG_FILTER_SHIFT_FACTOR
The factor for the analog filter: Difference equation: where .
Definition: AH/Settings/Settings.hpp:64
AH::GenericFilteredAnalog::getFloatValue
float getFloatValue() const
Get the filtered value of the analog input with the mapping function applied as a floating point numb...
Definition: FilteredAnalog.hpp:134
SettingsWrapper.hpp
ExtendedInputOutput.hpp
AH::min
constexpr auto min(const T &a, const U &b) -> decltype(b< a ? b :a)
Return the smaller of two numbers/objects.
Definition: MinMaxFix.hpp:15
IncreaseBitDepth.hpp
AH_DIAGNOSTIC_POP
#define AH_DIAGNOSTIC_POP()
Definition: Warnings.hpp:36
AH::FilteredAnalog
A class that reads and filters an analog input.
Definition: FilteredAnalog.hpp:249
AH::GenericFilteredAnalog::filter
EMA< FilterShiftFactor, FilterType > filter
Definition: FilteredAnalog.hpp:195
AH::GenericFilteredAnalog::getRawValue
AnalogType getRawValue() const
Read the raw value of the analog input without any filtering or mapping applied, but with its bit dep...
Definition: FilteredAnalog.hpp:142
AH::GenericFilteredAnalog::getValue
AnalogType getValue() const
Get the filtered value of the analog input (with the mapping function applied).
Definition: FilteredAnalog.hpp:125
AH::ADC_BITS
constexpr uint8_t ADC_BITS
The bit depth to use for the ADC (Analog to Digital Converter).
Definition: AH/Settings/Settings.hpp:53
AH::GenericFilteredAnalog::update
bool update()
Read the analog input value, apply the mapping function, and update the average.
Definition: FilteredAnalog.hpp:107
AH::ExtIO::analogRead
analog_t analogRead(pin_t pin)
An ExtIO version of the Arduino function.
Definition: ExtendedInputOutput.cpp:73
EMA
A class for single-pole infinite impulse response filters or exponential moving average filters.
Definition: EMA.hpp:42
AH::GenericFilteredAnalog::map
void map(MappingFunction fn)
Specify a mapping function/functor that is applied to the analog value after filtering and before app...
Definition: FilteredAnalog.hpp:87
AH::GenericFilteredAnalog::GenericFilteredAnalog
GenericFilteredAnalog(pin_t analogPin, MappingFunction mapFn, AnalogType initial=0)
Construct a new GenericFilteredAnalog object.
Definition: FilteredAnalog.hpp:51
Hysteresis
A class for applying hysteresis to a given input.
Definition: Hysteresis.hpp:36
AH::GenericFilteredAnalog::getMappingFunction
MappingFunction & getMappingFunction()
Get a reference to the mapping function.
Definition: FilteredAnalog.hpp:92
AH::FilteredAnalog::FilteredAnalog
FilteredAnalog(pin_t analogPin, AnalogType initial=0)
Construct a new FilteredAnalog object.
Definition: FilteredAnalog.hpp:259
AH::analog_t
uint16_t analog_t
The type returned from analogRead and similar functions.
Definition: Hardware-Types.hpp:15
AH::ANALOG_FILTER_TYPE
uint16_t ANALOG_FILTER_TYPE
The unsigned integer type to use for analog inputs during filtering.
Definition: AH/Settings/Settings.hpp:71
AH::GenericFilteredAnalog::getMaxRawValue
constexpr static AnalogType getMaxRawValue()
Get the maximum value that can be returned from getRawValue.
Definition: FilteredAnalog.hpp:150
std
Definition: vector.cpp:5
AH::FilteredAnalog::invert
void invert()
Invert the analog value.
Definition: FilteredAnalog.hpp:275
AH_DIAGNOSTIC_WERROR
#define AH_DIAGNOSTIC_WERROR()
Definition: Warnings.hpp:35
AH::GenericFilteredAnalog::mapFn
MappingFunction mapFn
Definition: FilteredAnalog.hpp:191
BEGIN_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
Definition: AH/Settings/NamespaceSettings.hpp:9
AH::GenericFilteredAnalog::analogPin
pin_t analogPin
Definition: FilteredAnalog.hpp:190
END_AH_NAMESPACE
#define END_AH_NAMESPACE
Definition: AH/Settings/NamespaceSettings.hpp:10
AH::GenericFilteredAnalog::reset
void reset(AnalogType value=0)
Reset the filter to the given value.
Definition: FilteredAnalog.hpp:66
MinMaxFix.hpp
AH::GenericFilteredAnalog::mapFnHelper
std::enable_if< std::is_constructible< bool, M >::value, AnalogType >::type mapFnHelper(AnalogType input)
Helper function that applies the mapping function if it's enabled.
Definition: FilteredAnalog.hpp:174
MappingFunction
analog_t(*)(analog_t) MappingFunction
Definition: Def.hpp:20
Hardware-Types.hpp