Dawn Framework 1.0
Universal data acquisition framework for embedded systems
toggle.cxx
1// dawn/src/prog/toggle.cxx
2//
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#include "dawn/prog/toggle.hxx"
7
8#include <cstring>
9#include <new>
10
11#include "dawn/debug.hxx"
12#include "dawn/io/common.hxx"
13#include "dawn/io/ddata.hxx"
14
15using namespace dawn;
16
17CProgToggle::CProgToggle(CDescObject &desc)
18 : CProgCommon(desc)
19 , onVal(1)
20 , offVal(0)
21 , curVal(0)
22 , active(false)
23 , registered(false)
24{
25}
26
27CProgToggle::~CProgToggle()
28{
29 deinit();
30}
31
32int CProgToggle::allocBind(SObjectId::ObjectId sourceId, SObjectId::ObjectId outputId)
33{
34 SToggleBind *bind;
35
36 bind = new (std::nothrow) SToggleBind();
37 if (!bind)
38 {
39 return -ENOMEM;
40 }
41
42 bind->owner = this;
43 bind->sourceId = sourceId;
44 bind->outputId = outputId;
45 bind->source = nullptr;
46 bind->output = nullptr;
47 bind->sourceData = nullptr;
48 bind->prevInput = 0;
49
50 binds.push_back(bind);
51 setObjectMapItem(sourceId, nullptr);
52 setObjectMapItem(outputId, nullptr);
53 return OK;
54}
55
56int CProgToggle::configureDesc(const CDescObject &desc)
57{
59 const SObjectId::UObjectId *ids;
61 size_t offset = 0;
62
63 for (size_t i = 0; i < desc.getSize(); i++)
64 {
65 item = desc.objectCfgItemNext(offset);
66
67 if (item->cfgid.s.cls != CProgCommon::PROG_CLASS_TOGGLE)
68 {
69 DAWNERR("toggle: unsupported cfg class 0x%" PRIx32 "\n", item->cfgid.v);
70 return -EINVAL;
71 }
72
73 switch (item->cfgid.s.id)
74 {
75 case PROG_TOGGLE_CFG_IOBIND:
76 {
77 size_t nitems = static_cast<size_t>(item->cfgid.s.size);
78 if (nitems == 0 || nitems % 2 != 0)
79 {
80 DAWNERR("toggle: invalid IOBIND size %zu\n", nitems);
81 return -EINVAL;
82 }
83
84 ids = reinterpret_cast<const SObjectId::UObjectId *>(item->data);
85 for (size_t b = 0; b < nitems / 2; b++)
86 {
87 int ret = allocBind(ids[b * 2].v, ids[b * 2 + 1].v);
88 if (ret != OK)
89 {
90 return ret;
91 }
92 }
93 break;
94 }
95
96 case PROG_TOGGLE_CFG_VALUES:
97 {
98 if (item->cfgid.s.size != 2)
99 {
100 DAWNERR("toggle: VALUES config must have exactly 2 entries\n");
101 return -EINVAL;
102 }
103
104 raw = reinterpret_cast<const SObjectCfg::ObjectCfgData_t *>(item->data);
105 offVal = SObjectCfg::cfgToU32(raw[0]);
106 onVal = SObjectCfg::cfgToU32(raw[1]);
107 break;
108 }
109
110 default:
111 {
112 DAWNERR("toggle: unsupported cfg id %u\n", item->cfgid.s.id);
113 return -EINVAL;
114 }
115 }
116 }
117
118 if (binds.empty())
119 {
120 DAWNERR("toggle: at least one IOBIND entry required\n");
121 return -EINVAL;
122 }
123
124 curVal = offVal;
125 return OK;
126}
127
129{
130 return configureDesc(getDesc());
131}
132
134{
135 int ret;
136
137 for (auto bind : binds)
138 {
139 bind->source = getIO(bind->sourceId);
140 bind->output = getIO(bind->outputId);
141 if (!bind->source || !bind->output)
142 {
143 return -EIO;
144 }
145
146 if (!bind->source->isRead())
147 {
148 DAWNERR("toggle: source 0x%" PRIx32 " is not readable\n", bind->sourceId);
149 return -EINVAL;
150 }
151
152 ret = prepareWritableTarget(bind->output, 1, true);
153 if (ret != OK)
154 {
155 return ret;
156 }
157
158 if (bind->output->getDtype() != SObjectId::DTYPE_UINT32 || bind->output->getDataDim() != 1)
159 {
160 DAWNERR("toggle: output 0x%" PRIx32 " must be writable scalar uint32\n", bind->outputId);
161 return -EINVAL;
162 }
163
164 bind->sourceData = bind->source->ddata_alloc(1);
165 if (!bind->sourceData)
166 {
167 return -ENOMEM;
168 }
169 }
170
171 return OK;
172}
173
175{
176 doStop();
177
178 for (auto bind : binds)
179 {
180 delete bind->sourceData;
181 delete bind;
182 }
183
184 binds.clear();
185 return OK;
186}
187
188uint32_t CProgToggle::readInput(SToggleBind *bind, io_ddata_t *data)
189{
190 uint32_t input = 0;
191
192 if (data && data->getItems() >= 1)
193 {
194 std::memcpy(
195 bind->sourceData->getDataPtr(), data->getDataPtr(), bind->sourceData->getDataSize());
196 }
197 else if (bind->source->getData(*bind->sourceData, 1) != OK)
198 {
199 return 0;
200 }
201
202 std::memcpy(&input,
203 bind->sourceData->getDataPtr(),
204 bind->sourceData->getDataSize() < sizeof(input) ? bind->sourceData->getDataSize()
205 : sizeof(input));
206 return input;
207}
208
209void CProgToggle::writeValue(SToggleBind *bind)
210{
211 bind->outputData(0) = curVal;
212 int ret = bind->output->setData(bind->outputData);
213 if (ret != OK)
214 {
215 DAWNERR("toggle: setData failed %d\n", ret);
216 }
217}
218
219void CProgToggle::refresh(SToggleBind *bind, io_ddata_t *data)
220{
221 uint32_t input = readInput(bind, data);
222
223 if (bind->prevInput == 0 && input != 0)
224 {
225 curVal = curVal == offVal ? onVal : offVal;
226 writeValue(bind);
227 }
228
229 bind->prevInput = input;
230}
231
232int CProgToggle::ioNotifierCb(void *priv, io_ddata_t *data)
233{
234 SToggleBind *bind = static_cast<SToggleBind *>(priv);
235
236 if (bind && bind->owner && bind->owner->active)
237 {
238 bind->owner->refresh(bind, data);
239 }
240
241 return OK;
242}
243
245{
246 int ret;
247
248 if (!registered)
249 {
250 for (auto bind : binds)
251 {
252 if (!bind->source->isNotify())
253 {
254 continue;
255 }
256
257 ret = bind->source->setNotifier(ioNotifierCb, 0, bind);
258 if (ret != OK)
259 {
260 return ret;
261 }
262 }
263
264 registered = true;
265 }
266
267 active = true;
268
269 for (auto bind : binds)
270 {
271 bind->prevInput = readInput(bind, nullptr);
272 writeValue(bind);
273 }
274
275 return OK;
276}
277
279{
280 if (registered)
281 {
282 for (auto bind : binds)
283 {
284 if (bind->source && bind->source->isNotify())
285 {
286 bind->source->setNotifier(nullptr, 0, nullptr);
287 }
288 }
289
290 registered = false;
291 }
292
293 active = false;
294 return OK;
295}
296
298{
299 return false;
300}
301
302int CProgToggle::trigger(uint8_t cmd)
303{
304 if (cmd == CMD_RESET)
305 {
306 curVal = offVal;
307 for (auto bind : binds)
308 {
309 bind->prevInput = 0;
310 }
311 return OK;
312 }
313
314 return -ENOTSUP;
315}
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 * objectCfgItemNext(size_t &offset) const
Get config item at current offset and advance past it.
CDescObject & getDesc()
Get descriptor object for this object.
Definition object.cxx:190
@ CMD_RESET
Reset object internal state.
Definition object.hxx:42
Base class for all PROG (processing) objects.
Definition common.hxx:27
int deinit()
De-initialize object.
Definition toggle.cxx:174
int doStart()
Start implementation hook.
Definition toggle.cxx:244
int trigger(uint8_t cmd)
Execute a trigger command.
Definition toggle.cxx:302
bool hasThread() const
Check if a background thread is active.
Definition toggle.cxx:297
int configure()
Configure object from descriptor data.
Definition toggle.cxx:128
int init()
One-time initialize object after bindings are resolved.
Definition toggle.cxx:133
int doStop()
Stop implementation hook.
Definition toggle.cxx:278
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).
@ 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
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.
32-bit encoded object identifier (union with bit field).
Definition objectid.hxx:218