Dawn Framework 1.0
Universal data acquisition framework for embedded systems
threshold.hxx
1// dawn/include/dawn/prog/threshold.hxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#pragma once
7
8#include <cstdint>
9#include <cstring>
10#include <inttypes.h>
11#include <map>
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{
25{
26public:
27 enum
28 {
29 PROG_THRESHOLD_CFG_MODE = 2,
30 PROG_THRESHOLD_CFG_LOW = 3,
31 PROG_THRESHOLD_CFG_HIGH = 4,
32 };
33
34 enum
35 {
36 MODE_ABOVE = 0,
37 MODE_BELOW = 1,
38 MODE_HYSTERESIS = 2,
39 MODE_WINDOW = 3,
40 };
41
42 explicit CProgThresholdBase(CDescObject &desc)
43 : CProgProcess(desc)
44 , mode(MODE_ABOVE)
45 , low(0)
46 , high(0)
47 {
48 }
49
50 int trigger(uint8_t cmd) override
51 {
52 if (cmd == CMD_RESET)
53 {
54 state.clear();
55 }
56
57 return CProgProcess::trigger(cmd);
58 }
59
60protected:
63 size_t &offset) override
64 {
66 uint32_t val;
67
68 (void)desc;
69 (void)offset;
70
71 if (item->cfgid.s.size != 1)
72 {
73 DAWNERR("threshold: invalid config size %u\n", item->cfgid.s.size);
74 return -EINVAL;
75 }
76
77 raw = reinterpret_cast<const SObjectCfg::ObjectCfgData_t *>(item->data);
78 val = SObjectCfg::cfgToU32(raw[0]);
79
80 switch (item->cfgid.s.id)
81 {
82 case PROG_THRESHOLD_CFG_MODE:
83 {
84 if (val > MODE_WINDOW)
85 {
86 DAWNERR("threshold: invalid mode %" PRIu32 "\n", val);
87 return -EINVAL;
88 }
89
90 mode = val;
91 break;
92 }
93
94 case PROG_THRESHOLD_CFG_LOW:
95 {
96 low = raw[0];
97 break;
98 }
99
100 case PROG_THRESHOLD_CFG_HIGH:
101 {
102 high = raw[0];
103 break;
104 }
105
106 default:
107 {
108 return -ENOTSUP;
109 }
110 }
111
112 return OK;
113 }
114
115 void handle(CIOCommon *output,
116 io_ddata_t *data,
117 io_ddata_t *ioData,
118 io_ddata_t *outputData,
119 bool &initsample) override
120 {
121 (void)initsample;
122
123 if (!validateOutputDtype(data->getDtype(), outputData->getDtype()))
124 {
125 DAWNERR("threshold: invalid output dtype %d for input dtype %d\n",
126 outputData->getDtype(),
127 data->getDtype());
128 return;
129 }
130
131 switch (data->getDtype())
132 {
133#ifdef CONFIG_DAWN_DTYPE_INT8
135 {
136 handleTyped<int8_t>(output,
137 data,
138 ioData,
139 outputData,
140 static_cast<int8_t>(low),
141 static_cast<int8_t>(high));
142 break;
143 }
144#endif
145
146#ifdef CONFIG_DAWN_DTYPE_UINT8
148 {
149 handleTyped<uint8_t>(output,
150 data,
151 ioData,
152 outputData,
153 static_cast<uint8_t>(low),
154 static_cast<uint8_t>(high));
155 break;
156 }
157#endif
158
159#ifdef CONFIG_DAWN_DTYPE_INT16
161 {
162 handleTyped<int16_t>(output,
163 data,
164 ioData,
165 outputData,
166 static_cast<int16_t>(low),
167 static_cast<int16_t>(high));
168 break;
169 }
170#endif
171
172#ifdef CONFIG_DAWN_DTYPE_UINT16
174 {
175 handleTyped<uint16_t>(output,
176 data,
177 ioData,
178 outputData,
179 static_cast<uint16_t>(low),
180 static_cast<uint16_t>(high));
181 break;
182 }
183#endif
184
185#ifdef CONFIG_DAWN_DTYPE_INT32
187 {
188 handleTyped<int32_t>(output,
189 data,
190 ioData,
191 outputData,
194 break;
195 }
196#endif
197
198#ifdef CONFIG_DAWN_DTYPE_UINT32
200 {
201 handleTyped<uint32_t>(output,
202 data,
203 ioData,
204 outputData,
207 break;
208 }
209#endif
210
211#ifdef CONFIG_DAWN_DTYPE_INT64
213 {
214 handleTyped<int64_t>(output,
215 data,
216 ioData,
217 outputData,
218 static_cast<int64_t>(low),
219 static_cast<int64_t>(high));
220 break;
221 }
222#endif
223
224#ifdef CONFIG_DAWN_DTYPE_UINT64
226 {
227 handleTyped<uint64_t>(output,
228 data,
229 ioData,
230 outputData,
231 static_cast<uint64_t>(low),
232 static_cast<uint64_t>(high));
233 break;
234 }
235#endif
236
237#ifdef CONFIG_DAWN_DTYPE_FLOAT
239 {
240 handleTyped<float>(
241 output, data, ioData, outputData, SObjectCfg::cfgToF(low), SObjectCfg::cfgToF(high));
242 break;
243 }
244#endif
245
246#ifdef CONFIG_DAWN_DTYPE_DOUBLE
248 {
249 handleTyped<double>(output,
250 data,
251 ioData,
252 outputData,
253 static_cast<double>(SObjectCfg::cfgToF(low)),
254 static_cast<double>(SObjectCfg::cfgToF(high)));
255 break;
256 }
257#endif
258
259 default:
260 {
261 DAWNERR("threshold: unsupported dtype %d\n", data->getDtype());
262 break;
263 }
264 }
265 }
266
267 virtual bool validateOutputDtype(uint8_t inputDtype, uint8_t outputDtype) const = 0;
268 virtual int emitOutput(CIOCommon *output,
269 uint8_t inputDtype,
270 size_t items,
271 io_ddata_t *ioData,
272 io_ddata_t *outputData) = 0;
273
274private:
275 struct SState
276 {
277 size_t items = 0;
278 std::vector<uint8_t> last;
279 };
280
281 template<typename T>
282 bool evaluate(T x, T lowT, T highT, uint8_t prev) const
283 {
284 switch (mode)
285 {
286 case MODE_ABOVE:
287 return x >= highT;
288
289 case MODE_BELOW:
290 return x <= lowT;
291
292 case MODE_WINDOW:
293 return x >= lowT && x <= highT;
294
295 case MODE_HYSTERESIS:
296 if (x >= highT)
297 {
298 return true;
299 }
300
301 if (x <= lowT)
302 {
303 return false;
304 }
305
306 return prev != 0;
307
308 default:
309 return false;
310 }
311 }
312
313 template<typename T>
314 void handleTyped(CIOCommon *output,
315 io_ddata_t *data,
316 io_ddata_t *ioData,
317 io_ddata_t *outputData,
318 T lowT,
319 T highT)
320 {
321 int ret;
322
323 std::memcpy(ioData->getDataPtr(), data->getDataPtr(), ioData->getDataSize());
324
325 const SObjectId::ObjectId outputId = output->getIdV();
326 SState &st = state[outputId];
327 const size_t items = ioData->getItems();
328
329 if (st.items != items || st.last.size() != items)
330 {
331 st.items = items;
332 st.last.assign(items, 0);
333 }
334
335 for (size_t i = 0; i < items; i++)
336 {
337 const uint8_t prev = st.last[i];
338 const T x = ioData->get<T>(i);
339 const bool out = evaluate(x, lowT, highT, prev);
340
341 st.last[i] = out ? 1 : 0;
342 }
343
344 this->alerts = st.last;
345 ret = emitOutput(output, data->getDtype(), items, ioData, outputData);
346 if (ret != OK)
347 {
348 DAWNERR("threshold: emit failed %d\n", ret);
349 }
350 }
351
352protected:
353 uint32_t mode;
356 std::vector<uint8_t> alerts;
357
358private:
359 std::map<SObjectId::ObjectId, SState> state;
360};
361
367{
368public:
369 explicit CProgThreshold(CDescObject &desc)
370 : CProgThresholdBase(desc)
371 {
372 }
373
374#ifdef CONFIG_DAWN_OBJECT_HAS_NAME
375 const char *getClassNameStr() const override
376 {
377 return "threshold";
378 }
379#endif
380
381 constexpr static SObjectId::ObjectId objectId(uint16_t inst)
382 {
383 return SObjectId::objectId(
385 }
386
387 constexpr static SObjectCfg::ObjectCfgId cfgId(bool rw, uint8_t size, uint8_t id)
388 {
392 rw,
393 size,
394 id);
395 }
396
397 constexpr static SObjectCfg::ObjectCfgId cfgIdIOBind(uint16_t size = 2)
398 {
399 return CProgThreshold::cfgId(false, size, PROG_STATS_CFG_IOBIND);
400 }
401
402 constexpr static SObjectCfg::ObjectCfgId cfgIdMode()
403 {
404 return CProgThreshold::cfgId(false, 1, PROG_THRESHOLD_CFG_MODE);
405 }
406
407 constexpr static SObjectCfg::ObjectCfgId cfgIdLow()
408 {
409 return CProgThreshold::cfgId(false, 1, PROG_THRESHOLD_CFG_LOW);
410 }
411
412 constexpr static SObjectCfg::ObjectCfgId cfgIdHigh()
413 {
414 return CProgThreshold::cfgId(false, 1, PROG_THRESHOLD_CFG_HIGH);
415 }
416
417protected:
418 bool validateOutputDtype(uint8_t inputDtype, uint8_t outputDtype) const override
419 {
420 (void)inputDtype;
421 return outputDtype == SObjectId::DTYPE_BOOL;
422 }
423
424 int emitOutput(CIOCommon *output,
425 uint8_t inputDtype,
426 size_t items,
427 io_ddata_t *ioData,
428 io_ddata_t *outputData) override
429 {
430 (void)inputDtype;
431 (void)ioData;
432
433 for (size_t i = 0; i < items; i++)
434 {
435 outputData->get<uint8_t>(i) = this->alerts[i];
436 }
437
438 return output->setData(*outputData);
439 }
440};
441
447{
448public:
449 explicit CProgThresholdValue(CDescObject &desc)
450 : CProgThresholdBase(desc)
451 {
452 }
453
454#ifdef CONFIG_DAWN_OBJECT_HAS_NAME
455 const char *getClassNameStr() const override
456 {
457 return "thresholdvalue";
458 }
459#endif
460
461 constexpr static SObjectId::ObjectId objectId(uint16_t inst)
462 {
466 0,
467 inst);
468 }
469
470 constexpr static SObjectCfg::ObjectCfgId cfgId(bool rw, uint8_t size, uint8_t id)
471 {
475 rw,
476 size,
477 id);
478 }
479
480 constexpr static SObjectCfg::ObjectCfgId cfgIdIOBind(uint16_t size = 2)
481 {
482 return CProgThresholdValue::cfgId(false, size, PROG_STATS_CFG_IOBIND);
483 }
484
485 constexpr static SObjectCfg::ObjectCfgId cfgIdMode()
486 {
487 return CProgThresholdValue::cfgId(false, 1, PROG_THRESHOLD_CFG_MODE);
488 }
489
490 constexpr static SObjectCfg::ObjectCfgId cfgIdLow()
491 {
492 return CProgThresholdValue::cfgId(false, 1, PROG_THRESHOLD_CFG_LOW);
493 }
494
495 constexpr static SObjectCfg::ObjectCfgId cfgIdHigh()
496 {
497 return CProgThresholdValue::cfgId(false, 1, PROG_THRESHOLD_CFG_HIGH);
498 }
499
500protected:
501 bool validateOutputDtype(uint8_t inputDtype, uint8_t outputDtype) const override
502 {
503 return outputDtype == inputDtype;
504 }
505
506 int emitOutput(CIOCommon *output,
507 uint8_t inputDtype,
508 size_t items,
509 io_ddata_t *ioData,
510 io_ddata_t *outputData) override
511 {
512 switch (inputDtype)
513 {
514#ifdef CONFIG_DAWN_DTYPE_INT8
516 {
517 return emitOutputTyped<int8_t>(output, items, ioData, outputData);
518 }
519#endif
520
521#ifdef CONFIG_DAWN_DTYPE_UINT8
523 {
524 return emitOutputTyped<uint8_t>(output, items, ioData, outputData);
525 }
526#endif
527
528#ifdef CONFIG_DAWN_DTYPE_INT16
530 {
531 return emitOutputTyped<int16_t>(output, items, ioData, outputData);
532 }
533#endif
534
535#ifdef CONFIG_DAWN_DTYPE_UINT16
537 {
538 return emitOutputTyped<uint16_t>(output, items, ioData, outputData);
539 }
540#endif
541
542#ifdef CONFIG_DAWN_DTYPE_INT32
544 {
545 return emitOutputTyped<int32_t>(output, items, ioData, outputData);
546 }
547#endif
548
549#ifdef CONFIG_DAWN_DTYPE_UINT32
551 {
552 return emitOutputTyped<uint32_t>(output, items, ioData, outputData);
553 }
554#endif
555
556#ifdef CONFIG_DAWN_DTYPE_INT64
558 {
559 return emitOutputTyped<int64_t>(output, items, ioData, outputData);
560 }
561#endif
562
563#ifdef CONFIG_DAWN_DTYPE_UINT64
565 {
566 return emitOutputTyped<uint64_t>(output, items, ioData, outputData);
567 }
568#endif
569
570#ifdef CONFIG_DAWN_DTYPE_FLOAT
572 {
573 return emitOutputTyped<float>(output, items, ioData, outputData);
574 }
575#endif
576
577#ifdef CONFIG_DAWN_DTYPE_DOUBLE
579 {
580 return emitOutputTyped<double>(output, items, ioData, outputData);
581 }
582#endif
583
584 default:
585 {
586 return -ENOTSUP;
587 }
588 }
589 }
590
591private:
592 template<typename T>
593 int emitOutputTyped(CIOCommon *output, size_t items, io_ddata_t *ioData, io_ddata_t *outputData)
594 {
595 for (size_t i = 0; i < items; i++)
596 {
597 if (this->alerts[i] != 0)
598 {
599 outputData->get<T>(i) = ioData->get<T>(i);
600 }
601 else
602 {
603 outputData->get<T>(i) = static_cast<T>(0);
604 }
605 }
606
607 return output->setData(*outputData);
608 }
609};
610} // 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
@ CMD_RESET
Reset object internal state.
Definition object.hxx:42
@ PROG_CLASS_THRESHOLD_VALUE
Threshold comparator returning gated source value.
Definition common.hxx:99
@ PROG_CLASS_THRESHOLD
Threshold and hysteresis comparator.
Definition common.hxx:95
Base class for callback-driven sample processing Program objects.
Definition process.hxx:28
int trigger(uint8_t cmd)
Execute a trigger command.
Definition process.cxx:310
@ PROG_STATS_CFG_IOBIND
I/O binding configuration.
Definition process.hxx:35
Shared threshold logic for derived threshold programs.
Definition threshold.hxx:25
int trigger(uint8_t cmd)
Execute a trigger command.
Definition threshold.hxx:50
int configureExtraCfgItem(const CDescObject &desc, const SObjectCfg::SObjectCfgItem *item, size_t &offset)
Parse program-specific config item (optional extension hook).
Definition threshold.hxx:61
void handle(CIOCommon *output, io_ddata_t *data, io_ddata_t *ioData, io_ddata_t *outputData, bool &initsample)
Process incoming sample.
Threshold comparator returning gated source values.
Threshold comparator returning boolean alert output.
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 float cfgToF(ObjectCfgData_t x)
Convert ObjectCfgData_t to float.
static uint32_t cfgToU32(ObjectCfgData_t x)
Convert ObjectCfgData_t to uint32_t.
static int32_t cfgtoi32(ObjectCfgData_t x)
Convert ObjectCfgData_t to int32_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
@ DTYPE_BOOL
Boolean data type (stored in 32-bit container).
Definition objectid.hxx:72
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
T & get(size_t index, size_t batch=0)
Get data element by index and batch (type-safe).
Definition ddata.hxx:93
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.