6#include "dawn/prog/sequencer.hxx"
12#include "dawn/debug.hxx"
13#include "dawn/io/common.hxx"
14#include "dawn/io/ddata.hxx"
18int CProgSequencer::configureDesc(
const CDescObject &desc)
22 bool hasTargets =
false;
23 bool hasStates =
false;
24 size_t statesCount = 0;
26 for (
size_t i = 0; i < desc.
getSize(); i++)
32 DAWNERR(
"sequencer: unsupported cfg 0x%08" PRIx32
"\n", item->
cfgid.
v);
38 case PROG_SEQUENCER_CFG_TARGET:
47 DAWNERR(
"sequencer: no targets configured\n");
53 targetIds.reserve(ntargets);
56 for (j = 0; j < ntargets; j++)
58 ret = allocObject(ids[j].v);
68 case PROG_SEQUENCER_CFG_STATE:
72 DAWNERR(
"sequencer: invalid state table size %d\n", item->
cfgid.
s.
size);
81 case PROG_SEQUENCER_CFG_START:
85 DAWNERR(
"sequencer: invalid START size %d\n", item->
cfgid.
s.
size);
94 DAWNERR(
"sequencer: unsupported cfg 0x%08" PRIx32
"\n", item->
cfgid.
v);
100 if (!hasTargets || targetIds.empty())
102 DAWNERR(
"sequencer: target list is empty\n");
106 if (!hasStates || statesCount == 0)
108 DAWNERR(
"sequencer: state table is empty\n");
112 states.resize(statesCount);
114 return reloadRuntimeConfig(
true);
119 DAWNINFO(
"allocate sequencer target 0x%" PRIx32
"\n", targetId);
121 targetIds.push_back(targetId);
127int CProgSequencer::reloadRuntimeConfig(
bool resetCurrent,
129 const uint32_t *overrideData,
134 const uint32_t *data =
nullptr;
135 size_t dataWords = 0;
137 size_t statesCount = 0;
138 size_t newStartIndex = startIndex;
139 size_t parsedStates = 0;
141 bool hasState =
false;
142 bool hasStartItem =
false;
144 for (
size_t itemIdx = 0; itemIdx < desc.
getSize(); itemIdx++)
147 data =
reinterpret_cast<const uint32_t *
>(item->
data);
150 if (overrideCfg != 0 && item->
cfgid.
v == overrideCfg)
154 DAWNERR(
"sequencer: null override data\n");
159 dataWords = overrideLen;
164 DAWNERR(
"sequencer: invalid runtime cfg class\n");
170 case PROG_SEQUENCER_CFG_STATE:
173 statesCount = dataWords / 2;
174 if (dataWords == 0 || dataWords % 2 != 0 || states.empty() ||
175 statesCount != states.size())
177 DAWNERR(
"sequencer: invalid state table size %d\n", (
int)dataWords);
181 parsedStates = statesCount;
185 case PROG_SEQUENCER_CFG_START:
189 DAWNERR(
"sequencer: invalid START size %d\n", (
int)dataWords);
194 if (overrideCfg == 0 || item->
cfgid.
v == overrideCfg)
196 newStartIndex =
static_cast<size_t>(*data);
206 if (!hasState || parsedStates == 0)
208 DAWNERR(
"sequencer: state table is empty\n");
212 if (hasStartItem && newStartIndex >= parsedStates)
214 DAWNERR(
"sequencer: start index %zu out of range (%zu)\n", newStartIndex, parsedStates);
221 for (
size_t itemIdx = 0; itemIdx < desc.
getSize(); itemIdx++)
224 data =
reinterpret_cast<const uint32_t *
>(item->
data);
227 if (overrideCfg != 0 && item->
cfgid.
v == overrideCfg)
230 dataWords = overrideLen;
233 if (item->
cfgid.
s.
id == PROG_SEQUENCER_CFG_STATE)
236 for (i = 0; i < dataWords; i += 2)
238 states[parsedStates].value = data[i];
239 states[parsedStates].dwellUs = data[i + 1];
240 if (states[parsedStates].dwellUs == 0)
242 DAWNERR(
"sequencer: state[%zu] dwell_us must be > 0\n", parsedStates);
252 startIndex = newStartIndex;
256 currentIndex = startIndex;
280 if (
id != PROG_SEQUENCER_CFG_STATE &&
id != PROG_SEQUENCER_CFG_START)
287 ret = reloadRuntimeConfig(resetCurrent, objcfg, data, len);
295 ret = applyState(startIndex);
306 index = currentIndex;
309 ret = applyState(index);
319int CProgSequencer::applyState(
size_t index)
325 if (index >= states.size() || !iodata || targetSize == 0 || targetSize > 4)
330 value = states[index].value;
332 std::memcpy(iodata->
getDataPtr(), &value, targetSize);
335 for (i = 0; i < targets.size(); i++)
338 r = targets[i]->setData(*iodata);
341 DAWNERR(
"sequencer: setData failed for target[%zu] (%d)\n", i, r);
349void CProgSequencer::thread()
354 DAWNINFO(
"start sequencer thread\n");
360 dwell = states[idx].dwellUs;
367 currentIndex = (idx + 1) % states.size();
370 while (!threadCtl.shouldQuit());
373CProgSequencer::~CProgSequencer()
382 ret = configureDesc(
getDesc());
385 DAWNERR(
"sequencer configure failed: %d\n", ret);
398 targets.reserve(targetIds.size());
400 for (i = 0; i < targetIds.size(); i++)
402 io =
getIO(targetIds[i]);
405 DAWNERR(
"sequencer: target 0x%" PRIx32
" not found\n", targetIds[i]);
409 ret = prepareWritableTarget(io, 1,
true);
412 DAWNERR(
"sequencer: target prepare failed %d\n", ret);
418 DAWNERR(
"sequencer: target 0x%" PRIx32
" must be scalar output\n", targetIds[i]);
424 DAWNERR(
"sequencer: target 0x%" PRIx32
" unsupported data size %zu (expected 1..4)\n",
437 DAWNERR(
"sequencer: target 0x%" PRIx32
" type mismatch with first target\n",
442 targets.push_back(io);
446 std::vector<SObjectId::ObjectId>().swap(targetIds);
448 iodata =
new (std::nothrow)
io_ddata_t(targetSize, 1, 1, targetDtype);
449 if (iodata ==
nullptr || !iodata->isAllocated())
453 DAWNERR(
"sequencer: iodata allocation failed\n");
465 std::vector<CIOCommon *>().swap(targets);
466 std::vector<SObjectId::ObjectId>().swap(targetIds);
467 std::vector<SState>().swap(states);
477 ret = reloadRuntimeConfig(
true);
510 ret = reloadRuntimeConfig(
true);
516 ret = applyState(startIndex);
CIOCommon * getIO(SObjectId::ObjectId id)
Get an I/O object by ID.
void setObjectMapItem(SObjectId::ObjectId id, CObject *obj)
Set an item in the object map.
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.
Base class for all I/O objects.
virtual size_t getDataDim() const =0
Get data vector dimension.
virtual size_t getDataSize() const =0
Get data size in bytes.
@ STATE_STOPPED
Object is stopped.
@ STATE_RUNNING
Object is running.
virtual EObjectState getState() const
Get current operational state.
CDescObject & getDesc()
Get descriptor object for this object.
uint8_t getDtype() const
Get data type field.
@ CMD_RESET
Reset object internal state.
@ PROG_CLASS_SEQUENCER
Periodic state sequencer.
bool hasThread() const
Check if a background thread is active.
int init()
One-time initialize object after bindings are resolved.
int configure()
Configure object from descriptor data.
int deinit()
De-initialize object.
int doStop()
Stop implementation hook.
int doStart()
Start implementation hook.
int trigger(uint8_t cmd)
Execute a trigger command.
bool isRunning() const
Check if the worker thread is running.
int threadStop()
Stop the worker thread.
int threadStart()
Start the worker thread.
void setThreadFunc(Func &&func)
Assign the function executed by threadStart().
uint32_t ObjectCfgId
ConfigID type - single 32-bit value.
static uint16_t objectCfgGetCls(const ObjectCfgId objcfg)
Extract object class from ConfigID.
static uint8_t objectCfgGetId(const ObjectCfgId objcfg)
Extract configuration identifier from ConfigID.
static uint8_t objectCfgGetType(const ObjectCfgId objcfg)
Extract object type from ConfigID.
Out-of-tree user-extension hooks for Dawn.
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.
@ DTYPE_ANY
Wildcard data type (matches any actual type).
uint32_t ObjectId
ObjectID type - single 32-bit value.
Heap-allocated dynamic I/O data buffer.
size_t getDataSize()
Get data size in bytes.
void * getDataPtr(size_t batch=0)
Get pointer to data only (skips timestamp if present).
ObjectCfgId v
Raw 32-bit ConfigID value (for storage, comparison).
uint32_t cls
Object class (bits 21-29, max 511).
uint32_t id
Configuration identifier (bits 0-4, max 31).
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).