Control Surface main
MIDI Control Surface library for Arduino
Loading...
Searching...
No Matches
FilteredAnalog.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <AH/Filters/EMA.hpp>
9#include <AH/STL/type_traits> // std::enable_if, std::is_constructible
10#include <AH/STL/utility> // std::forward
12
14
19template <uint8_t FilterShiftFactor, class FilterType, class AnalogType>
21 constexpr static uint8_t value =
22 min(sizeof(FilterType) * CHAR_BIT - ADC_BITS - FilterShiftFactor,
23 sizeof(AnalogType) * CHAR_BIT - ADC_BITS);
24};
25
31template <class MappingFunction, uint8_t Precision = 10,
32 uint8_t FilterShiftFactor = ANALOG_FILTER_SHIFT_FACTOR,
33 class FilterType = ANALOG_FILTER_TYPE, class AnalogType = analog_t,
34 uint8_t IncRes = MaximumFilteredAnalogIncRes<
35 FilterShiftFactor, FilterType, AnalogType>::value>
37 public:
49 AnalogType initial = 0)
50 : analogPin(analogPin), mapFn(std::forward<MappingFunction>(mapFn)),
51 filter(increaseBitDepth<ADC_BITS + IncRes, Precision, AnalogType,
52 AnalogType>(initial)) {}
53
56 AnalogType initial = 0)
58 std::forward<MappingFunction>(mapFn), initial) {
59 }
60
70 void reset(AnalogType value = 0) {
71 AnalogType widevalue = increaseBitDepth<ADC_BITS + IncRes, Precision,
72 AnalogType, AnalogType>(value);
73 filter.reset(widevalue);
74 hysteresis.setValue(widevalue);
75 }
76
84 AnalogType widevalue = getRawValue();
85 filter.reset(widevalue);
86 hysteresis.setValue(widevalue);
87 }
88
105 void map(MappingFunction fn) { mapFn = std::forward<MappingFunction>(fn); }
106
114 const MappingFunction &getMappingFunction() const { return mapFn; }
115
125 bool update() {
126 AnalogType input = getRawValue(); // read the raw analog input value
127 input = filter.filter(input); // apply a low-pass EMA filter
128 input = mapFnHelper(input); // apply the mapping function
129 return hysteresis.update(input); // apply hysteresis, and return true
130 // if the value changed since last time
131 }
132
143 AnalogType getValue() const { return hysteresis.getValue(); }
144
152 float getFloatValue() const {
153 return getValue() * (1.0f / (ldexpf(1.0f, Precision) - 1.0f));
154 }
155
160 AnalogType getRawValue() const {
161 AnalogType value = ExtIO::analogRead(analogPin);
162#ifdef ESP8266
163 if (value > 1023)
164 value = 1023;
165#endif
167 }
168
172 constexpr static AnalogType getMaxRawValue() {
173 return (1ul << (ADC_BITS + IncRes)) - 1ul;
174 }
175
183 static void setupADC() {
184#if HAS_ANALOG_READ_RESOLUTION
185 analogReadResolution(ADC_BITS);
186#endif
187 }
188
189 private:
193 template <typename M = MappingFunction>
194 typename std::enable_if<std::is_constructible<bool, M>::value,
195 AnalogType>::type
196 mapFnHelper(AnalogType input) {
197 return bool(mapFn) ? mapFn(input) : input;
198 }
199
204 template <typename M = MappingFunction>
205 typename std::enable_if<!std::is_constructible<bool, M>::value,
206 AnalogType>::type
207 mapFnHelper(AnalogType input) {
208 return mapFn(input);
209 }
210
211 private:
214
216
217 static_assert(
218 ADC_BITS + IncRes + FilterShiftFactor <= sizeof(FilterType) * CHAR_BIT,
219 "Error: FilterType is not wide enough to hold the maximum value");
220 static_assert(
221 ADC_BITS + IncRes <= sizeof(AnalogType) * CHAR_BIT,
222 "Error: AnalogType is not wide enough to hold the maximum value");
223 static_assert(
224 Precision <= ADC_BITS + IncRes,
225 "Error: Precision is larger than the increased ADC precision");
226 static_assert(EMA_t::supports_range(AnalogType(0), getMaxRawValue()),
227 "Error: EMA filter type doesn't support full ADC range");
228
230 Hysteresis<ADC_BITS + IncRes - Precision, AnalogType, AnalogType>
232};
233
267template <uint8_t Precision = 10,
268 uint8_t FilterShiftFactor = ANALOG_FILTER_SHIFT_FACTOR,
269 class FilterType = ANALOG_FILTER_TYPE, class AnalogType = analog_t,
270 uint8_t IncRes = MaximumFilteredAnalogIncRes<
271 FilterShiftFactor, FilterType, AnalogType>::value>
273 : public GenericFilteredAnalog<AnalogType (*)(AnalogType), Precision,
274 FilterShiftFactor, FilterType, AnalogType,
275 IncRes> {
276 public:
285 FilteredAnalog(pin_t analogPin, AnalogType initial = 0)
286 : GenericFilteredAnalog<AnalogType (*)(AnalogType), Precision,
287 FilterShiftFactor, FilterType, AnalogType,
288 IncRes>(analogPin, nullptr, initial) {}
289
291 FilteredAnalog(ArduinoPin_t analogPin, AnalogType initial = 0)
292 : FilteredAnalog(pin_t(analogPin), initial) {}
293
303
306 using MappingFunction = AnalogType (*)(AnalogType);
307
315 void invert() {
316 constexpr AnalogType maxval = FilteredAnalog::getMaxRawValue();
317 this->map([](AnalogType val) -> AnalogType { return maxval - val; });
318 }
319};
320
#define END_AH_NAMESPACE
#define BEGIN_AH_NAMESPACE
AH::function_traits< decltype(::digitalWrite)>::argument_t< 0 > ArduinoPin_t
analog_t(*)(analog_t) MappingFunction
Definition Def.hpp:23
Exponential moving average filter.
Definition EMA.hpp:59
static constexpr bool supports_range(T min, T max)
Definition EMA.hpp:122
A class that reads and filters an analog input.
FilteredAnalog(pin_t analogPin, AnalogType initial=0)
Construct a new FilteredAnalog object.
FilteredAnalog(ArduinoPin_t analogPin, AnalogType initial=0)
Construct a new FilteredAnalog object.
FilteredAnalog()
Construct a new FilteredAnalog object.
void invert()
Invert the analog value.
AnalogType(*)(AnalogType) MappingFunction
A function pointer to a mapping function to map analog values.
FilteredAnalog base class with generic MappingFunction.
GenericFilteredAnalog(pin_t analogPin, MappingFunction mapFn, AnalogType initial=0)
Construct a new GenericFilteredAnalog object.
void resetToCurrentValue()
Reset the filtered value to the value that's currently being measured at the analog input.
static void setupADC()
Select the configured ADC resolution.
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.
EMA< FilterShiftFactor, AnalogType, FilterType > EMA_t
void map(MappingFunction fn)
Specify a mapping function/functor that is applied to the analog value after filtering and before app...
AnalogType getRawValue() const
Read the raw value of the analog input without any filtering or mapping applied, but with its bit dep...
void reset(AnalogType value=0)
Reset the filter to the given value.
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.
AnalogType getValue() const
Get the filtered value of the analog input (with the mapping function applied).
float getFloatValue() const
Get the filtered value of the analog input with the mapping function applied as a floating point numb...
bool update()
Read the analog input value, apply the mapping function, and update the average.
MappingFunction & getMappingFunction()
Get a reference to the mapping function.
GenericFilteredAnalog(ArduinoPin_t analogPin, MappingFunction mapFn, AnalogType initial=0)
Construct a new GenericFilteredAnalog object.
Hysteresis< ADC_BITS+IncRes - Precision, AnalogType, AnalogType > hysteresis
const MappingFunction & getMappingFunction() const
Get a reference to the mapping function.
static constexpr AnalogType getMaxRawValue()
Get the maximum value that can be returned from getRawValue.
A class for applying hysteresis to a given input.
analog_t analogRead(pin_t pin)
An ExtIO version of the Arduino function.
constexpr auto min(const T &a, const U &b) -> decltype(b< a ? b :a)
Return the smaller of two numbers/objects.
Definition MinMaxFix.hpp:12
T_out increaseBitDepth(T_in in)
Increase the bit depth of the given value from Bits_in bits wide to Bits_out bits wide,...
uint16_t analog_t
The type returned from analogRead and similar functions.
constexpr pin_t NO_PIN
A special pin number that indicates an unused or invalid pin.
constexpr uint8_t ANALOG_FILTER_SHIFT_FACTOR
The factor for the analog filter: Difference equation: where .
constexpr uint8_t ADC_BITS
The bit depth to use for the ADC (Analog to Digital Converter).
uint16_t ANALOG_FILTER_TYPE
The unsigned integer type to use for analog inputs during filtering.
Type for storing pin numbers of Extended Input/Output elements.
Helper to determine how many of the remaining bits of the filter data types can be used to achieve hi...
static constexpr uint8_t value