Dawn Framework 1.0
Universal data acquisition framework for embedded systems
iirfilter.hxx
1// dawn/include/dawn/prog/iirfilter.hxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#pragma once
7
8#include <cstdint>
9#include <cstring>
10#include <limits>
11
12#include "dawn/io/ddata.hxx"
13#include "dawn/io/common.hxx"
14#include "dawn/porting/config.hxx"
15#include "dawn/prog/common.hxx"
16#include "dawn/prog/process.hxx"
17
18namespace dawn
19{
29{
30public:
31 enum
32 {
33 PROG_IIR_CFG_ALPHA_NUM = 2,
34 PROG_IIR_CFG_ALPHA_DEN = 3,
35 };
36
37 explicit CProgIIRFilter(CDescObject &desc)
38 : CProgProcess(desc)
39 , alphaNum(1)
40 , alphaDen(1)
41 {
42 }
43
44#ifdef CONFIG_DAWN_OBJECT_HAS_NAME
45 const char *getClassNameStr() const override
46 {
47 return "iir";
48 }
49#endif
50
51 constexpr static SObjectId::ObjectId objectId(uint16_t inst)
52 {
55 }
56
57 constexpr static SObjectCfg::ObjectCfgId cfgId(bool rw, uint8_t size, uint8_t id)
58 {
62 rw,
63 size,
64 id);
65 }
66
67 constexpr static SObjectCfg::ObjectCfgId cfgIdIOBind(uint16_t size = 2)
68 {
69 return CProgIIRFilter::cfgId(false, size, PROG_STATS_CFG_IOBIND);
70 }
71
72 constexpr static SObjectCfg::ObjectCfgId cfgIdAlphaNum()
73 {
74 return CProgIIRFilter::cfgId(false, 1, PROG_IIR_CFG_ALPHA_NUM);
75 }
76
77 constexpr static SObjectCfg::ObjectCfgId cfgIdAlphaDen()
78 {
79 return CProgIIRFilter::cfgId(false, 1, PROG_IIR_CFG_ALPHA_DEN);
80 }
81
82protected:
85 size_t &offset) override
86 {
88 uint32_t val;
89
90 (void)desc;
91 (void)offset;
92
93 if (item->cfgid.s.size != 1)
94 {
95 DAWNERR("iir: invalid alpha config size %u\n", item->cfgid.s.size);
96 return -EINVAL;
97 }
98
99 raw = reinterpret_cast<const SObjectCfg::ObjectCfgData_t *>(item->data);
100 val = SObjectCfg::cfgToU32(raw[0]);
101
102 switch (item->cfgid.s.id)
103 {
104 case PROG_IIR_CFG_ALPHA_NUM:
105 alphaNum = val;
106 break;
107 case PROG_IIR_CFG_ALPHA_DEN:
108 alphaDen = val;
109 break;
110 default:
111 return -ENOTSUP;
112 }
113
114 if (alphaDen == 0 || alphaNum > alphaDen)
115 {
116 DAWNERR("iir: invalid alpha %u/%u\n", alphaNum, alphaDen);
117 return -EINVAL;
118 }
119
120 return OK;
121 }
122
123 void handle(CIOCommon *output,
124 io_ddata_t *data,
125 io_ddata_t *ioData,
126 io_ddata_t *outputData,
127 bool &initsample) override
128 {
129 switch (data->getDtype())
130 {
131#ifdef CONFIG_DAWN_DTYPE_INT8
133 {
134 handleSigned<int8_t>(output, data, ioData, outputData, initsample);
135 break;
136 }
137#endif
138
139#ifdef CONFIG_DAWN_DTYPE_UINT8
141 {
142 handleUnsigned<uint8_t>(output, data, ioData, outputData, initsample);
143 break;
144 }
145#endif
146
147#ifdef CONFIG_DAWN_DTYPE_INT16
149 {
150 handleSigned<int16_t>(output, data, ioData, outputData, initsample);
151 break;
152 }
153#endif
154
155#ifdef CONFIG_DAWN_DTYPE_UINT16
157 {
158 handleUnsigned<uint16_t>(output, data, ioData, outputData, initsample);
159 break;
160 }
161#endif
162
163#ifdef CONFIG_DAWN_DTYPE_INT32
165 {
166 handleSigned<int32_t>(output, data, ioData, outputData, initsample);
167 break;
168 }
169#endif
170
171#ifdef CONFIG_DAWN_DTYPE_UINT32
173 {
174 handleUnsigned<uint32_t>(output, data, ioData, outputData, initsample);
175 break;
176 }
177#endif
178
179#ifdef CONFIG_DAWN_DTYPE_B16
181 {
182 handleSigned<int32_t>(output, data, ioData, outputData, initsample);
183 break;
184 }
185#endif
186
187#ifdef CONFIG_DAWN_DTYPE_UB16
189 {
190 handleUnsigned<uint32_t>(output, data, ioData, outputData, initsample);
191 break;
192 }
193#endif
194
195#ifdef CONFIG_DAWN_DTYPE_FLOAT
197 {
198 handleFloat<float>(output, data, ioData, outputData, initsample);
199 break;
200 }
201#endif
202
203#ifdef CONFIG_DAWN_DTYPE_DOUBLE
205 {
206 handleFloat<double>(output, data, ioData, outputData, initsample);
207 break;
208 }
209#endif
210
211 default:
212 {
213 DAWNERR("iir: unsupported dtype %d\n", data->getDtype());
214 break;
215 }
216 }
217 }
218
219private:
220 void handleInitSample(CIOCommon *output,
221 io_ddata_t *data,
222 io_ddata_t *ioData,
223 io_ddata_t *outputData,
224 bool &initsample)
225 {
226 std::memcpy(ioData->getDataPtr(), data->getDataPtr(), ioData->getDataSize());
227 std::memcpy(outputData->getDataPtr(), data->getDataPtr(), outputData->getDataSize());
228 output->setData(*outputData);
229 initsample = false;
230 }
231
232 static int64_t scaleDelta(int64_t diff, uint32_t num, uint32_t den)
233 {
234 const bool negative = diff < 0;
235 const uint64_t magnitude =
236 negative ? static_cast<uint64_t>(-diff) : static_cast<uint64_t>(diff);
237 const uint64_t quotient = magnitude / den;
238 const uint64_t remainder = magnitude % den;
239 const uint64_t scaled = quotient * static_cast<uint64_t>(num) +
240 (remainder * static_cast<uint64_t>(num)) / static_cast<uint64_t>(den);
241
242 return negative ? -static_cast<int64_t>(scaled) : static_cast<int64_t>(scaled);
243 }
244
245 template<typename T>
246 static T clampSigned(int64_t value)
247 {
248 const int64_t min = static_cast<int64_t>(std::numeric_limits<T>::lowest());
249 const int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max());
250
251 if (value < min)
252 {
253 return std::numeric_limits<T>::lowest();
254 }
255
256 if (value > max)
257 {
258 return std::numeric_limits<T>::max();
259 }
260
261 return static_cast<T>(value);
262 }
263
264 template<typename T>
265 static T clampUnsigned(int64_t value)
266 {
267 const int64_t max = static_cast<int64_t>(std::numeric_limits<T>::max());
268
269 if (value < 0)
270 {
271 return 0;
272 }
273
274 if (value > max)
275 {
276 return std::numeric_limits<T>::max();
277 }
278
279 return static_cast<T>(value);
280 }
281
282 template<typename T>
283 void handleSigned(CIOCommon *output,
284 io_ddata_t *data,
285 io_ddata_t *ioData,
286 io_ddata_t *outputData,
287 bool &initsample)
288 {
289 if (initsample)
290 {
291 handleInitSample(output, data, ioData, outputData, initsample);
292 return;
293 }
294
295 std::memcpy(ioData->getDataPtr(), data->getDataPtr(), ioData->getDataSize());
296
297 for (size_t i = 0; i < ioData->getItems(); i++)
298 {
299 const int64_t x = ioData->get<T>(i);
300 int64_t y = outputData->get<T>(i);
301 const int64_t diff = x - y;
302 y += scaleDelta(diff, alphaNum, alphaDen);
303 outputData->get<T>(i) = clampSigned<T>(y);
304 }
305
306 output->setData(*outputData);
307 }
308
309 template<typename T>
310 void handleUnsigned(CIOCommon *output,
311 io_ddata_t *data,
312 io_ddata_t *ioData,
313 io_ddata_t *outputData,
314 bool &initsample)
315 {
316 if (initsample)
317 {
318 handleInitSample(output, data, ioData, outputData, initsample);
319 return;
320 }
321
322 std::memcpy(ioData->getDataPtr(), data->getDataPtr(), ioData->getDataSize());
323
324 for (size_t i = 0; i < ioData->getItems(); i++)
325 {
326 const int64_t x = ioData->get<T>(i);
327 int64_t y = outputData->get<T>(i);
328 const int64_t diff = x - y;
329 y += scaleDelta(diff, alphaNum, alphaDen);
330 outputData->get<T>(i) = clampUnsigned<T>(y);
331 }
332
333 output->setData(*outputData);
334 }
335
336 template<typename T>
337 void handleFloat(CIOCommon *output,
338 io_ddata_t *data,
339 io_ddata_t *ioData,
340 io_ddata_t *outputData,
341 bool &initsample)
342 {
343 if (initsample)
344 {
345 handleInitSample(output, data, ioData, outputData, initsample);
346 return;
347 }
348
349 std::memcpy(ioData->getDataPtr(), data->getDataPtr(), ioData->getDataSize());
350
351 const T alpha = static_cast<T>(alphaNum) / static_cast<T>(alphaDen);
352
353 for (size_t i = 0; i < ioData->getItems(); i++)
354 {
355 const T x = ioData->get<T>(i);
356 T y = outputData->get<T>(i);
357 y += (x - y) * alpha;
358 outputData->get<T>(i) = y;
359 }
360
361 output->setData(*outputData);
362 }
363
364 uint32_t alphaNum;
365 uint32_t alphaDen;
366};
367} // Namespace dawn
Descriptor wrapper for individual object configuration.
Base class for all I/O objects.
Definition common.hxx:27
int setData(IODataCmn &data, size_t offset=0)
Set data for I/O (public interface with stats tracking).
Definition common.hxx:392
@ PROG_CLASS_IIR_FILTER
First-order IIR filter.
Definition common.hxx:91
First-order IIR low-pass filter.
Definition iirfilter.hxx:29
void handle(CIOCommon *output, io_ddata_t *data, io_ddata_t *ioData, io_ddata_t *outputData, bool &initsample)
Process incoming sample.
int configureExtraCfgItem(const CDescObject &desc, const SObjectCfg::SObjectCfgItem *item, size_t &offset)
Parse program-specific config item (optional extension hook).
Definition iirfilter.hxx:83
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_UINT16
Unsigned 16-bit integer (0 to 65535).
Definition objectid.hxx:88
@ DTYPE_UB16
Unsigned 16.16 fixed-point (32-bit).
Definition objectid.hxx:132
@ DTYPE_DOUBLE
IEEE 754 double-precision floating point (64-bit).
Definition objectid.hxx:120
@ DTYPE_UINT32
Unsigned 32-bit integer (0 to 4294967295).
Definition objectid.hxx:96
@ DTYPE_B16
Signed 16.16 fixed-point (32-bit).
Definition objectid.hxx:128
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 getDataSize()
Get data size in bytes.
Definition ddata.hxx:153
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
Definition ddata.hxx:180
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.