forked from letscontrolit/ESPEasy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request letscontrolit#5087 from TD-er/feature/improve_GPS_…
…time_accuracy [GPS] Improve GPS time stability
- Loading branch information
Showing
10 changed files
with
855 additions
and
490 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
#ifndef HELPERS_MODULOOVERSAMPLINGHELPER_H | ||
#define HELPERS_MODULOOVERSAMPLINGHELPER_H | ||
|
||
#include "../../ESPEasy_common.h" | ||
#include <limits> | ||
#include "../Helpers/OversamplingHelper.h" | ||
|
||
template<class T, class SUM_VALUE_TYPE = float> | ||
class ModuloOversamplingHelper { | ||
public: | ||
|
||
// When working with cyclical values which may 'overflow', | ||
// it is hard to compute an average. | ||
// For example with some angle in degrees, 359 and 1 degree are very close to eachother. | ||
// The expected average would be 0, however the numerical average is 180. | ||
// | ||
// Typical use cases: | ||
// - Compute direction in degrees (range 0 .. 359) | ||
// - Compute 'jitter' in some periodical signal | ||
// - Phase shift calculations | ||
ModuloOversamplingHelper() { | ||
// Just set some value for _modulo | ||
// so there will be no overflow when applying the offset | ||
// And we have a default constructor. | ||
// However it is highly unlikely this is a practical value, | ||
// so should not be run with this default value | ||
_modulo = std::numeric_limits<T>::max() / 2; | ||
} | ||
|
||
ModuloOversamplingHelper(T modulo) : _modulo(modulo) {} | ||
|
||
void setModulo(T modulo) { | ||
_modulo = modulo; | ||
reset(); | ||
} | ||
|
||
// Add new sample | ||
void add(T currentValue) { | ||
// Make sure the value is in range 0 ... (_modulo - 1) | ||
currentValue %= _modulo; | ||
|
||
if (_oversampling.getCount() == 0) { | ||
// Work with values centered around the middle of the modulo range. | ||
// Since the template type T can be unsigned, | ||
// must make sure the offset is positive. | ||
// N.B. _offset is always less than or equal to (_modulo / 2) | ||
const T modulo_halve = (_modulo / 2); | ||
|
||
if (currentValue > modulo_halve) { | ||
_offset = currentValue - modulo_halve; | ||
} else { | ||
_offset = modulo_halve - currentValue; | ||
} | ||
} | ||
|
||
T shiftedValue = currentValue + _offset; // FIXME TD-er: Could overflow | ||
|
||
if (shiftedValue > _modulo) { | ||
shiftedValue -= _modulo; | ||
} | ||
|
||
_oversampling.add(shiftedValue); | ||
} | ||
|
||
// Get current oversampling value without reset. | ||
// @param value Value will only be updated if there were samples available | ||
bool peek(SUM_VALUE_TYPE& value) const { | ||
if (!_oversampling.peek(value)) { | ||
return false; | ||
} | ||
|
||
if (value < _offset) { | ||
value += _modulo; | ||
} | ||
value -= _offset; | ||
return true; | ||
} | ||
|
||
// Get current oversampling value and reset. | ||
// @param value Value will only be updated if there were samples available | ||
bool get(SUM_VALUE_TYPE& value) { | ||
// Must call functions of this class and not just return _oversampling.get() | ||
// This way we are sure the _offset is properly applied | ||
if (peek(value)) { | ||
reset(); | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
// Return number of used samples | ||
uint32_t getCount() const { | ||
return _oversampling.getCount(); | ||
} | ||
|
||
// Clear all oversampling values | ||
void reset() { | ||
_oversampling.reset(); | ||
} | ||
|
||
// Clear all oversampling values and add last average if there were samples available. | ||
SUM_VALUE_TYPE resetKeepLast() { | ||
SUM_VALUE_TYPE value{}; | ||
|
||
// Must call functions of this class and not just return _oversampling.resetKeepLast() | ||
// This way we are sure the _offset is properly applied | ||
if (get(value)) { | ||
add(static_cast<T>(value)); | ||
} | ||
return value; | ||
} | ||
|
||
// Clear all oversampling values and add last average if there were samples available. | ||
// Last value will be added with a weight according to the given ratio of the last count. | ||
// @param countRatio New weight will be previous nr of samples / countRatio | ||
void resetKeepLastWeighted(int countRatio) { | ||
SUM_VALUE_TYPE value{}; | ||
const uint32_t count = getCount(); | ||
|
||
// Must call functions of this class and not just return _oversampling.resetKeepLast() | ||
// This way we are sure the _offset is properly applied | ||
if (get(value)) { | ||
if (count > countRatio) { | ||
const uint32_t weight = (count + (countRatio / 2)) / countRatio; | ||
|
||
for (uint32_t i = 0; i < weight; ++i) { | ||
add(static_cast<T>(value)); | ||
} | ||
} else { | ||
add(static_cast<T>(value)); | ||
} | ||
} | ||
} | ||
|
||
void setFilterPeaks(bool enable) { | ||
_oversampling.setFilterPeaks(enable); | ||
} | ||
|
||
private: | ||
|
||
OversamplingHelper<T, SUM_VALUE_TYPE>_oversampling; | ||
T _modulo; | ||
T _offset{}; | ||
}; | ||
|
||
#endif // ifndef HELPERS_MODULOOVERSAMPLINGHELPER_H |
Empty file.
Oops, something went wrong.