Dawn Framework 1.0
Universal data acquisition framework for embedded systems
movingavg.hxx
1// dawn/include/dawn/prog/movingavg.hxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#pragma once
7
8#include <algorithm>
9#include <cstdint>
10#include <cstring>
11#include <new>
12#include <vector>
13
14#include "dawn/io/ddata.hxx"
15#include "dawn/io/common.hxx"
16#include "dawn/porting/config.hxx"
17#include "dawn/prog/common.hxx"
18#include "dawn/prog/process.hxx"
19
20namespace dawn
21{
30{
31public:
32 enum
33 {
34 PROG_MOVAVG_CFG_WINDOW = 2,
35 };
36
37 explicit CProgMovingAverage(CDescObject &desc)
38 : CProgProcess(desc)
39 , window(1)
40 {
41 }
42
43#ifdef CONFIG_DAWN_OBJECT_HAS_NAME
44 const char *getClassNameStr() const override
45 {
46 return "movingavg";
47 }
48#endif
49
50 constexpr static SObjectId::ObjectId objectId(uint16_t inst)
51 {
54 }
55
56 constexpr static SObjectCfg::ObjectCfgId cfgId(bool rw, uint8_t size, uint8_t id)
57 {
61 rw,
62 size,
63 id);
64 }
65
66 constexpr static SObjectCfg::ObjectCfgId cfgIdIOBind(uint16_t size = 2)
67 {
68 return CProgMovingAverage::cfgId(false, size, PROG_STATS_CFG_IOBIND);
69 }
70
71 constexpr static SObjectCfg::ObjectCfgId cfgIdWindow()
72 {
73 return CProgMovingAverage::cfgId(false, 1, PROG_MOVAVG_CFG_WINDOW);
74 }
75
76protected:
79 size_t &offset) override
80 {
81 (void)desc;
82 (void)offset;
83
84 switch (item->cfgid.s.id)
85 {
86 case PROG_MOVAVG_CFG_WINDOW:
87 {
89
90 if (item->cfgid.s.size != 1)
91 {
92 DAWNERR("movingavg: invalid WINDOW size %u\n", item->cfgid.s.size);
93 return -EINVAL;
94 }
95
96 raw = reinterpret_cast<const SObjectCfg::ObjectCfgData_t *>(item->data);
97 window = SObjectCfg::cfgToU32(raw[0]);
98 if (window == 0)
99 {
100 DAWNERR("movingavg: window must be > 0\n");
101 return -EINVAL;
102 }
103
104 return OK;
105 }
106
107 default:
108 {
109 return -ENOTSUP;
110 }
111 }
112 }
113
115 CIOCommon *output,
116 io_ddata_t *ioData,
117 io_ddata_t *outputData,
118 SBindState **state) override
119 {
120 (void)output;
121 (void)outputData;
122
123 switch (src->getDtype())
124 {
125#ifdef CONFIG_DAWN_DTYPE_INT8
127 return allocState<int8_t, int64_t, int64_t>(ioData->getItems(), state);
128#endif
129#ifdef CONFIG_DAWN_DTYPE_UINT8
131 return allocState<uint8_t, uint64_t, uint64_t>(ioData->getItems(), state);
132#endif
133#ifdef CONFIG_DAWN_DTYPE_INT16
135 return allocState<int16_t, int64_t, int64_t>(ioData->getItems(), state);
136#endif
137#ifdef CONFIG_DAWN_DTYPE_UINT16
139 return allocState<uint16_t, uint64_t, uint64_t>(ioData->getItems(), state);
140#endif
141#ifdef CONFIG_DAWN_DTYPE_INT32
143 return allocState<int32_t, int64_t, int64_t>(ioData->getItems(), state);
144#endif
145#ifdef CONFIG_DAWN_DTYPE_UINT32
147 return allocState<uint32_t, uint64_t, uint64_t>(ioData->getItems(), state);
148#endif
149#ifdef CONFIG_DAWN_DTYPE_INT64
151 return allocState<int64_t, int64_t, int64_t>(ioData->getItems(), state);
152#endif
153#ifdef CONFIG_DAWN_DTYPE_UINT64
155 return allocState<uint64_t, uint64_t, uint64_t>(ioData->getItems(), state);
156#endif
157#ifdef CONFIG_DAWN_DTYPE_FLOAT
159 return allocState<float, float, float>(ioData->getItems(), state);
160#endif
161#ifdef CONFIG_DAWN_DTYPE_DOUBLE
163 return allocState<double, double, double>(ioData->getItems(), state);
164#endif
165 default:
166 {
167 DAWNERR("movingavg: unsupported dtype %d\n", src->getDtype());
168 return -ENOTSUP;
169 }
170 }
171 }
172
173 void handle(CIOCommon *output,
174 io_ddata_t *data,
175 io_ddata_t *ioData,
176 io_ddata_t *outputData,
177 bool &initsample) override
178 {
179 handleWithState(output, data, ioData, outputData, initsample, nullptr);
180 }
181
183 io_ddata_t *data,
184 io_ddata_t *ioData,
185 io_ddata_t *outputData,
186 bool &initsample,
187 void *state) override
188 {
189 if (state == nullptr)
190 {
191 DAWNERR("movingavg: missing state\n");
192 return;
193 }
194
195 if (initsample)
196 {
197 static_cast<SBindState *>(state)->reset();
198 initsample = false;
199 }
200
201 switch (data->getDtype())
202 {
203#ifdef CONFIG_DAWN_DTYPE_INT8
205 handleTyped<int8_t, int64_t, int64_t>(output, data, ioData, outputData, state);
206 break;
207#endif
208#ifdef CONFIG_DAWN_DTYPE_UINT8
210 handleTyped<uint8_t, uint64_t, uint64_t>(output, data, ioData, outputData, state);
211 break;
212#endif
213#ifdef CONFIG_DAWN_DTYPE_INT16
215 handleTyped<int16_t, int64_t, int64_t>(output, data, ioData, outputData, state);
216 break;
217#endif
218#ifdef CONFIG_DAWN_DTYPE_UINT16
220 handleTyped<uint16_t, uint64_t, uint64_t>(output, data, ioData, outputData, state);
221 break;
222#endif
223#ifdef CONFIG_DAWN_DTYPE_INT32
225 handleTyped<int32_t, int64_t, int64_t>(output, data, ioData, outputData, state);
226 break;
227#endif
228#ifdef CONFIG_DAWN_DTYPE_UINT32
230 handleTyped<uint32_t, uint64_t, uint64_t>(output, data, ioData, outputData, state);
231 break;
232#endif
233#ifdef CONFIG_DAWN_DTYPE_INT64
235 handleTyped<int64_t, int64_t, int64_t>(output, data, ioData, outputData, state);
236 break;
237#endif
238#ifdef CONFIG_DAWN_DTYPE_UINT64
240 handleTyped<uint64_t, uint64_t, uint64_t>(output, data, ioData, outputData, state);
241 break;
242#endif
243#ifdef CONFIG_DAWN_DTYPE_FLOAT
245 handleTyped<float, float, float>(output, data, ioData, outputData, state);
246 break;
247#endif
248#ifdef CONFIG_DAWN_DTYPE_DOUBLE
250 handleTyped<double, double, double>(output, data, ioData, outputData, state);
251 break;
252#endif
253 default:
254 {
255 DAWNERR("movingavg: unsupported dtype %d\n", data->getDtype());
256 break;
257 }
258 }
259 }
260
261private:
262 template<typename T, typename HistT, typename SumT>
263 struct SState final : public SBindState
264 {
265 uint32_t count = 0;
266 uint32_t pos = 0;
267 uint32_t items = 0;
268 std::vector<HistT> hist;
269 std::vector<SumT> sum;
270
271 void reset() override
272 {
273 count = 0;
274 pos = 0;
275 std::fill(hist.begin(), hist.end(), static_cast<HistT>(0));
276 std::fill(sum.begin(), sum.end(), static_cast<SumT>(0));
277 }
278 };
279
280 template<typename T, typename HistT, typename SumT>
281 int allocState(size_t items, SBindState **state)
282 {
283 SState<T, HistT, SumT> *st;
284
285 st = new (std::nothrow) SState<T, HistT, SumT>();
286 if (st == nullptr)
287 {
288 return -ENOMEM;
289 }
290
291 st->items = items;
292 st->hist.assign(items * window, static_cast<HistT>(0));
293 st->sum.assign(items, static_cast<SumT>(0));
294 if (st->hist.size() != items * window || st->sum.size() != items)
295 {
296 delete st;
297 return -ENOMEM;
298 }
299
300 *state = st;
301 return OK;
302 }
303
304 template<typename T, typename HistT, typename SumT>
305 void handleTyped(CIOCommon *output,
306 io_ddata_t *data,
307 io_ddata_t *ioData,
308 io_ddata_t *outputData,
309 void *state)
310 {
311 SState<T, HistT, SumT> *st = static_cast<SState<T, HistT, SumT> *>(state);
312 const size_t items = ioData->getItems();
313 const uint32_t used = (st->count < window) ? st->count : window;
314
315 std::memcpy(ioData->getDataPtr(), data->getDataPtr(), ioData->getDataSize());
316
317 if (st->items != items)
318 {
319 DAWNERR("movingavg: item count changed from %u to %zu\n", st->items, items);
320 return;
321 }
322
323 for (size_t i = 0; i < items; i++)
324 {
325 const size_t hidx = i * window + st->pos;
326 const HistT x = static_cast<HistT>(ioData->get<T>(i));
327
328 if (used == window)
329 {
330 st->sum[i] -= st->hist[hidx];
331 }
332
333 st->hist[hidx] = x;
334 st->sum[i] += x;
335 }
336
337 if (st->count < window)
338 {
339 st->count++;
340 }
341
342 st->pos = (st->pos + 1) % window;
343
344 for (size_t i = 0; i < items; i++)
345 {
346 outputData->get<T>(i) = static_cast<T>(st->sum[i] / static_cast<SumT>(st->count));
347 }
348
349 output->setData(*outputData);
350 }
351
352 uint32_t window;
353};
354} // Namespace dawn
Descriptor wrapper for individual object configuration.
Base class for all I/O objects.
Definition common.hxx:27
uint8_t getDtype() const
Get data type field.
Definition object.cxx:175
@ PROG_CLASS_MOVING_AVG
Moving average filter.
Definition common.hxx:87
Notify-driven sliding window moving average filter.
Definition movingavg.hxx:30
int bindStateAlloc(CIOCommon *src, CIOCommon *output, io_ddata_t *ioData, io_ddata_t *outputData, SBindState **state)
Allocate optional per-binding derived state.
void handleWithState(CIOCommon *output, io_ddata_t *data, io_ddata_t *ioData, io_ddata_t *outputData, bool &initsample, void *state)
Process incoming sample with optional per-binding state.
int configureExtraCfgItem(const CDescObject &desc, const SObjectCfg::SObjectCfgItem *item, size_t &offset)
Parse program-specific config item (optional extension hook).
Definition movingavg.hxx:77
void handle(CIOCommon *output, io_ddata_t *data, io_ddata_t *ioData, io_ddata_t *outputData, bool &initsample)
Process incoming sample.
Base class for callback-driven sample processing Program objects.
Definition process.hxx:28
@ PROG_STATS_CFG_IOBIND
I/O binding configuration.
Definition process.hxx:35
static ObjectCfgId objectCfg(uint8_t type, uint16_t cls, uint8_t dtype, bool rw, uint16_t size, uint8_t id)
Construct 32-bit ConfigID from component fields.
uint32_t ObjectCfgId
ConfigID type - single 32-bit value.
Definition objectcfg.hxx:60
uint32_t ObjectCfgData_t
Configuration data element - single 32-bit word.
Definition objectcfg.hxx:69
static uint32_t cfgToU32(ObjectCfgData_t x)
Convert ObjectCfgData_t to uint32_t.
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Single configuration item within object.
ObjectCfgData_t data[]
Configuration data array (flexible, size from cfgid.s.size).
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
@ OBJTYPE_PROG
Program/algorithm object type.
Definition objectid.hxx:202
@ DTYPE_FLOAT
IEEE 754 single-precision floating point (32-bit).
Definition objectid.hxx:112
@ DTYPE_INT32
Signed 32-bit integer (-2147483648 to 2147483647).
Definition objectid.hxx:92
@ DTYPE_UINT8
Unsigned 8-bit integer (0 to 255).
Definition objectid.hxx:80
@ DTYPE_INT16
Signed 16-bit integer (-32768 to 32767).
Definition objectid.hxx:84
@ DTYPE_INT8
Signed 8-bit integer (-128 to 127).
Definition objectid.hxx:76
@ DTYPE_ANY
Wildcard data type (matches any actual type).
Definition objectid.hxx:68
@ DTYPE_UINT64
Unsigned 64-bit integer.
Definition objectid.hxx:104
@ DTYPE_UINT16
Unsigned 16-bit integer (0 to 65535).
Definition objectid.hxx:88
@ DTYPE_DOUBLE
IEEE 754 double-precision floating point (64-bit).
Definition objectid.hxx:120
@ DTYPE_INT64
Signed 64-bit integer.
Definition objectid.hxx:100
@ DTYPE_UINT32
Unsigned 32-bit integer (0 to 4294967295).
Definition objectid.hxx:96
uint32_t ObjectId
ObjectID type - single 32-bit value.
Definition objectid.hxx:44
static ObjectId objectId(uint8_t type, uint16_t cls, uint8_t dtype, uint8_t flags, uint16_t priv)
Construct 32-bit ObjectID from component fields.
Definition objectid.hxx:290
Heap-allocated dynamic I/O data buffer.
Definition ddata.hxx:21
uint8_t getDtype() const
Get data type enum for introspection.
Definition ddata.hxx:217
size_t getItems()
Get number of items per batch.
Definition ddata.hxx:128
uint32_t id
Configuration identifier (bits 0-4, max 31).
Definition objectcfg.hxx:94
uint32_t size
Configuration data size in 32-bit words (bits 5-14, max 1023).
struct dawn::SObjectCfg::UObjectCfgId::@10 s
Bit-field structure for named member access.