SDK สำหรับ TESAIoT Dev Kit
คู่มืออ้างอิง API และ Tutorial (MTB & µPython)
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)
 สมาชิกของ set ใด ๆ ตามลำดับใน registry; สมาชิกภาพที่กำหนดชัดแจ้งชนะขาด
const char * ai_engine_set_name (uint32_t set_index)
 ชื่อที่มนุษย์อ่านได้ของ set; คืน NULL สำหรับดัชนีที่ไม่ใช่ set
int ai_engine_set_define (uint32_t set_index, const uint8_t *members, uint32_t n)
 กำหนดสมาชิกภาพแบบชัดแจ้งให้ set ณ เวลาทำงาน; ต้องอยู่ใน task context และเป็นแบบทั้งหมดหรือไม่เอาเลย
uint32_t ai_engine_set_members_defined (uint32_t set_index, uint8_t *out, uint32_t max)
 สมาชิกภาพแบบชัดแจ้งหากมีการนิยามไว้ มิฉะนั้นได้ 0 — เป็น ack เดียวของ set_define
void ai_engine_unload (uint32_t idx)
 คำขอ unload แบบอะซิงโครนัส — จะถูกปฏิเสธ เว้นแต่ engine ว่างอยู่
uint32_t ai_engine_unload_done (void)
 ค่านับสะสมของ unload ที่ทำสำเร็จ; ให้อ่านเป็นคู่กับ refused
uint32_t ai_engine_unload_refused (void)
 ค่านับสะสมของ unload ที่ถูกปฏิเสธ; ให้อ่านคู่กับ ai_engine_unload_done()
uint32_t ai_engine_model_count (void)
 มีโมเดลลงทะเบียนไว้กี่ตัว; ค่านับนำหน้าแถวจริง
const ai_model_desc_tai_engine_model (uint32_t index)
 รายการใน registry คืน NULL หากอยู่นอกช่วง — และคืน NULL สำหรับดัชนีเทียมของ set
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)
 สร้าง inference task (idempotent); ต้องเรียกก่อน ai_engine_start()
bool ai_engine_start (uint32_t index)
 เปิดใช้งานโมเดล (หรือ set) ด้วยดัชนี แล้วเริ่มการอนุมาน; ต้องตรวจค่าที่คืนมา
uint32_t ai_engine_stack_words (void)
 ขนาด stack ที่ inference task ได้รับ หน่วยเป็นเวิร์ด; 0 = engine ไม่เคยเริ่มทำงาน — เป็น gate สากล
uint32_t ai_engine_feeds (void)
 จำนวนตัวอย่างที่โมเดลรับเข้าไป; ให้อ่านเป็นผลต่างในช่วงอย่างน้อย 1 s
uint32_t ai_engine_dq_ok (void)
 จำนวนการดึงคิวที่สำเร็จ; ค้างนิ่งขณะที่ dq_calls ไต่ขึ้น = NPU หยุดนิ่ง
uint32_t ai_engine_dq_calls (void)
 จำนวนครั้งที่พยายามดึงคิว; ให้จับคู่กับ ai_engine_dq_ok() เพื่อตรวจการหยุดนิ่ง
void ai_engine_set_sensor_rate (uint32_t interval_ms)
 ตั้งช่วงเวลาการป้อนข้อมูลของเซนเซอร์วัดความเร่ง; เป็นผู้ส่งรายเดียวที่ถูกต้องบน s_rate_msg
void ai_engine_resume_sensor (void)
 resume จังหวะค่าเริ่มต้นแบบยืนเดี่ยว; ห้ามเรียกติดกันกับการตั้งอัตรา
uint32_t ai_engine_inits (void)
 จำนวนการเริ่มต้นโมเดลที่สำเร็จ; เป็น nibble ที่อัดไว้ในเวิร์ดของสัญญาณชีพ
uint32_t ai_engine_init_calls (void)
 จำนวนครั้งที่เข้าไปเรียก init() ของโมเดล; ให้อ่านคู่กับ ai_engine_init_returns()
uint32_t ai_engine_init_returns (void)
 จำนวนครั้งที่ init() ของโมเดล RETURNED ออกมา; ให้อ่านเป็นคู่เสมอ
uint64_t ai_engine_npu_cycles (void)
 จำนวน cycle ของ NPU ที่สะสมมาถึงตอนนี้; ไม่ใช่หลักฐานว่ามีการอนุมานใดเสร็จสิ้น
uint32_t ai_engine_stale_drops (void)
 ผลตัดสินที่ถูกทิ้งเพราะเลยขอบเวลารอของ Ethos-U; ต้องนิ่งอยู่กับที่ขณะที่ npu_cycles เดินหน้า
uint32_t ai_engine_stack_free_words (void)
 ค่าต่ำสุดตลอดกาลของจำนวนเวิร์ดใน stack ที่ยังไม่ถูกใช้; เป็นการสแกนแบบ O(stack) — อ่านได้ไม่เกินประมาณ 1 Hz
int32_t ai_engine_last_init_rc (void)
 รหัสที่คืนจาก init() ของโมเดลครั้งล่าสุด: 0x7FFFFFFF = ไม่เคยถูกเรียก; 0 = ปกติ
void ai_engine_stop (void)
 หยุดโมเดลที่ active อยู่ (idempotent); ต้องจับคู่กับการลดอัตราเซนเซอร์ลง
int ai_engine_active (void)
 โมเดลที่ LOADED แล้ว (s_current) หรือ -1; ตามหลัง requested อยู่หนึ่งช่วง cold-init
int ai_engine_requested (void)
 โมเดลที่ REQUESTED ไว้ (s_active) หรือ -1; เป็นตัวกันที่ถูกต้องสำหรับ fallback
bool ai_engine_snapshot (ai_result_t *out)
 คัดลอกผลลัพธ์ล่าสุดที่เผยแพร่ไว้; เป็นแบบ last-writer-wins — ใช้ไม่ได้ภายใน set
bool ai_engine_snapshot_model (uint32_t index, ai_result_t *out)
 ผลตัดสินล่าสุดของโมเดลหนึ่งตัว — เป็นตัวอ่านที่ต้องใช้ภายใน parallel set
uint32_t ai_engine_set_members (uint8_t *idx, uint32_t max)
 ดัชนีใน registry ของสมาชิกใน set ที่ ACTIVE อยู่; ต้องตรวจเซนเซอร์ของสมาชิกแต่ละราย
bool ai_engine_mic_settling (void)
 เป็น true ตราบใดที่ parallel set ยังเติมหน้าต่างข้อมูลไม่เต็ม; ผลตัดสินจะถูกระงับไว้
uint32_t ai_engine_mic_settle_pct (void)
 ความคืบหน้าของการ settle 0..100; มีความหมายเฉพาะภายใน set เท่านั้น (นอกนั้นได้ 100)

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 )