SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
Loading...
Searching...
No Matches
ai_engine.h
Go to the documentation of this file.
1/*******************************************************************************
2 * File Name : ai_engine.h
3 *
4 * Description : BENTO Edge AI engine on CM55 (TFLite-Micro + Ethos-U55).
5 * Holds the model registry, runs one model or one model set
6 * at a time, and publishes a result snapshot for the UI and
7 * the MicroPython model link.
8 *
9 * Start a model, or a set (a set index in place of a model
10 * index), with ai_engine_start(). Read one model's verdict
11 * with ai_engine_snapshot_model(); ai_engine_snapshot()
12 * returns only the most recent verdict from any model.
13 * ai_engine_requested() is what was asked for;
14 * ai_engine_active() is what has finished loading.
15 *
16 * Every inference is timed and published in the snapshot
17 * (inference_us), so a model that outgrows its cadence is
18 * visible on-screen rather than silent.
19 *
20 * Target : PSoC Edge E84, CM55
21 *******************************************************************************/
22
23#ifndef AI_ENGINE_H
24#define AI_ENGINE_H
25
26#include <stdint.h>
27#include <stdbool.h>
28#include <stddef.h> /* NULL — ai_result_top_positive() below is inline here */
29
30#ifdef __cplusplus
31extern "C" {
32#endif
33
34#define AI_MAX_CLASSES (8u)
35#define AI_MAX_LABEL_LEN (16u)
36
43
45typedef struct {
46 const char *name;
47 const char *description;
49 uint8_t class_count;
50 /* Registry contract: index 0 is the negative class -- the one that means
51 * "nothing is happening". It is "unlabelled" in the audio and radar models,
52 * "idle" in motion, "normal" in fall. Everything from 1 up is a positive
53 * detection.
54 *
55 * Summary scores depend on this: ai_result_top_positive() (below) takes
56 * the maximum over classes 1..class_count-1, so a model whose classes were
57 * all positive would read as if the loudest one were always firing. A model
58 * that cannot honour this contract must not be registered as if it did;
59 * give it an explicit negative class instead. */
61 uint32_t flash_bytes;
62 uint16_t period_ms;
63
64 /* DEEPCRAFT-generated entry points (symbol-prefixed per model so several
65 * models can be linked into one image — the generated sources all declare
66 * IMAI_* otherwise). */
67 int (*init)(void);
68 int (*enqueue)(const float *in);
69 int (*dequeue)(float *out);
70 void (*finalize)(void);
72
74typedef struct {
75 uint8_t model_index;
76 uint8_t class_count;
77 uint8_t top_class;
78 uint8_t running;
80 uint32_t inference_us;
82 uint32_t inferences;
83 uint32_t seq;
85
98#define AI_PARALLEL_MIC (255)
99
104#define AI_PARALLEL_ROOM (254)
105#define AI_PARALLEL_INTRUDER (253)
106
108#define AI_PARALLEL_ALL (252)
109
114#define AI_PARALLEL_FIRST AI_PARALLEL_ALL
115
116/* These numbers are also defined in the model-link wire header
117 * (ipc_model_link_defs.h), because MicroPython has to resolve a legacy
118 * 13/14/15 to the same value before it can confirm a select. The two are
119 * checked equal here rather than trusted, and only when the wire header is in
120 * the translation unit, so this header still compiles on its own. */
121#if defined(MODEL_LINK_SET_MIC)
122_Static_assert(AI_PARALLEL_ALL == MODEL_LINK_SET_ALL, "set index drift");
123_Static_assert(AI_PARALLEL_INTRUDER == MODEL_LINK_SET_INTRUDER, "set index drift");
124_Static_assert(AI_PARALLEL_ROOM == MODEL_LINK_SET_ROOM, "set index drift");
125_Static_assert(AI_PARALLEL_MIC == MODEL_LINK_SET_MIC, "set index drift");
126#endif
127
129uint32_t ai_engine_set_models(uint32_t set_index, uint8_t *idx, uint32_t max);
130
132const char *ai_engine_set_name(uint32_t set_index);
133
139int ai_engine_set_define(uint32_t set_index, const uint8_t *members, uint32_t n);
140
142uint32_t ai_engine_set_members_defined(uint32_t set_index, uint8_t *out, uint32_t max);
143
148void ai_engine_unload(uint32_t idx);
151
153
155const ai_model_desc_t *ai_engine_model(uint32_t index);
156
187
189uint32_t ai_engine_dyn_count(void);
191
194bool ai_engine_init(void);
195
201bool ai_engine_start(uint32_t index);
202
206
209uint32_t ai_engine_feeds(void);
210uint32_t ai_engine_dq_ok(void);
211uint32_t ai_engine_dq_calls(void);
212
217void ai_engine_set_sensor_rate(uint32_t interval_ms);
218
222uint32_t ai_engine_inits(void);
223
228uint32_t ai_engine_init_calls(void);
229
233
237uint64_t ai_engine_npu_cycles(void);
238
253
258
260void ai_engine_stop(void);
261
264
270
273
278bool ai_engine_snapshot_model(uint32_t index, ai_result_t *out);
279
284uint32_t ai_engine_set_members(uint8_t *idx, uint32_t max);
285
293static inline int ai_result_top_positive(const ai_result_t *r, uint8_t *which)
294{
295 if (which != NULL) { *which = 1u; }
296 if ((r == NULL) || (r->class_count < 2u)) { return 0; }
297 float best = r->scores[1];
298 uint8_t arg = 1u;
299 /* Bounded by class_count, not the array size: only the first class_count
300 * scores are valid and the slots above are never set. */
301 for (uint8_t c = 2u; (c < r->class_count) && (c < AI_MAX_CLASSES); c++) {
302 if (r->scores[c] > best) { best = r->scores[c]; arg = c; }
303 }
304 if (which != NULL) { *which = arg; }
305 int pct = (int)(best * 100.0f + 0.5f);
306 if (pct < 0) { pct = 0; }
307 if (pct > 100) { pct = 100; }
308 return pct;
309}
310
315
318
319#ifdef __cplusplus
320}
321#endif
322
323#endif /* AI_ENGINE_H */
#define AI_MAX_CLASSES
Definition ai_engine.h:34
uint32_t ai_engine_dyn_capacity(void)
#define AI_PARALLEL_ROOM
Definition ai_engine.h:104
#define AI_PARALLEL_INTRUDER
Definition ai_engine.h:105
#define AI_PARALLEL_MIC
Definition ai_engine.h:98
int ai_engine_register(const ai_model_desc_t *desc)
#define AI_PARALLEL_ALL
Definition ai_engine.h:108
ai_sensor_t
Definition ai_engine.h:38
@ AI_SENSOR_IMU
Definition ai_engine.h:39
@ AI_SENSOR_RADAR
Definition ai_engine.h:40
@ AI_SENSOR_MIC
Definition ai_engine.h:41
uint32_t ai_engine_dyn_count(void)
uint32_t ai_engine_init_returns(void)
Model init() calls that RETURNED; always read as the pair.
int32_t ai_engine_last_init_rc(void)
Return code of the last model init(): 0x7FFFFFFF = never called; 0 = ok.
uint32_t ai_engine_feeds(void)
Samples accepted by the model; take the delta over at least 1 s.
uint32_t ai_engine_inits(void)
Successful model initialisations; a packed nibble in the heartbeat word.
uint32_t ai_engine_dq_ok(void)
Successful dequeues; frozen while dq_calls climbs = NPU stall.
uint32_t ai_engine_init_calls(void)
Model init() calls entered; read together with ai_engine_init_returns().
uint64_t ai_engine_npu_cycles(void)
NPU cycles accumulated so far; not proof any inference completed.
uint32_t ai_engine_dq_calls(void)
Dequeue attempts; pair with ai_engine_dq_ok() for stall detection.
uint32_t ai_engine_stale_drops(void)
Verdicts discarded past the Ethos-U wait bound; must stay flat while npu_cycles advances.
int ai_engine_active(void)
The LOADED model, or -1; lags requested by a cold-init window.
uint32_t ai_engine_stack_free_words(void)
All-time minimum of unused stack words; O(stack) scan — read at ~1 Hz at most.
int ai_engine_requested(void)
The REQUESTED model, or -1; the correct guard for a fallback.
uint32_t ai_engine_stack_words(void)
Stack the inference task got, in words; 0 = engine never started — the universal gate.
void ai_engine_stop(void)
Stop the active model (idempotent); pair with a sensor-rate walk-down.
bool ai_engine_start(uint32_t index)
Activate a model (or set) by index and begin inferring; check the return.
bool ai_engine_init(void)
Create the inference task (idempotent); it must precede ai_engine_start().
bool ai_engine_snapshot(ai_result_t *out)
Copy the latest verdict from any model — not valid inside a set.
uint32_t ai_engine_mic_settle_pct(void)
Settle progress 0..100; only meaningful inside a set (100 otherwise).
bool ai_engine_mic_settling(void)
True for a few seconds after a set starts, while its inputs settle; verdicts are withheld.
uint32_t ai_engine_model_count(void)
How many models are registered; the count leads the rows.
const ai_model_desc_t * ai_engine_model(uint32_t index)
Registry entry, NULL if out of range — and NULL for a set pseudo-index.
bool ai_engine_snapshot_model(uint32_t index, ai_result_t *out)
One model's last verdict — the reader to use inside a set.
void ai_engine_set_sensor_rate(uint32_t interval_ms)
Set the accelerometer feed interval; call it on its own, from one owner.
void ai_engine_resume_sensor(void)
Standalone resume of the default cadence; never back-to-back with a rate set.
uint32_t ai_engine_set_members(uint8_t *idx, uint32_t max)
Registry indices of the ACTIVE set's members; test each member's sensor.
uint32_t ai_engine_set_members_defined(uint32_t set_index, uint8_t *out, uint32_t max)
The explicit membership if defined, else 0 — the only ack for set_define.
uint32_t ai_engine_set_models(uint32_t set_index, uint8_t *idx, uint32_t max)
Members of any set, in registry order; an explicit membership replaces the compiled one.
int ai_engine_set_define(uint32_t set_index, const uint8_t *members, uint32_t n)
Give a set an explicit run-time membership; task context, all-or-nothing.
const char * ai_engine_set_name(uint32_t set_index)
Human name for a set; NULL for a non-set index.
void ai_engine_unload(uint32_t idx)
Asynchronous unload request — refused unless the engine is idle.
uint32_t ai_engine_unload_done(void)
Cumulative count of completed unloads; read as a pair with refused.
uint32_t ai_engine_unload_refused(void)
Cumulative count of refused unloads; read with ai_engine_unload_done().
Definition ai_engine.h:45
uint8_t class_count
Definition ai_engine.h:49
const char * name
Definition ai_engine.h:46
const char * class_labels[AI_MAX_CLASSES]
Definition ai_engine.h:60
uint16_t period_ms
Definition ai_engine.h:62
const char * description
Definition ai_engine.h:47
int(*) dequeue(float *out)
Definition ai_engine.h:69
ai_sensor_t sensor
Definition ai_engine.h:48
uint32_t flash_bytes
Definition ai_engine.h:61
void(*) finalize(void)
Definition ai_engine.h:70
int(*) init(void)
Definition ai_engine.h:67
int(*) enqueue(const float *in)
Definition ai_engine.h:68
Definition ai_engine.h:74
uint32_t inference_us
Definition ai_engine.h:80
uint32_t seq
Definition ai_engine.h:83
uint8_t running
Definition ai_engine.h:78
uint8_t class_count
Definition ai_engine.h:76
uint8_t model_index
Definition ai_engine.h:75
uint8_t top_class
Definition ai_engine.h:77
float scores[AI_MAX_CLASSES]
Definition ai_engine.h:79
uint32_t inference_us_max
Definition ai_engine.h:81
uint32_t inferences
Definition ai_engine.h:82