Files
MAG160C/csdk/include/mag160c/mag160c_render.h
T
ZXCLI 9db940a615 demo3 迁移到 mag160c_render 抽象库(v6);render 库加手动 FFC/NUC 访问器/钩子
- mag160c_demo3.c 从内联管线重写为 render API 调用:删除 DDT 加载/NUC/
  LUT/gray/2x/FFC 状态机实现(~700 行),保留 USB 取帧/GDI/探针/附加环节
- 附加环节(0x230 帧差/0x41fe8 隔行平滑/0x30 gray 覆盖)经 render 的
  post_nuc/post_gray 钩子挂接,编译开关与运行时按键 0/8/9 不变
- mag160c_render 新增 mag160c_render_request_ffc / get_nuc 访问器
- 实测无回归:FFC 时序 init@20→FFC(1)@28→漂移触发,与 v5 一致;
  stats 正常,auto BMP 生成正常;全开关版本编译通过
- linux_demo 修帧组装(38400px+28B 尾),快门=31492 sel=2 正常
2026-08-19 15:41:34 +08:00

111 lines
4.7 KiB
C

/*
* mag160c_render.h - platform-independent official rendering pipeline.
*
* Mirrors the official CoreSDKLib.dll frame path (verified pixel-exact):
* raw frame -> shutter extract -> FFC state machine -> endpoint select
* + Q12 table interp -> ref (4x type-1 mean) -> NUC lookup -> blind
* compensation -> stats/window -> LUT1024 rebuild -> gray -> 2x
* upscale -> palette -> RGB24 output.
*
* No OS/display dependencies: feed it USB frames, get 320x240 RGB24.
* FFC commands are emitted through a callback so the caller owns the
* transport (libusb on Linux, bulk transfers on Windows, ...).
*/
#ifndef MAG160C_RENDER_H
#define MAG160C_RENDER_H
#include <stdint.h>
#include <stddef.h>
#include "mag160c.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Default output geometry (official: 2x of the 160x120 sensor). */
#define MAG160C_RENDER_OUT_W 320
#define MAG160C_RENDER_OUT_H 240
/* FFC command callback: param 0 = FFC(0), 1 = FFC(1). */
typedef void (*mag160c_render_ffc_cb_t)(void *user, int param);
/* Optional post-NUC hook (called after NUC+blind, before stats/window).
* Lets the app run the official extra paths (frame-diff 0x230, interlace
* smoothing 0x41fe8) on the NUC buffer. */
typedef void (*mag160c_render_post_nuc_cb_t)(void *user, unsigned short *nuc);
/* Optional post-gray hook (called after the 160x120 gray is mapped,
* before the 2x upscale). Lets the app run the official 0x30 gray
* overlay paths (0x17770 auto / 0x17c40 manual) on the gray buffer. */
typedef void (*mag160c_render_post_gray_cb_t)(void *user, unsigned char *gray160);
typedef struct mag160c_render_t mag160c_render_t;
typedef struct mag160c_render_cfg_t {
uint16_t width; /* sensor width, 160 */
uint16_t height; /* sensor height, 120 */
const char *ddt_path; /* official DDT calibration file */
int ffc_period; /* frames between FFC pairs, official 1800 */
int ffc_drift; /* shutter drift threshold, official 250 */
int startup_force_ffc; /* official frame-75 forced FFC, 1 = on */
int warm_frames; /* frames dropped after start, official 20 */
int cdf_pivot_75; /* 0x8c: CDF pivot at 75% cumulative, 1 = on */
mag160c_render_ffc_cb_t ffc_cb;
void *ffc_user;
mag160c_render_post_nuc_cb_t post_nuc_cb;
void *post_nuc_user;
mag160c_render_post_gray_cb_t post_gray_cb;
void *post_gray_user;
} mag160c_render_cfg_t;
MAG160C_API mag160c_error_t
mag160c_render_init(mag160c_render_t **out, const mag160c_render_cfg_t *cfg);
/* Process one raw frame.
* frame : USB frame buffer. If has_hdr, the 28-byte header is at
* frame[0] (marker 0x1bb1b11b, counter, len, type, ...) and
* the shutter word is extracted from the tail; otherwise
* frame is the bare 38400-byte pixel buffer and shutter
* must be supplied via mag160c_render_set_shutter().
* out_rgb : 320x240x3 RGB24 (palette-colored).
* Returns MAG160C_OK when out_rgb was written, MAG160C_ERR_NOT_READY
* while the startup/FFC window is running (image frozen by caller). */
MAG160C_API mag160c_error_t
mag160c_render_frame(mag160c_render_t *r, const uint8_t *frame,
int has_hdr, uint8_t *out_rgb);
/* Bare-pixel mode: set the current shutter (device temperature proxy)
* before calling mag160c_render_frame(). */
MAG160C_API void mag160c_render_set_shutter(mag160c_render_t *r, int shutter);
/* Per-frame diagnostics for UI overlays. */
MAG160C_API void mag160c_render_get_stats(mag160c_render_t *r,
int *win_lo, int *win_hi,
int *fmin, int *fmax,
int *mean, int *stddev);
MAG160C_API int mag160c_render_get_shutter(mag160c_render_t *r);
MAG160C_API int mag160c_render_get_endpoint(mag160c_render_t *r);
MAG160C_API int mag160c_render_get_frame_index(mag160c_render_t *r);
MAG160C_API int mag160c_render_has_reference(mag160c_render_t *r);
/* Manual FFC trigger (official FFC button / recenter): forces FFC(0) at
* the next rendered frame. */
MAG160C_API void mag160c_render_request_ffc(mag160c_render_t *r);
/* NUC-domain pixel read (valid when mag160c_render_has_reference()).
* Returns 0 when no reference yet. Used for hot-spot scan / overlay. */
MAG160C_API uint32_t mag160c_render_get_nuc(mag160c_render_t *r, uint32_t idx);
/* Temperature probe on the current NUC output (millidegrees C). */
MAG160C_API mag160c_error_t
mag160c_render_probe_temp(mag160c_render_t *r, uint32_t x, uint32_t y,
int32_t *out_temp_mc);
MAG160C_API void mag160c_render_destroy(mag160c_render_t *r);
#ifdef __cplusplus
}
#endif
#endif /* MAG160C_RENDER_H */