README.md

# SSCMEx

`SSCMEx` is an Elixir NIF wrapper for SSCMA-Micro on SG2002/reCamera.

It provides:
- camera access (`SSCMEx.Camera`)
- model loading/inference (`SSCMEx.Engine`, `SSCMEx.Model`)
- zero-copy image structs (`SSCMEx.Image`)

## Installation

Add `sscmex` to your dependencies:

```elixir
def deps do
  [
    {:sscmex, "~> 0.1.0"}
  ]
end
```

## Manual IEx flow (camera -> TPU -> results)

Use this when you want to test manually without `SSCMEx.Examples.*`.

```elixir
# 1) Load NIF
:ok = SSCMEx.load_nif()

# 2) Device + camera
{:ok, device} = SSCMEx.Device.get_instance()
{:ok, camera} = SSCMEx.Camera.get(device, 0)

# 3) TPU engine + model
model_path = "/data/yolov8n_cv181x_int8.cvimodel"
{:ok, engine} = SSCMEx.Engine.new()
:ok = SSCMEx.Engine.load(engine, model_path)
{:ok, model} = SSCMEx.Model.create(engine)
:ok = SSCMEx.Model.set_config(model, :threshold_score, 0.5)
:ok = SSCMEx.Model.set_config(model, :threshold_nms, 0.45)

# 4) Camera config and stream
{:ok, :initialized} = SSCMEx.Camera.init(camera, 0)
{:ok, :ok} = SSCMEx.Camera.set_ctrl(camera, :channel, 0)
{:ok, :ok} = SSCMEx.Camera.set_ctrl(camera, :window, {640, 640})
{:ok, :ok} = SSCMEx.Camera.set_ctrl(camera, :format, :rgb888)
{:ok, :ok} = SSCMEx.Camera.set_ctrl(camera, :fps, 3)
{:ok, :streaming} = SSCMEx.Camera.start_stream(camera, :refresh_on_return)

Process.sleep(1500)

# 5) Grab frame and run inference
# retrieve_frame already returns %SSCMEx.Image{}
{:ok, image} = SSCMEx.Camera.retrieve_frame(camera, :rgb888)
{:ok, results} = SSCMEx.Model.run(model, image)
{:ok, perf} = SSCMEx.Model.get_perf(model)

IO.inspect(results, label: "results")
IO.inspect(perf, label: "perf")

# 6) Cleanup
{:ok, :stopped} = SSCMEx.Camera.stop_stream(camera)
{:ok, :deinitialized} = SSCMEx.Camera.deinit(camera)
```

`SSCMEx.Model.run/2` returns different result maps depending on model output type:

- `:boxes` (detection): `%{x, y, w, h, score, target}`
- `:classes` (classification): `%{score, target}`
- `:points`: `%{x, y, score, target}`
- `:keypoints` (pose): `%{box: %{x, y, w, h, score, target}, points: [%{x, y, z}, ...]}`
- `:segments` (segmentation): `%{box: %{x, y, w, h, score, target}, mask: %{width, height, data}}`

For backward compatibility, detection models still return the same bbox fields (`x`, `y`, `w`, `h`, `score`, `target`).

## Notes

- `SSCMEx.Camera.retrieve_frame/2` now returns `%SSCMEx.Image{}` directly.
- For one-shot tests, keep `fps` low (for example `3`) to reduce memory pressure.

## Runtime observability (SG2002)

When debugging camera/TPU contention, these runtime stats are useful:

- VB/ION pool status (best signal for camera-side memory pressure):
  - `cat /proc/cvitek/vb`
  - Look at per-pool `BlkSz`, `BlkCnt`, `Free`, and especially `MinFree`.
  - If `MinFree` drops near `0`, the pipeline is close to buffer exhaustion.

- TPU usage profiling:
  - Enable: `echo 1 > /proc/tpu/usage_profiling`
  - Read: `cat /proc/tpu/usage_profiling`
  - Disable: `echo 0 > /proc/tpu/usage_profiling`

- Per-inference model timings (already exposed by SSCMEx):
  - `{:ok, perf} = SSCMEx.Model.get_perf(model)`
  - Returns `%{preprocess: ms, inference: ms, postprocess: ms}` from the last run.

- Optional bandwidth monitor (if your image enables it):
  - `echo 1 > /proc/mon/bw_profiling`
  - `cat /proc/mon/profiling_window_ms`