AFBR-S50 API Reference Manual v1.6.5
AFBR-S50 Time-of-Flight Sensor SDK for Embedded Software
Loading...
Searching...
No Matches
fp_ema.h
Go to the documentation of this file.
1/*************************************************************************/
37#ifndef FP_EMA_H
38#define FP_EMA_H
39#ifdef __cplusplus
40extern "C" {
41#endif
42
43/*!***************************************************************************
44 * @addtogroup argus_fp
45 * @{
46 *****************************************************************************/
47
48#include "fp_def.h"
49
50#include "utility/fp_rnd.h"
51#include "utility/fp_mul.h"
52
53/*!***************************************************************************
54 * @brief Circular exponentially weighted moving average using UQ1.15 format.
55 *
56 * @details Evaluates the moving average (exponentially weighted) for circular
57 * data in UQ1.15 format.
58 * Circular data is that MAX_VALUE + 1 == MIN_VALUE. For example the
59 * usual phase information.
60 *
61 * Problem: Due to circularity of phase values, i.e. 0+x and 2PI+x are
62 * the same, the usual EMA has issues with the wrap around effect.
63 * Especially for vectors with phase around 0 (or 2PI), two values
64 * like 0 + x and PI - y are averaged to something around PI instead
65 * of 0 which would be more correct.
66 *
67 * Solution: Assume that phase jumps of more than PI are not allowed
68 * or possible. If a deviation of the new value to the smoothed signal
69 * occurs, it is clear that this stems from the wrap around effect and
70 * can be caught and correctly handled by the smoothing algorithm.
71 *
72 * Caution: If a target comes immediately into the field of view, phase
73 * jumps of > PI are indeed possible and volitional. However, the
74 * averaging break there anyway since the smoothed signal approaches
75 * only with delay to the correct values. The error made here is, that
76 * the smoothed signal approaches from the opposite direction. However,
77 * is approaches even faster since it always takes the shortest
78 * direction.
79 *
80 * @param mean The previous mean value in UQ1.15 format.
81 * @param x The current value to be added to the average UQ1.15 format.
82 * @param weight The EMA weight in UQ0.8 format.
83 * @return The new mean value in UQ1.15 format.
84 *****************************************************************************/
86{
87 if (weight == 0) return x;
88 // Heeds the wrap around effect by casting dx to int16:
89 const int16_t dx = (int16_t)(x - mean);
90 const int32_t diff = weight * dx;
91 return (uq1_15_t)fp_rnds((mean << 8U) + diff, 8U);
92}
93
94/*!***************************************************************************
95 * @brief Exponentially weighted moving average using the Q11.4 format.
96 *
97 * @details Evaluates the moving average (exponentially weighted) for data in
98 * Q11.4 format.
99 *
100 * @param mean The previous mean value in Q11.4 format.
101 * @param x The current value to be added to the average Q11.4 format.
102 * @param weight The EMA weight in UQ0.8 format.
103 * @return The new mean value in Q11.4 format.
104 *****************************************************************************/
105inline q11_4_t fp_ema4(q11_4_t mean, q11_4_t x, uq0_8_t weight)
106{
107 if (weight == 0) return x;
108 const int32_t dx = x - mean;
109 const int32_t diff = weight * dx;
110 return (q11_4_t)fp_rnds((mean << 8U) + diff, 8U);
111}
112
113/*!***************************************************************************
114 * @brief Exponentially weighted moving average using the UQ12.4 format.
115 *
116 * @details Evaluates the moving average (exponentially weighted) for data in
117 * UQ12.4 format.
118 *
119 * @param mean The previous mean value in UQ12.4 format.
120 * @param x The current value to be added to the average UQ12.4 format.
121 * @param weight The EMA weight in UQ0.8 format.
122 * @return The new mean value in UQ12.4 format.
123 *****************************************************************************/
125{
126 if (weight == 0) return x;
127
128 if (x > mean)
129 {
130 const uq12_4_t dx = x - mean;
131 const uint32_t diff = weight * dx;
132 return (uq12_4_t)fp_rndu((mean << 8U) + diff, 8U);
133 }
134 else
135 {
136 const uq12_4_t dx = mean - x;
137 const uint32_t diff = weight * dx;
138 return (uq12_4_t)fp_rndu((mean << 8U) - diff, 8U);
139 }
140}
141
142/*!***************************************************************************
143 * @brief Exponentially weighted moving average using the Q7.8 format.
144 *
145 * @details Evaluates the moving average (exponentially weighted) for data in
146 * Q7.8 format.
147 *
148 * @param mean The previous mean value in Q7.8 format.
149 * @param x The current value to be added to the average Q7.8 format.
150 * @param weight The EMA weight in UQ0.8 format.
151 * @return The new mean value in Q7.8 format.
152 *****************************************************************************/
153inline q7_8_t fp_ema8(q7_8_t mean, q7_8_t x, uq0_8_t weight)
154{
155 return (q7_8_t)fp_ema4(mean, x, weight);
156}
157
158/*!***************************************************************************
159 * @brief Exponentially weighted moving average using the Q15.16 format.
160 *
161 * @details Evaluates the moving average (exponentially weighted) for data in
162 * Q15.16 format.
163 *
164 * @param mean The previous mean value in Q15.16 format.
165 * @param x The current value to be added to the average Q15.16 format.
166 * @param weight The EMA weight in UQ0.8 format.
167 * @return The new mean value in Q15.16 format.
168 *****************************************************************************/
169inline uint32_t uint_ema32(uint32_t mean, uint32_t x, uq0_8_t weight)
170{
171 if (weight == 0) return x;
172 if (x > mean)
173 {
174 const uint32_t dx = x - mean;
175 const uint32_t diff = fp_mulu(weight, dx, 8U);
176 return mean + diff;
177 }
178 else
179 {
180 const uint32_t dx = mean - x;
181 const uint32_t diff = fp_mulu(weight, dx, 8U);
182 return mean - diff;
183 }
184}
185/*!***************************************************************************
186 * @brief Exponentially weighted moving average using the Q15.16 format.
187 *
188 * @details Evaluates the moving average (exponentially weighted) for data in
189 * Q15.16 format.
190 *
191 * @param mean The previous mean value in Q15.16 format.
192 * @param x The current value to be added to the average Q15.16 format.
193 * @param weight The EMA weight in UQ0.8 format.
194 * @return The new mean value in Q15.16 format.
195 *****************************************************************************/
196inline int32_t int_ema32(int32_t mean, int32_t x, uq0_8_t weight)
197{
198 if (weight == 0) return x;
199 if (x > mean)
200 {
201 const uint32_t dx = x - mean;
202 const uint32_t diff = fp_mulu(weight, dx, 8U);
203 return mean + diff;
204 }
205 else
206 {
207 const uint32_t dx = mean - x;
208 const uint32_t diff = fp_mulu(weight, dx, 8U);
209 return mean - diff;
210 }
211}
212
213/*!***************************************************************************
214 * @brief Exponentially weighted moving average using the Q15.16 format.
215 *
216 * @details Evaluates the moving average (exponentially weighted) for data in
217 * Q15.16 format.
218 *
219 * @param mean The previous mean value in Q15.16 format.
220 * @param x The current value to be added to the average Q15.16 format.
221 * @param weight The EMA weight in UQ0.8 format.
222 * @return The new mean value in Q15.16 format.
223 *****************************************************************************/
225{
226 return (q15_16_t)int_ema32(mean, x, weight);
227}
228
230#ifdef __cplusplus
231} // extern "C"
232#endif
233#endif /* FP_EMA_H */
This file is part of the AFBR-S50 API.
This file is part of the AFBR-S50 API.
This file is part of the AFBR-S50 API.
uq1_15_t fp_ema15c(uq1_15_t mean, uq1_15_t x, uq0_8_t weight)
Circular exponentially weighted moving average using UQ1.15 format.
Definition fp_ema.h:85
uint32_t fp_rndu(uint32_t Q, uint_fast8_t n)
Converting with rounding from UQx.n1 to UQx.n2.
Definition fp_rnd.h:60
q15_16_t fp_ema16(q15_16_t mean, q15_16_t x, uq0_8_t weight)
Exponentially weighted moving average using the Q15.16 format.
Definition fp_ema.h:224
uint32_t uint_ema32(uint32_t mean, uint32_t x, uq0_8_t weight)
Exponentially weighted moving average using the Q15.16 format.
Definition fp_ema.h:169
uint8_t uq0_8_t
Unsigned fixed point number: UQ0.8.
Definition fp_def.h:162
uint32_t fp_mulu(uint32_t u, uint32_t v, uint_fast8_t shift)
64-bit implementation of an unsigned multiplication with fixed point format.
Definition fp_mul.h:116
int32_t fp_rnds(int32_t Q, uint_fast8_t n)
Converting with rounding from Qx.n1 to Qx.n2.
Definition fp_rnd.h:80
int32_t int_ema32(int32_t mean, int32_t x, uq0_8_t weight)
Exponentially weighted moving average using the Q15.16 format.
Definition fp_ema.h:196
uint16_t uq1_15_t
Unsigned fixed point number: UQ1.15.
Definition fp_def.h:271
q11_4_t fp_ema4(q11_4_t mean, q11_4_t x, uq0_8_t weight)
Exponentially weighted moving average using the Q11.4 format.
Definition fp_ema.h:105
uq12_4_t fp_ema4u(uq12_4_t mean, uq12_4_t x, uq0_8_t weight)
Exponentially weighted moving average using the UQ12.4 format.
Definition fp_ema.h:124
int16_t q7_8_t
Signed fixed point number: Q7.8.
Definition fp_def.h:335
int32_t q15_16_t
Signed fixed point number: Q15.16.
Definition fp_def.h:515
q7_8_t fp_ema8(q7_8_t mean, q7_8_t x, uq0_8_t weight)
Exponentially weighted moving average using the Q7.8 format.
Definition fp_ema.h:153
uint16_t uq12_4_t
Unsigned fixed point number: UQ12.4.
Definition fp_def.h:231
int16_t q11_4_t
Signed fixed point number: Q11.4.
Definition fp_def.h:312