AFBR-S50 API Reference Manual  v1.6.5
AFBR-S50 Time-of-Flight Sensor SDK for Embedded Software
fp_ema.h
Go to the documentation of this file.
1 /*************************************************************************/
37 #ifndef FP_EMA_H
38 #define FP_EMA_H
39 #ifdef __cplusplus
40 extern "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  *****************************************************************************/
85 inline uq1_15_t fp_ema15c(uq1_15_t mean, uq1_15_t x, uq0_8_t weight)
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  *****************************************************************************/
105 inline 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  *****************************************************************************/
124 inline uq12_4_t fp_ema4u(uq12_4_t mean, uq12_4_t x, uq0_8_t weight)
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  *****************************************************************************/
153 inline 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  *****************************************************************************/
169 inline 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  *****************************************************************************/
196 inline 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  *****************************************************************************/
224 inline q15_16_t fp_ema16(q15_16_t mean, q15_16_t x, uq0_8_t weight)
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 */
fp_ema16
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
fp_ema15c
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
fp_ema8
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
q7_8_t
int16_t q7_8_t
Signed fixed point number: Q7.8.
Definition: fp_def.h:335
uq0_8_t
uint8_t uq0_8_t
Unsigned fixed point number: UQ0.8.
Definition: fp_def.h:162
uint_ema32
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
fp_ema4u
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
fp_rnd.h
This file is part of the AFBR-S50 API.
uq12_4_t
uint16_t uq12_4_t
Unsigned fixed point number: UQ12.4.
Definition: fp_def.h:231
fp_mul.h
This file is part of the AFBR-S50 API.
fp_ema4
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
fp_def.h
This file is part of the AFBR-S50 API.
fp_mulu
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
fp_rndu
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
fp_rnds
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
int_ema32
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
q15_16_t
int32_t q15_16_t
Signed fixed point number: Q15.16.
Definition: fp_def.h:515
q11_4_t
int16_t q11_4_t
Signed fixed point number: Q11.4.
Definition: fp_def.h:312
uq1_15_t
uint16_t uq1_15_t
Unsigned fixed point number: UQ1.15.
Definition: fp_def.h:271