SDK for TESAIoT Dev Kit
API reference & tutorials (ModusToolbox)
Loading...
Searching...
No Matches
ai_engine.h File Reference
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

Go to the source code of this file.

Data Structures

struct  ai_model_desc_t
struct  ai_result_t

Macros

#define AI_MAX_CLASSES   (8u)
#define AI_MAX_LABEL_LEN   (16u)
#define AI_PARALLEL_MIC   (255)
#define AI_PARALLEL_ROOM   (254)
#define AI_PARALLEL_INTRUDER   (253)
#define AI_PARALLEL_ALL   (252)
#define AI_PARALLEL_FIRST   AI_PARALLEL_ALL

Enumerations

enum  ai_sensor_t { AI_SENSOR_IMU = 0 , AI_SENSOR_RADAR , AI_SENSOR_MIC }

Functions

uint32_t ai_engine_set_models (uint32_t set_index, uint8_t *idx, uint32_t max)
 Members of any set, in registry order; explicit membership wins outright.
const char * ai_engine_set_name (uint32_t set_index)
 Human name for a set; NULL for a non-set index.
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.
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.
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().
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.
int ai_engine_register (const ai_model_desc_t *desc)
uint32_t ai_engine_dyn_count (void)
uint32_t ai_engine_dyn_capacity (void)
bool ai_engine_init (void)
 Create the inference task (idempotent); it must precede ai_engine_start().
bool ai_engine_start (uint32_t index)
 Activate a model (or set) by index and begin inferring; check the return.
uint32_t ai_engine_stack_words (void)
 Stack the inference task got, in words; 0 = engine never started — the universal gate.
uint32_t ai_engine_feeds (void)
 Samples accepted by the model; take the delta over at least 1 s.
uint32_t ai_engine_dq_ok (void)
 Successful dequeues; frozen while dq_calls climbs = NPU stall.
uint32_t ai_engine_dq_calls (void)
 Dequeue attempts; pair with ai_engine_dq_ok() for stall detection.
void ai_engine_set_sensor_rate (uint32_t interval_ms)
 Set the accelerometer feed interval; the only legal sender on s_rate_msg.
void ai_engine_resume_sensor (void)
 Standalone resume of the default cadence; never back-to-back with a rate set.
uint32_t ai_engine_inits (void)
 Successful model initialisations; a packed nibble in the heartbeat word.
uint32_t ai_engine_init_calls (void)
 Model init() calls entered; read together with ai_engine_init_returns().
uint32_t ai_engine_init_returns (void)
 Model init() calls that RETURNED; always read as the pair.
uint64_t ai_engine_npu_cycles (void)
 NPU cycles accumulated so far; not proof any inference completed.
uint32_t ai_engine_stale_drops (void)
 Verdicts discarded past the Ethos-U wait bound; must stay flat while npu_cycles advances.
uint32_t ai_engine_stack_free_words (void)
 All-time minimum of unused stack words; O(stack) scan — read at ~1 Hz at most.
int32_t ai_engine_last_init_rc (void)
 Return code of the last model init(): 0x7FFFFFFF = never called; 0 = ok.
void ai_engine_stop (void)
 Stop the active model (idempotent); pair with a sensor-rate walk-down.
int ai_engine_active (void)
 The LOADED model (s_current), or -1; lags requested by a cold-init window.
int ai_engine_requested (void)
 The REQUESTED model (s_active), or -1; the correct guard for a fallback.
bool ai_engine_snapshot (ai_result_t *out)
 Copy the latest published result; last-writer-wins — not valid inside a set.
bool ai_engine_snapshot_model (uint32_t index, ai_result_t *out)
 One model's last verdict — the reader to use inside a parallel 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.
bool ai_engine_mic_settling (void)
 True while a parallel set is still filling its windows; verdicts are withheld.
uint32_t ai_engine_mic_settle_pct (void)
 Settle progress 0..100; only meaningful inside a set (100 otherwise).

Macro Definition Documentation

◆ AI_MAX_CLASSES

#define AI_MAX_CLASSES   (8u)

◆ AI_MAX_LABEL_LEN

#define AI_MAX_LABEL_LEN   (16u)

◆ AI_PARALLEL_MIC

#define AI_PARALLEL_MIC   (255)

How many models are compiled in. Set index: several models listening to the same sensor data.

Pass one of these to ai_engine_start() in place of a model index. ai_engine_active() reports it back. ai_engine_set_models() lists the members and ai_engine_set_name() gives the display name.

These are the top of the uint8 range, not the numbers immediately above the registry. While they sat just above it they were its ceiling, and the registry has to be free to grow. The older 13/14/15 spellings still work: the firmware translates them to the values here, and ai_engine_active() answers with the value here, so a caller that sends 13 is told 253.

◆ AI_PARALLEL_ROOM

#define AI_PARALLEL_ROOM   (254)

MIC every microphone model at once. ROOM radar plus the microphone models that suit a room. INTRUDER motion, radar and the alarm models. Contains an IMU model, so starting it raises the CM33 sensor push rate for the session.

◆ AI_PARALLEL_INTRUDER

#define AI_PARALLEL_INTRUDER   (253)

◆ AI_PARALLEL_ALL

#define AI_PARALLEL_ALL   (252)

Every registered model at once — the widest watch.

◆ AI_PARALLEL_FIRST

#define AI_PARALLEL_FIRST   AI_PARALLEL_ALL

Lowest pseudo-index in use; anything at or above this is a set, not a model. (AI_PARALLEL_ALL was absent here for one day — the archive then shipping predated the set and rejected 252 on hardware. The archive was re-cut from the current engine 2026-08-28 and honours it; verified over the REPL.)

Enumeration Type Documentation

◆ ai_sensor_t

Sensor pipeline a model consumes.

Enumerator
AI_SENSOR_IMU 

BMI270 accel+gyro via ipc_sensorhub (CM33-owned)

AI_SENSOR_RADAR 

BGT60TR13C frames from the CM55 radar task

AI_SENSOR_MIC 

PDM microphone front-end (audio_pdm.c), shared by all mic models

Function Documentation

◆ ai_engine_register()

int ai_engine_register ( const ai_model_desc_t * desc)

Register a model descriptor at run time. Returns its registry index, or -1.

BEFORE YOU USE THIS: confirm the archive beside you exports it — grep ai_engine_register lib/edge_ai/api.txt An archive cut before this symbol was exported carries it under an internal name, and the link fails with "undefined reference to ai_engine_register". The compile-time route (modules/ai_models/README.md, "Filling a model slot") works against every build.

This is the engine's open extension point: a model added here needs no rebuilt engine, no fixed slot name, and no source from TESAIoT. Fill in an ai_model_desc_t with your own init/enqueue/dequeue/finalize and the model joins the registry, the Edge AI menu and the sets like any built-in one. The compile-time alternative — filling one of the named slots the engine already imports — is in modules/ai_models/README.md, "Filling a model slot".

Task context only. The registry is read from the IPC pipe callback in ISR context, so registration runs inside a critical section rather than behind a mutex the ISR could not take. Do not call it from an ISR.

The descriptor is COPIED; the pointers inside it are not. name, description and every class_labels[] entry must outlive the boot, and they are read from an ISR. String literals and static buffers qualify. A stack buffer does not.

Rejected if: the descriptor is incomplete, class_count is 0 or above AI_MAX_CLASSES, capacity is exhausted, or the name duplicates a row that is already registered. Names are the key for set membership and for the watch threshold overrides, so a duplicate is a correctness problem, not a cosmetic one.

Rows cannot be removed. Every reader is lockless because an index that was once valid stays valid; removal would invalidate that and needs its own design.

◆ ai_engine_dyn_count()

uint32_t ai_engine_dyn_count ( void )

Rows added at run time so far, and the ceiling.

◆ ai_engine_dyn_capacity()

uint32_t ai_engine_dyn_capacity ( void )