Dawn Framework 1.0
Universal data acquisition framework for embedded systems
adjust.cxx
1// dawn/src/prog/adjust.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/prog/adjust.hxx"
7
8#include "dawn/debug.hxx"
9#include "dawn/io/common.hxx"
10#include "dawn/io/ddata.hxx"
11
12using namespace dawn;
13
14template<typename SRC, typename DST, typename PARAM>
15static void applyAdjust(const void *src,
16 void *dst,
17 size_t n,
18 uint32_t rawScale,
19 uint32_t rawOffset,
20 PARAM (*toCfg)(uint32_t))
21{
22 PARAM scale = toCfg(rawScale);
23 PARAM offset = toCfg(rawOffset);
24 const SRC *in = static_cast<const SRC *>(src);
25 DST *out = static_cast<DST *>(dst);
26
27 for (size_t i = 0; i < n; i++)
28 {
29 out[i] = static_cast<DST>(in[i]) * scale + offset;
30 }
31}
32
33template<typename SRC>
34static void applyAdjustB16(const void *src,
35 void *dst,
36 size_t n,
37 uint32_t rawScale,
38 uint32_t rawOffset)
39{
40 b16_t scale = SObjectCfg::cfgToB16(rawScale);
41 b16_t offset = SObjectCfg::cfgToB16(rawOffset);
42 const SRC *in = static_cast<const SRC *>(src);
43 b16_t *out = static_cast<b16_t *>(dst);
44
45 for (size_t i = 0; i < n; i++)
46 {
47 b16_t tmp1 = itob16(in[i]);
48 b16_t tmp2 = b16mulb16(tmp1, scale);
49 out[i] = tmp2 + offset;
50 }
51}
52
53static void applyAdjustFloatToB16(const void *src,
54 void *dst,
55 size_t n,
56 uint32_t rawScale,
57 uint32_t rawOffset)
58{
59 b16_t scale = SObjectCfg::cfgToB16(rawScale);
60 b16_t offset = SObjectCfg::cfgToB16(rawOffset);
61 const float *in = static_cast<const float *>(src);
62 b16_t *out = static_cast<b16_t *>(dst);
63
64 for (size_t i = 0; i < n; i++)
65 {
66 b16_t tmp1 = ftob16(in[i]);
67 b16_t tmp2 = b16mulb16(tmp1, scale);
68 out[i] = tmp2 + offset;
69 }
70}
71
72static double cfgToDouble(uint32_t raw)
73{
74 return static_cast<double>(SObjectCfg::cfgToF(raw));
75}
76
77template<typename SRC>
78static void applyAdjustRealToB16(const void *src,
79 void *dst,
80 size_t n,
81 uint32_t rawScale,
82 uint32_t rawOffset)
83{
84 b16_t scale = SObjectCfg::cfgToB16(rawScale);
85 b16_t offset = SObjectCfg::cfgToB16(rawOffset);
86 const SRC *in = static_cast<const SRC *>(src);
87 b16_t *out = static_cast<b16_t *>(dst);
88
89 for (size_t i = 0; i < n; i++)
90 {
91 b16_t tmp1 = ftob16(static_cast<float>(in[i]));
92 b16_t tmp2 = b16mulb16(tmp1, scale);
93 out[i] = tmp2 + offset;
94 }
95}
96
97template<typename SRC>
98static bool applyAdjustToDst(int dstType,
99 const void *src,
100 void *dst,
101 size_t n,
102 uint32_t rawScale,
103 uint32_t rawOffset)
104{
105 switch (dstType)
106 {
107#ifdef CONFIG_DAWN_DTYPE_INT8
109 applyAdjust<SRC, int8_t, int32_t>(src, dst, n, rawScale, rawOffset, SObjectCfg::cfgtoi32);
110 return true;
111#endif
112#ifdef CONFIG_DAWN_DTYPE_UINT8
114 applyAdjust<SRC, uint8_t, uint32_t>(src, dst, n, rawScale, rawOffset, SObjectCfg::cfgToU32);
115 return true;
116#endif
117#ifdef CONFIG_DAWN_DTYPE_INT16
119 applyAdjust<SRC, int16_t, int32_t>(src, dst, n, rawScale, rawOffset, SObjectCfg::cfgtoi32);
120 return true;
121#endif
122#ifdef CONFIG_DAWN_DTYPE_UINT16
124 applyAdjust<SRC, uint16_t, uint32_t>(
125 src, dst, n, rawScale, rawOffset, SObjectCfg::cfgToU32);
126 return true;
127#endif
128#ifdef CONFIG_DAWN_DTYPE_INT32
130 applyAdjust<SRC, int32_t, int32_t>(src, dst, n, rawScale, rawOffset, SObjectCfg::cfgtoi32);
131 return true;
132#endif
133#ifdef CONFIG_DAWN_DTYPE_UINT32
135 applyAdjust<SRC, uint32_t, uint32_t>(
136 src, dst, n, rawScale, rawOffset, SObjectCfg::cfgToU32);
137 return true;
138#endif
139#ifdef CONFIG_DAWN_DTYPE_INT64
141 applyAdjust<SRC, int64_t, int32_t>(src, dst, n, rawScale, rawOffset, SObjectCfg::cfgtoi32);
142 return true;
143#endif
144#ifdef CONFIG_DAWN_DTYPE_UINT64
146 applyAdjust<SRC, uint64_t, uint32_t>(
147 src, dst, n, rawScale, rawOffset, SObjectCfg::cfgToU32);
148 return true;
149#endif
150#ifdef CONFIG_DAWN_DTYPE_FLOAT
152 applyAdjust<SRC, float, float>(src, dst, n, rawScale, rawOffset, SObjectCfg::cfgToF);
153 return true;
154#endif
155#ifdef CONFIG_DAWN_DTYPE_DOUBLE
157 applyAdjust<SRC, double, double>(src, dst, n, rawScale, rawOffset, cfgToDouble);
158 return true;
159#endif
160#ifdef CONFIG_DAWN_DTYPE_B16
162 applyAdjustB16<SRC>(src, dst, n, rawScale, rawOffset);
163 return true;
164#endif
165 default:
166 return false;
167 }
168}
169
170template<>
171bool applyAdjustToDst<float>(int dstType,
172 const void *src,
173 void *dst,
174 size_t n,
175 uint32_t rawScale,
176 uint32_t rawOffset)
177{
178 if (dstType == SObjectId::DTYPE_B16)
179 {
180#ifdef CONFIG_DAWN_DTYPE_B16
181 applyAdjustFloatToB16(src, dst, n, rawScale, rawOffset);
182 return true;
183#else
184 return false;
185#endif
186 }
187
188 return applyAdjustToDst<const float>(dstType, src, dst, n, rawScale, rawOffset);
189}
190
191template<>
192bool applyAdjustToDst<double>(int dstType,
193 const void *src,
194 void *dst,
195 size_t n,
196 uint32_t rawScale,
197 uint32_t rawOffset)
198{
199 if (dstType == SObjectId::DTYPE_B16)
200 {
201#ifdef CONFIG_DAWN_DTYPE_B16
202 applyAdjustRealToB16<double>(src, dst, n, rawScale, rawOffset);
203 return true;
204#else
205 return false;
206#endif
207 }
208
209 return applyAdjustToDst<const double>(dstType, src, dst, n, rawScale, rawOffset);
210}
211
212static bool applyAdjustByType(int srcType,
213 int dstType,
214 const void *src,
215 void *dst,
216 size_t n,
217 uint32_t rawScale,
218 uint32_t rawOffset)
219{
220 switch (srcType)
221 {
222#ifdef CONFIG_DAWN_DTYPE_INT8
224 return applyAdjustToDst<int8_t>(dstType, src, dst, n, rawScale, rawOffset);
225#endif
226#ifdef CONFIG_DAWN_DTYPE_UINT8
228 return applyAdjustToDst<uint8_t>(dstType, src, dst, n, rawScale, rawOffset);
229#endif
230#ifdef CONFIG_DAWN_DTYPE_INT16
232 return applyAdjustToDst<int16_t>(dstType, src, dst, n, rawScale, rawOffset);
233#endif
234#ifdef CONFIG_DAWN_DTYPE_UINT16
236 return applyAdjustToDst<uint16_t>(dstType, src, dst, n, rawScale, rawOffset);
237#endif
238#ifdef CONFIG_DAWN_DTYPE_INT32
240 return applyAdjustToDst<int32_t>(dstType, src, dst, n, rawScale, rawOffset);
241#endif
242#ifdef CONFIG_DAWN_DTYPE_UINT32
244 return applyAdjustToDst<uint32_t>(dstType, src, dst, n, rawScale, rawOffset);
245#endif
246#ifdef CONFIG_DAWN_DTYPE_INT64
248 return applyAdjustToDst<int64_t>(dstType, src, dst, n, rawScale, rawOffset);
249#endif
250#ifdef CONFIG_DAWN_DTYPE_UINT64
252 return applyAdjustToDst<uint64_t>(dstType, src, dst, n, rawScale, rawOffset);
253#endif
254#ifdef CONFIG_DAWN_DTYPE_FLOAT
256 return applyAdjustToDst<float>(dstType, src, dst, n, rawScale, rawOffset);
257#endif
258#ifdef CONFIG_DAWN_DTYPE_DOUBLE
260 return applyAdjustToDst<double>(dstType, src, dst, n, rawScale, rawOffset);
261#endif
262 default:
263 return false;
264 }
265}
266
267int CProgAdjust::ioNotifierCb(void *priv, io_ddata_t *data)
268{
269 CProgAdjust *obj = static_cast<CProgAdjust *>(priv);
270
271 // Handle data
272
273 obj->handle(data);
274 return OK;
275}
276
277int CProgAdjust::configureDesc(const CDescObject &desc)
278{
279 const SObjectCfg::SObjectCfgItem *item = nullptr;
280 size_t offset = 0;
281
282 for (size_t i = 0; i < desc.getSize(); i++)
283 {
284 item = desc.objectCfgItemAtOffset(offset);
285
287 {
288 DAWNERR("Unsupported adjust config 0x%08" PRIx32 "\n", item->cfgid.v);
289 return -EINVAL;
290 }
291
292 switch (item->cfgid.s.id)
293 {
295 {
296 offset += 1;
297
298 if (item->cfgid.s.size != sizeof(SProgAdjustIOBind) / 4)
299 {
300 DAWNERR("Invalid IOBIND config size %d, expected %zu\n",
301 item->cfgid.s.size,
302 sizeof(SProgAdjustIOBind) / 4);
303 return -EINVAL;
304 }
305
306 SProgAdjustIOBind *iobind =
307 reinterpret_cast<SProgAdjustIOBind *>(desc.objectCfgItemAtOffset(offset));
308
309 allocObject(iobind);
310 offset += sizeof(SProgAdjustIOBind) / 4;
311 break;
312 }
313
315 {
316 offset += 1;
317
318 if (item->cfgid.s.size != sizeof(SProgAdjustParams) / 4)
319 {
320 DAWNERR("Invalid PARAMS config size %d, expected %zu\n",
321 item->cfgid.s.size,
322 sizeof(SProgAdjustParams) / 4);
323 return -EINVAL;
324 }
325
326 const SProgAdjustParams *params =
327 reinterpret_cast<SProgAdjustParams *>(desc.objectCfgItemAtOffset(offset));
328
329 ioscale = params->scale;
330 iooffset = params->offset;
331 offset += sizeof(SProgAdjustParams) / 4;
332 break;
333 }
334
335 default:
336 {
337 DAWNERR("Unsupported adjust config 0x%08" PRIx32 "\n", item->cfgid.v);
338 return -EINVAL;
339 }
340 }
341 }
342
343 return OK;
344}
345
346int CProgAdjust::onSetObjConfig(SObjectCfg::ObjectCfgId objcfg, uint32_t *data, size_t len)
347{
348 // Only the adjustment params (scale/offset) are runtime-writable; refresh the
349 // cached values so the next handle() applies them immediately.
350
352 {
353 return OK;
354 }
355
356 if (data == nullptr || len != sizeof(SProgAdjustParams) / sizeof(uint32_t))
357 {
358 return -EINVAL;
359 }
360
361 const SProgAdjustParams *params = reinterpret_cast<const SProgAdjustParams *>(data);
362
363 ioscale = params->scale;
364 iooffset = params->offset;
365 return OK;
366}
367
368void CProgAdjust::handle(io_ddata_t *data)
369{
370 if (data == nullptr)
371 {
372 DAWNERR("Null data pointer in handle()\n");
373 return;
374 }
375
376 void *data_ptr = data->getDataPtr();
377 void *dst = outputData->getDataPtr();
378 size_t n = outputData->getItems();
379
380 if (!applyAdjustByType(srcType, outputType, data_ptr, dst, n, ioscale, iooffset))
381 {
382 DAWNERR("Invalid conversion from type %d to type %d\n", srcType, outputType);
383 return;
384 }
385
386 output->setData(*outputData);
387}
388
389bool CProgAdjust::isSupportedConvType(int sourceType, int targetType)
390{
391 return applyAdjustByType(sourceType, targetType, nullptr, nullptr, 0, 0, 0);
392}
393
394int CProgAdjust::allocObject(SProgAdjustIOBind *alloc)
395{
396 DAWNINFO("allocate prog 0x%" PRIx32 " -> 0x%" PRIx32 "\n", alloc->objid.v, alloc->output.v);
397
398 // Allocate source and output in map
399
400 setObjectMapItem(alloc->objid.v, nullptr);
401 setObjectMapItem(alloc->output.v, nullptr);
402
403 // Store pointer to config for later
404
405 cfg = alloc;
406
407 return OK;
408};
409
410int CProgAdjust::bindPrepare()
411{
412 int ret;
413 size_t dim;
414
415 if (!src->isRead())
416 {
417 DAWNERR("Source IO 0x%" PRIx32 " is not readable\n", src->getIdV());
418 return -EINVAL;
419 }
420
421#ifdef CONFIG_DAWN_IO_NOTIFY
422 if (src->isNotify())
423 {
424 // Register callback if notify is supported
425
426 ret = src->setNotifier(ioNotifierCb, 0, this);
427 if (ret < 0)
428 {
429 DAWNERR("Set notifier failed for objId = 0x%" PRIx32 ": %d\n", src->getIdV(), ret);
430 return ret;
431 }
432 }
433#endif
434
435 // Get dimension
436
437 dim = src->getDataDim();
438
439 // Initialize deferred virtual outputs and validate configured targets.
440
441 ret = prepareWritableTarget(output, dim, src->isNotify());
442 if (ret != OK)
443 {
444 DAWNERR("Output IO initialize failed: %d\n", ret);
445 return ret;
446 }
447
448 if (output->getDataDim() != dim)
449 {
450 DAWNERR("Adjust output 0x%" PRIx32 " shape mismatch\n", output->getIdV());
451 return -EINVAL;
452 }
453
454 return OK;
455}
456
457CProgAdjust::~CProgAdjust()
458{
459 deinit();
460}
461
463{
464 int ret;
465
466 // Configure object
467
468 ret = configureDesc(getDesc());
469 if (ret != OK)
470 {
471 DAWNERR("Adjust configure failed (error %d)\n", ret);
472 return ret;
473 }
474
475 // Type of conversion
476
477 srcType = SObjectId::objectIdGetDtype(cfg->objid.v);
478 outputType = SObjectId::objectIdGetDtype(cfg->output.v);
479
480 if (!isSupportedConvType(srcType, outputType))
481 {
482 DAWNERR("Unsupported conversion from type %d to type %d\n", srcType, outputType);
483 return -EINVAL;
484 }
485
486 // By default, scale is set to 1 and offset set to 0 to allow type conversion
487
488 if (ioscale == 0 && iooffset == 0)
489 {
490 switch (outputType)
491 {
492#if defined(CONFIG_DAWN_DTYPE_INT8) || defined(CONFIG_DAWN_DTYPE_INT16) || \
493 defined(CONFIG_DAWN_DTYPE_INT32) || defined(CONFIG_DAWN_DTYPE_INT64)
498 ioscale = SObjectCfg::i32ToCfg(1);
499 iooffset = SObjectCfg::i32ToCfg(0);
500 break;
501#endif
502
503#if defined(CONFIG_DAWN_DTYPE_UINT8) || defined(CONFIG_DAWN_DTYPE_UINT16) || \
504 defined(CONFIG_DAWN_DTYPE_UINT32) || defined(CONFIG_DAWN_DTYPE_UINT64)
509 ioscale = SObjectCfg::u32ToCfg(1);
510 iooffset = SObjectCfg::u32ToCfg(0);
511 break;
512#endif
513
514#ifdef CONFIG_DAWN_DTYPE_FLOAT
516 ioscale = SObjectCfg::fToCfg(1.0f);
517 iooffset = SObjectCfg::fToCfg(0.0f);
518 break;
519#endif
520
521#ifdef CONFIG_DAWN_DTYPE_DOUBLE
523 ioscale = SObjectCfg::fToCfg(1.0f);
524 iooffset = SObjectCfg::fToCfg(0.0f);
525 break;
526#endif
527
528#ifdef CONFIG_DAWN_DTYPE_B16
530 ioscale = SObjectCfg::fToB16ToCfg(1.0f);
531 iooffset = SObjectCfg::fToB16ToCfg(0.0f);
532 break;
533#endif
534
535 default:
536 DAWNERR("Unsupported output IO type %d for default scale/offset\n", outputType);
537 return -EINVAL;
538 }
539 }
540
541 // One-time initialization that depends on bindings is done in init()
542
543 return OK;
544}
545
547{
548 // Delete objects
549
550 delete ioData;
551 ioData = nullptr;
552 delete outputData;
553 outputData = nullptr;
554 src = nullptr;
555 output = nullptr;
556
557 return OK;
558}
559
561{
562 int ret;
563
564 // Get IOs
565
566 src = getIO(cfg->objid.v);
567 if (!src)
568 {
569 return -EIO;
570 }
571
572 output = getIO(cfg->output.v);
573 if (!output)
574 {
575 return -EIO;
576 }
577
578 // Complete binding
579
580 ret = bindPrepare();
581 if (ret != OK)
582 {
583 return ret;
584 }
585
586 // Create storage for IO data
587
588 ioData = src->ddata_alloc(1);
589 if (!ioData)
590 {
591 return -ENOMEM;
592 }
593
594 outputData = output->ddata_alloc(1);
595 if (!outputData)
596 {
597 delete ioData;
598 ioData = nullptr;
599 return -ENOMEM;
600 }
601
602 return OK;
603}
604
605int CProgAdjust::refresh()
606{
607 int ret;
608
609 ret = src->getData(*ioData, 1);
610 if (ret != OK)
611 {
612 DAWNERR("Failed to get data from source IO (error %d)\n", ret);
613 return ret;
614 }
615
616 handle(ioData);
617 return OK;
618}
619
621{
622 if (src->isNotify())
623 {
624 return OK;
625 }
626
627 return refresh();
628};
CIOCommon * getIO(SObjectId::ObjectId id)
Get an I/O object by ID.
Definition bindable.cxx:41
void setObjectMapItem(SObjectId::ObjectId id, CObject *obj)
Set an item in the object map.
Definition bindable.cxx:23
Descriptor wrapper for individual object configuration.
size_t getSize() const
Get number of configuration items for this object.
SObjectCfg::SObjectCfgItem * objectCfgItemAtOffset(size_t offset) const
Get configuration item at specified offset.
int setData(IODataCmn &data, size_t offset=0)
Set data for I/O (public interface with stats tracking).
Definition common.hxx:411
virtual size_t getDataDim() const =0
Get data vector dimension.
io_ddata_t * ddata_alloc(size_t batch, size_t chunk_size=0)
Allocate data buffer for this I/O.
Definition common.cxx:247
SObjectId::ObjectId getIdV() const
Get object identifier as raw 32-bit value.
Definition object.cxx:155
CDescObject & getDesc()
Get descriptor object for this object.
Definition object.cxx:190
Data scaling and offset transformation PROG.
Definition adjust.hxx:31
int onSetObjConfig(SObjectCfg::ObjectCfgId objcfg, uint32_t *data, size_t len)
Pre-update hook for runtime configuration writes.
Definition adjust.cxx:346
@ PROG_ADJUST_CFG_PARAMS
Adjustment parameters (scale, offset)
Definition adjust.hxx:37
@ PROG_ADJUST_CFG_IOBIND
I/O binding configuration.
Definition adjust.hxx:36
int init()
One-time initialize object after bindings are resolved.
Definition adjust.cxx:560
int doStart()
Start implementation hook.
Definition adjust.cxx:620
int configure()
Configure object from descriptor data.
Definition adjust.cxx:462
int deinit()
De-initialize object.
Definition adjust.cxx:546
@ PROG_CLASS_ADJUST
Scale/offset adjustment.
Definition common.hxx:71
uint32_t ObjectCfgId
ConfigID type - single 32-bit value.
Definition objectcfg.hxx:60
static float cfgToF(ObjectCfgData_t x)
Convert ObjectCfgData_t to float.
static uint8_t objectCfgGetId(const ObjectCfgId objcfg)
Extract configuration identifier from ConfigID.
static ObjectCfgData_t i32ToCfg(int32_t x)
Convert int32_t to ObjectCfgData_t.
static ObjectCfgData_t fToCfg(float x)
Convert float to ObjectCfgData_t.
static uint32_t cfgToU32(ObjectCfgData_t x)
Convert ObjectCfgData_t to uint32_t.
static ObjectCfgData_t u32ToCfg(uint32_t x)
Helper conversion functions: data types to cfg data type.
static b16_t cfgToB16(ObjectCfgData_t x)
Convert ObjectCfgData_t to b16_t.
static int32_t cfgtoi32(ObjectCfgData_t x)
Convert ObjectCfgData_t to int32_t.
static ObjectCfgData_t fToB16ToCfg(float x)
Convert float to b16_t and then to ObjectCfgData_t.
Out-of-tree user-extension hooks for Dawn.
Definition bindable.hxx:13
Single configuration item within object.
UObjectCfgId cfgid
Configuration ID header (type, class, id, size, rw, dtype).
@ 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_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_B16
Signed 16.16 fixed-point (32-bit).
Definition objectid.hxx:128
static uint8_t objectIdGetDtype(const ObjectId objid)
Extract data type field from ObjectID.
Definition objectid.hxx:337
Heap-allocated dynamic I/O data buffer.
Definition ddata.hxx:21
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
Definition ddata.hxx:180
size_t getItems()
Get number of items per batch.
Definition ddata.hxx:128
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
Definition objectcfg.hxx:82
uint32_t cls
Object class (bits 21-29, max 511).
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.