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 正常
This commit is contained in:
ZXCLI
2026-08-19 15:41:34 +08:00
parent 5c22bfe78c
commit 9db940a615
4 changed files with 235 additions and 867 deletions
Binary file not shown.
+22
View File
@@ -29,6 +29,16 @@ extern "C" {
/* FFC command callback: param 0 = FFC(0), 1 = FFC(1). */ /* FFC command callback: param 0 = FFC(0), 1 = FFC(1). */
typedef void (*mag160c_render_ffc_cb_t)(void *user, int param); 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_t mag160c_render_t;
typedef struct mag160c_render_cfg_t { typedef struct mag160c_render_cfg_t {
@@ -42,6 +52,10 @@ typedef struct mag160c_render_cfg_t {
int cdf_pivot_75; /* 0x8c: CDF pivot at 75% cumulative, 1 = on */ int cdf_pivot_75; /* 0x8c: CDF pivot at 75% cumulative, 1 = on */
mag160c_render_ffc_cb_t ffc_cb; mag160c_render_ffc_cb_t ffc_cb;
void *ffc_user; 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_render_cfg_t;
MAG160C_API mag160c_error_t MAG160C_API mag160c_error_t
@@ -74,6 +88,14 @@ 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_get_frame_index(mag160c_render_t *r);
MAG160C_API int mag160c_render_has_reference(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). */ /* Temperature probe on the current NUC output (millidegrees C). */
MAG160C_API mag160c_error_t MAG160C_API mag160c_error_t
mag160c_render_probe_temp(mag160c_render_t *r, uint32_t x, uint32_t y, mag160c_render_probe_temp(mag160c_render_t *r, uint32_t x, uint32_t y,
+26 -1
View File
@@ -36,7 +36,7 @@ struct mag160c_render_t {
int blind_count; int blind_count;
/* frame/FFC state */ /* frame/FFC state */
int ffc_idx, global_frames, shutter, shutter_at_ffc; int ffc_idx, global_frames, shutter, shutter_at_ffc, manual_ffc;
int has_ref, ref_cnt, startup_ffc_done, ref_reset; int has_ref, ref_cnt, startup_ffc_done, ref_reset;
unsigned short *ref; unsigned short *ref;
unsigned int *ref_acc; unsigned int *ref_acc;
@@ -54,6 +54,10 @@ struct mag160c_render_t {
/* config */ /* config */
mag160c_render_ffc_cb_t ffc_cb; mag160c_render_ffc_cb_t ffc_cb;
void *ffc_user; 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;
int ffc_period, ffc_drift, warm_frames, cdf_pivot_75, force75; int ffc_period, ffc_drift, warm_frames, cdf_pivot_75, force75;
}; };
@@ -503,6 +507,10 @@ static int ffc_step(mag160c_render_t *r, int shutter) {
if (drift < 0) drift = -drift; if (drift < 0) drift = -drift;
int cool = OFF_N0 + OFF_N2 + OFF_N1; int cool = OFF_N0 + OFF_N2 + OFF_N1;
int do_ffc = 0; int do_ffc = 0;
if (r->manual_ffc) {
r->manual_ffc = 0;
do_ffc = 1;
}
if (r->force75 && !r->startup_ffc_done && idx == 75) { if (r->force75 && !r->startup_ffc_done && idx == 75) {
r->startup_ffc_done = 1; r->startup_ffc_done = 1;
do_ffc = 1; do_ffc = 1;
@@ -533,6 +541,10 @@ mag160c_error_t mag160c_render_init(mag160c_render_t **out,
r->npix = r->w * r->h; r->npix = r->w * r->h;
r->ffc_cb = cfg->ffc_cb; r->ffc_cb = cfg->ffc_cb;
r->ffc_user = cfg->ffc_user; r->ffc_user = cfg->ffc_user;
r->post_nuc_cb = cfg->post_nuc_cb;
r->post_nuc_user = cfg->post_nuc_user;
r->post_gray_cb = cfg->post_gray_cb;
r->post_gray_user = cfg->post_gray_user;
r->ffc_period = cfg->ffc_period ? cfg->ffc_period : 1800; r->ffc_period = cfg->ffc_period ? cfg->ffc_period : 1800;
r->ffc_drift = cfg->ffc_drift ? cfg->ffc_drift : 250; r->ffc_drift = cfg->ffc_drift ? cfg->ffc_drift : 250;
r->warm_frames = cfg->warm_frames ? cfg->warm_frames : 20; r->warm_frames = cfg->warm_frames ? cfg->warm_frames : 20;
@@ -606,9 +618,13 @@ mag160c_error_t mag160c_render_frame(mag160c_render_t *r, const uint8_t *frame,
if (!r->has_ref) return MAG160C_ERR_NOT_READY; if (!r->has_ref) return MAG160C_ERR_NOT_READY;
nuc_and_blind(r, live, r->nuc); nuc_and_blind(r, live, r->nuc);
if (r->post_nuc_cb)
r->post_nuc_cb(r->post_nuc_user, r->nuc);
stats_window(r, r->nuc); stats_window(r, r->nuc);
lut_rebuild(r, r->nuc); lut_rebuild(r, r->nuc);
gray_map(r, r->nuc); gray_map(r, r->nuc);
if (r->post_gray_cb)
r->post_gray_cb(r->post_gray_user, r->gray160);
upscale2x(r); upscale2x(r);
/* palette colorize 320x240 */ /* palette colorize 320x240 */
for (int i = 0; i < r->npix * 4; ++i) { for (int i = 0; i < r->npix * 4; ++i) {
@@ -663,3 +679,12 @@ void mag160c_render_destroy(mag160c_render_t *r) {
free(r->gray320); free(r->gray320);
free(r); free(r);
} }
void mag160c_render_request_ffc(mag160c_render_t *r) {
if (r) r->manual_ffc = 1;
}
uint32_t mag160c_render_get_nuc(mag160c_render_t *r, uint32_t idx) {
if (!r || !r->has_ref || idx >= (uint32_t)r->npix) return 0;
return r->nuc[idx];
}
+185 -864
View File
File diff suppressed because it is too large Load Diff