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
346void CProgAdjust::handle(io_ddata_t *data)
347{
348 if (data == nullptr)
349 {
350 DAWNERR("Null data pointer in handle()\n");
351 return;
352 }
353
354 void *data_ptr = data->getDataPtr();
355 void *dst = outputData->getDataPtr();
356 size_t n = outputData->getItems();
357
358 if (!applyAdjustByType(srcType, outputType, data_ptr, dst, n, ioscale, iooffset))
359 {
360 DAWNERR("Invalid conversion from type %d to type %d\n", srcType, outputType);
361 return;
362 }
363
364 output->setData(*outputData);
365}
366
367bool CProgAdjust::isSupportedConvType(int sourceType, int targetType)
368{
369 return applyAdjustByType(sourceType, targetType, nullptr, nullptr, 0, 0, 0);
370}
371
372int CProgAdjust::allocObject(SProgAdjustIOBind *alloc)
373{
374 DAWNINFO("allocate prog 0x%" PRIx32 " -> 0x%" PRIx32 "\n", alloc->objid.v, alloc->output.v);
375
376 // Allocate source and output in map
377
378 setObjectMapItem(alloc->objid.v, nullptr);
379 setObjectMapItem(alloc->output.v, nullptr);
380
381 // Store pointer to config for later
382
383 cfg = alloc;
384
385 return OK;
386};
387
388int CProgAdjust::bindPrepare()
389{
390 int ret;
391 size_t dim;
392
393 if (!src->isRead())
394 {
395 DAWNERR("Source IO 0x%" PRIx32 " is not readable\n", src->getIdV());
396 return -EINVAL;
397 }
398
399#ifdef CONFIG_DAWN_IO_NOTIFY
400 if (src->isNotify())
401 {
402 // Register callback if notify is supported
403
404 ret = src->setNotifier(ioNotifierCb, 0, this);
405 if (ret < 0)
406 {
407 DAWNERR("Set notifier failed for objId = 0x%" PRIx32 ": %d\n", src->getIdV(), ret);
408 return ret;
409 }
410 }
411#endif
412
413 // Get dimension
414
415 dim = src->getDataDim();
416
417 // Initialize deferred virtual outputs and validate configured targets.
418
419 ret = prepareWritableTarget(output, dim, src->isNotify());
420 if (ret != OK)
421 {
422 DAWNERR("Output IO initialize failed: %d\n", ret);
423 return ret;
424 }
425
426 if (output->getDataDim() != dim)
427 {
428 DAWNERR("Adjust output 0x%" PRIx32 " shape mismatch\n", output->getIdV());
429 return -EINVAL;
430 }
431
432 return OK;
433}
434
435CProgAdjust::~CProgAdjust()
436{
437 deinit();
438}
439
441{
442 int ret;
443
444 // Configure object
445
446 ret = configureDesc(getDesc());
447 if (ret != OK)
448 {
449 DAWNERR("Adjust configure failed (error %d)\n", ret);
450 return ret;
451 }
452
453 // Type of conversion
454
455 srcType = SObjectId::objectIdGetDtype(cfg->objid.v);
456 outputType = SObjectId::objectIdGetDtype(cfg->output.v);
457
458 if (!isSupportedConvType(srcType, outputType))
459 {
460 DAWNERR("Unsupported conversion from type %d to type %d\n", srcType, outputType);
461 return -EINVAL;
462 }
463
464 // By default, scale is set to 1 and offset set to 0 to allow type conversion
465
466 if (ioscale == 0 && iooffset == 0)
467 {
468 switch (outputType)
469 {
470#if defined(CONFIG_DAWN_DTYPE_INT8) || defined(CONFIG_DAWN_DTYPE_INT16) || \
471 defined(CONFIG_DAWN_DTYPE_INT32) || defined(CONFIG_DAWN_DTYPE_INT64)
476 ioscale = SObjectCfg::i32ToCfg(1);
477 iooffset = SObjectCfg::i32ToCfg(0);
478 break;
479#endif
480
481#if defined(CONFIG_DAWN_DTYPE_UINT8) || defined(CONFIG_DAWN_DTYPE_UINT16) || \
482 defined(CONFIG_DAWN_DTYPE_UINT32) || defined(CONFIG_DAWN_DTYPE_UINT64)
487 ioscale = SObjectCfg::u32ToCfg(1);
488 iooffset = SObjectCfg::u32ToCfg(0);
489 break;
490#endif
491
492#ifdef CONFIG_DAWN_DTYPE_FLOAT
494 ioscale = SObjectCfg::fToCfg(1.0f);
495 iooffset = SObjectCfg::fToCfg(0.0f);
496 break;
497#endif
498
499#ifdef CONFIG_DAWN_DTYPE_DOUBLE
501 ioscale = SObjectCfg::fToCfg(1.0f);
502 iooffset = SObjectCfg::fToCfg(0.0f);
503 break;
504#endif
505
506#ifdef CONFIG_DAWN_DTYPE_B16
508 ioscale = SObjectCfg::fToB16ToCfg(1.0f);
509 iooffset = SObjectCfg::fToB16ToCfg(0.0f);
510 break;
511#endif
512
513 default:
514 DAWNERR("Unsupported output IO type %d for default scale/offset\n", outputType);
515 return -EINVAL;
516 }
517 }
518
519 // One-time initialization that depends on bindings is done in init()
520
521 return OK;
522}
523
525{
526 // Delete objects
527
528 delete ioData;
529 ioData = nullptr;
530 delete outputData;
531 outputData = nullptr;
532 src = nullptr;
533 output = nullptr;
534
535 return OK;
536}
537
539{
540 int ret;
541
542 // Get IOs
543
544 src = getIO(cfg->objid.v);
545 if (!src)
546 {
547 return -EIO;
548 }
549
550 output = getIO(cfg->output.v);
551 if (!output)
552 {
553 return -EIO;
554 }
555
556 // Complete binding
557
558 ret = bindPrepare();
559 if (ret != OK)
560 {
561 return ret;
562 }
563
564 // Create storage for IO data
565
566 ioData = src->ddata_alloc(1);
567 if (!ioData)
568 {
569 return -ENOMEM;
570 }
571
572 outputData = output->ddata_alloc(1);
573 if (!outputData)
574 {
575 delete ioData;
576 ioData = nullptr;
577 return -ENOMEM;
578 }
579
580 return OK;
581}
582
583int CProgAdjust::refresh()
584{
585 int ret;
586
587 ret = src->getData(*ioData, 1);
588 if (ret != OK)
589 {
590 DAWNERR("Failed to get data from source IO (error %d)\n", ret);
591 return ret;
592 }
593
594 handle(ioData);
595 return OK;
596}
597
599{
600 if (src->isNotify())
601 {
602 return OK;
603 }
604
605 return refresh();
606};
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:392
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 init()
One-time initialize object after bindings are resolved.
Definition adjust.cxx:538
@ 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 doStart()
Start implementation hook.
Definition adjust.cxx:598
int configure()
Configure object from descriptor data.
Definition adjust.cxx:440
int deinit()
De-initialize object.
Definition adjust.cxx:524
@ PROG_CLASS_ADJUST
Scale/offset adjustment.
Definition common.hxx:71
static float cfgToF(ObjectCfgData_t x)
Convert ObjectCfgData_t to float.
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.