/* tsdk_pair2: same-frame capture of official pipeline outputs. * Per frame (synced to ThermalSDK callback): * - gray : 8-bit display gray buffer dev+0x220 (160x120) * - rgb : RGB24 render 160x120 (MAG_GetOutputBMPdataRGB24, order=1) * - raw : u16 counts frame dev+0x270 (post-NUC processed frame) * - palette: 256x4 BGRx dev+0xb18 * - temps : u32 per-pixel temps MAG_GetTemperatureData_Raw * - cbRGB : ThermalSDK 320x240 callback frame * - points : ReadTemperatureAtPoint at several points * Also dumps device-struct bytes around the display header (dev+0xaf0..) and * the window fields found in the struct, for calibration. */ #define _WIN32_WINNT 0x0601 #include #include #include #include #include #include typedef void (CALLBACK *INewIRFrame)(const unsigned char *, int, int, int); typedef bool (CALLBACK *fn_Start_t)(void); typedef void (CALLBACK *fn_Stop_t)(void); typedef void (CALLBACK *fn_SetNewIRFrameDelegate_t)(INewIRFrame); typedef void (CALLBACK *fn_SetTempBoundary_t)(double, double, double); typedef void (CALLBACK *fn_SetUnitMode_t)(int); typedef void (CALLBACK *fn_ReadTemperatureAtPoint_t)(int, int, unsigned char *); typedef int (CALLBACK *MAG_GetOutputBMPdata_t)(int, unsigned char **, void **); typedef int (CALLBACK *MAG_GetOutputBMPdataRGB24_t)(int, unsigned char *, int, int); typedef int (CALLBACK *MAG_GetTemperatureData_Raw_t)(int, unsigned int *, int, int); typedef int (CALLBACK *MAG_GetOutputColorBardata_t)(int, void **, void **); typedef int (CALLBACK *MAG_TriggerFFC_t)(int, int); static volatile int g_frames; static unsigned char g_cb[320 * 240 * 3]; static int g_cbw, g_cbh; static const char *g_dir = "."; static void CALLBACK onIR(const unsigned char *buf, int w, int h, int ch) { if (buf && w > 0 && h > 0 && ch == 3) { memcpy(g_cb, buf, (size_t)w * h * ch); g_cbw = w; g_cbh = h; } g_frames++; } static void save(const char *name, const void *buf, size_t n) { char path[512]; snprintf(path, sizeof(path), "%s\\%s", g_dir, name); FILE *f = fopen(path, "wb"); if (f) { fwrite(buf, 1, n, f); fclose(f); } } int main(int argc, char **argv) { int npairs = 24; int start_delay = 6000; double tb[3] = {30.0, 44.0, 37.0}; if (argc > 1) g_dir = argv[1]; if (argc > 2) npairs = atoi(argv[2]); if (argc > 3) start_delay = atoi(argv[3]); if (argc > 4) tb[0] = atof(argv[4]); if (argc > 5) tb[1] = atof(argv[5]); if (argc > 6) tb[2] = atof(argv[6]); SetDllDirectoryA("C:\\Project\\MAG160C\\IR_Camera_SDK-1.0.1\\windows\\windows\\app"); HMODULE t = LoadLibraryA("ThermalSDK.dll"); HMODULE c = LoadLibraryA("CoreSDKLib.dll"); printf("T=%p C=%p\n", (void*)t, (void*)c); if (!t || !c) return 1; fn_Start_t T_Start = (fn_Start_t)GetProcAddress(t, "Start"); fn_Stop_t T_Stop = (fn_Stop_t)GetProcAddress(t, "Stop"); fn_SetNewIRFrameDelegate_t T_Set = (fn_SetNewIRFrameDelegate_t)GetProcAddress(t, "SetNewIRFrameDelegate"); fn_SetTempBoundary_t T_Bound = (fn_SetTempBoundary_t)GetProcAddress(t, "SetTempBoundary"); fn_SetUnitMode_t T_Unit = (fn_SetUnitMode_t)GetProcAddress(t, "SetUnitMode"); fn_ReadTemperatureAtPoint_t T_Temp = (fn_ReadTemperatureAtPoint_t)GetProcAddress(t, "ReadTemperatureAtPoint"); MAG_GetOutputBMPdata_t G_Gray = (MAG_GetOutputBMPdata_t)GetProcAddress(c, "MAG_GetOutputBMPdata"); MAG_GetOutputBMPdataRGB24_t G_RGB = (MAG_GetOutputBMPdataRGB24_t)GetProcAddress(c, "MAG_GetOutputBMPdataRGB24"); MAG_GetTemperatureData_Raw_t G_TempRaw = (MAG_GetTemperatureData_Raw_t)GetProcAddress(c, "MAG_GetTemperatureData_Raw"); MAG_GetOutputColorBardata_t G_Bar = (MAG_GetOutputColorBardata_t)GetProcAddress(c, "MAG_GetOutputColorBardata"); printf("Start=%p TempPoint=%p Gray=%p RGB=%p TempRaw=%p Bar=%p\n", (void*)T_Start, (void*)T_Temp, (void*)G_Gray, (void*)G_RGB, (void*)G_TempRaw, (void*)G_Bar); if (!T_Start || !T_Set || !G_Gray || !G_RGB) { printf("missing export\n"); return 2; } if (T_Unit) T_Unit(0); if (T_Bound) T_Bound(tb[0], tb[1], tb[2]); printf("SetTempBoundary(%.1f, %.1f, %.1f)\n", tb[0], tb[1], tb[2]); fflush(stdout); T_Set(onIR); printf("Start()...\n"); fflush(stdout); BOOL ok = T_Start(); printf("Start=%d\n", ok); fflush(stdout); printf("warming %d ms...\n", start_delay); fflush(stdout); Sleep(start_delay); /* locate channel device */ unsigned char *gray = NULL; void *hdr = NULL; int chan = -1; for (int i = 0; i < 8; ++i) { int rc = G_Gray(i, &gray, &hdr); printf("chan %d: rc=%d gray=%p hdr=%p\n", i, rc, (void*)gray, (void*)hdr); if (rc && gray && hdr) { chan = i; break; } } if (chan < 0) { printf("no channel\n"); T_Stop(); return 3; } unsigned char *dev = (unsigned char *)hdr - 0xaf0; int w = *(int *)(dev + 0xaf4); int h = *(int *)(dev + 0xaf8); printf("dev=%p w=%d h=%d graybuf=%p rawp=%p\n", (void*)dev, w, h, (void*)gray, (void*)*(void **)(dev + 0x270)); /* probe pointer fields near 0x250..0x2b0 (buffer pointers) */ for (int off = 0x240; off <= 0x2b0; off += 8) { void *p = *(void **)(dev + off); printf(" dev+0x%03x = %p\n", off, p); } if (w <= 0 || w > 1000 || h <= 0 || h > 1000) { w = 160; h = 120; } int n = w * h; int nw = w / 2, nh = h / 2; /* sensor frame 160x120 if 2x mode */ int nn = nw * nh; printf("capturing %d pairs (disp %dx%d, sensor %dx%d)...\n", npairs, w, h, nw, nh); fflush(stdout); unsigned char *rgb = malloc((size_t)n * 3); unsigned short *raw = malloc((size_t)nn * 2); unsigned char *pal = malloc(256 * 4); unsigned int *t32 = malloc((size_t)n * 4); unsigned char *g2 = malloc((size_t)n); int pts[][2] = {{80, 60}, {40, 40}, {120, 80}, {80, 30}, {30, 90}, {130, 100}, {10, 10}, {150, 110}, {80, 10}, {5, 115}, {155, 5}, {20, 60}}; int np = sizeof(pts) / sizeof(pts[0]); MAG_TriggerFFC_t G_FFC = (MAG_TriggerFFC_t)GetProcAddress(c, "MAG_TriggerFFC"); printf("TriggerFFC=%p\n", (void*)G_FFC); fflush(stdout); int prev = g_frames; for (int k = 0; k < npairs; ++k) { /* optional FFC triggers at specific pairs */ if (G_FFC && k == npairs / 3) { printf(">>> TriggerFFC(1)\n"); fflush(stdout); G_FFC(chan, 1); Sleep(1500); prev = g_frames; } if (G_FFC && k == 2 * npairs / 3) { printf(">>> TriggerFFC(0)\n"); fflush(stdout); G_FFC(chan, 0); Sleep(1500); prev = g_frames; } /* wait for a new callback frame, then a small settle */ int t0 = GetTickCount(); while (g_frames == prev && GetTickCount() - t0 < 3000) Sleep(5); prev = g_frames; Sleep(2); /* same-frame snapshot */ memcpy(g2, gray, (size_t)n); /* dev+0x220 gray (320x240) */ int rcr = G_RGB(chan, rgb, n * 3, 1); /* RGB24 320x240 */ unsigned short *rawp = *(unsigned short **)(dev + 0x270); memcpy(raw, rawp, (size_t)nn * 2); /* u16 sensor frame 160x120 */ memcpy(pal, dev + 0xb18, 256 * 4); /* palette */ int rct = G_TempRaw ? G_TempRaw(chan, t32, nn * 4, 1) : 0; /* frame counter + dev struct fields */ unsigned int fcnt = *(unsigned int *)(dev + 0x8); unsigned int win_hi = *(unsigned int *)(dev + 0x4202c); unsigned int win_lo = *(unsigned int *)(dev + 0x42030); unsigned int win_span = win_hi > win_lo ? win_hi - win_lo : 0; unsigned int pcount = *(unsigned int *)(dev + 0x47938); unsigned int comp_off = *(unsigned int *)(dev + 0x47948); unsigned int comp_shift = *(unsigned int *)(dev + 0x4794c); unsigned int gain = *(unsigned int *)0x18006ea60; /* global */ unsigned int smooth_mode = *(unsigned int *)(dev + 0x41fdc); unsigned int has_ref = *(unsigned int *)(dev + 0x41f0c); unsigned short *refp = *(unsigned short **)(dev + 0x41ef0); unsigned int m47944 = *(unsigned int *)(dev + 0x47944); unsigned int m47950 = *(unsigned int *)(dev + 0x47950); unsigned int m47954 = *(unsigned int *)(dev + 0x47954); unsigned int t_base = *(unsigned int *)0x1800990c0; unsigned int t_now = *(unsigned int *)0x1800990c4; unsigned int m41848 = *(unsigned int *)(dev + 0x41848); unsigned int m41858 = *(unsigned int *)(dev + 0x41858); unsigned int m41340 = *(unsigned int *)(dev + 0x41340); unsigned int m41348 = *(unsigned int *)(dev + 0x41348); unsigned int m41fe0 = *(unsigned int *)(dev + 0x41fe0); unsigned int m41f3c = *(unsigned int *)(dev + 0x41f3c); unsigned int m41840 = *(unsigned int *)(dev + 0x41840); unsigned int m41554 = *(unsigned int *)(dev + 0x41554); unsigned int m41558 = *(unsigned int *)(dev + 0x41558); unsigned int m4155c = *(unsigned int *)(dev + 0x4155c); unsigned int m41560 = *(unsigned int *)(dev + 0x41560); unsigned int m41564_0 = *(unsigned int *)(dev + 0x41564); unsigned int m41568_0 = *(unsigned int *)(dev + 0x41568); unsigned int m54 = *(unsigned int *)(dev + 0x54); char base[64]; snprintf(base, sizeof(base), "pair_%03d", k); { char nm[128]; snprintf(nm, sizeof(nm), "%s.win", base); FILE *f = fopen(nm, "wb"); if (f) { fwrite(&win_hi, 4, 1, f); fwrite(&win_lo, 4, 1, f); fwrite(&pcount, 4, 1, f); fwrite(&comp_off, 4, 1, f); fwrite(&comp_shift, 4, 1, f); fwrite(&gain, 4, 1, f); fwrite(&smooth_mode, 4, 1, f); fwrite(&has_ref, 4, 1, f); fclose(f); } /* extra fields for NUC-path analysis */ snprintf(nm, sizeof(nm), "%s.win2", base); { FILE *f2 = fopen(nm, "wb"); if (f2) { unsigned int v[14] = {m47944, m47950, m47954, t_base, t_now, m41848, m41858, m41340, m41348, m41fe0, comp_off, comp_shift, gain, smooth_mode}; fwrite(v, 4, 14, f2); fclose(f2); } } /* NUC lookup tables: thresholds (0x41858) + gain/offset (0x41870) heads */ { unsigned short th[16], g0[16], g1[16]; memcpy(th, dev + 0x41858, 32); memcpy(g0, dev + 0x41870, 32); memcpy(g1, dev + 0x41870 + 2 * 19200 * 2, 32); snprintf(nm, sizeof(nm), "%s.nuctab", base); { FILE *f3 = fopen(nm, "wb"); if (f3) { fwrite(th, 2, 16, f3); fwrite(g0, 2, 16, f3); fwrite(g1, 2, 16, f3); fclose(f3); } } printf(" nuctab th[0:4]=%d,%d,%d,%d g0[0:4]=%d,%d,%d,%d g1[0:4]=%d,%d,%d,%d\n", th[0], th[1], th[2], th[3], g0[0], g0[1], g0[2], g0[3], g1[0], g1[1], g1[2], g1[3]); } /* NUC lookup tables: pointers at 0x41858 (thresholds) and 0x41870 (gain/off) */ { unsigned int nsegs = *(unsigned int *)(dev + 0x41554); void *thrp = *(void **)(dev + 0x41858); void *gainp = *(void **)(dev + 0x41870); printf(" nsegs=%u thrp=%p gainp=%p\n", nsegs, thrp, gainp); if (thrp) { snprintf(nm, sizeof(nm), "%s.thr", base); save(nm, thrp, 19200 * 2 * nsegs); } if (gainp && nsegs <= 64) { snprintf(nm, sizeof(nm), "%s.gain", base); save(nm, gainp, 19200 * 4 * nsegs); } } /* LUT1024 at dev+0x4284c */ { unsigned int nsegs = *(unsigned int *)(dev + 0x41554); unsigned int segsz = nsegs * 19200u * 4u; printf(" nsegs=%u table_bytes=%u\n", nsegs, segsz); snprintf(nm, sizeof(nm), "%s.thr_inline", base); save(nm, dev + 0x41848, (nsegs * 2) > 4096 ? 4096 : (nsegs * 2)); if (segsz <= 24u * 1024u * 1024u && nsegs <= 512) { snprintf(nm, sizeof(nm), "%s.gain_inline", base); save(nm, dev + 0x41870, segsz); } } /* LUT1024 at dev+0x4284c */ snprintf(nm, sizeof(nm), "%s.lut", base); save(nm, dev + 0x4284c, 1024); /* histogram 256 bins at dev+0x4204c */ snprintf(nm, sizeof(nm), "%s.hist", base); save(nm, dev + 0x4204c, 256 * 4); /* reference frame if present */ if (refp) { snprintf(nm, sizeof(nm), "%s.ref", base); save(nm, refp, (size_t)nn * 2); } /* NUC input candidates: buffers pointed by 0x41848..0x41878 */ { void *p[8]; p[0] = *(void **)(dev + 0x41840); p[1] = *(void **)(dev + 0x41848); p[2] = *(void **)(dev + 0x41850); p[3] = *(void **)(dev + 0x41858); p[4] = *(void **)(dev + 0x41860); p[5] = *(void **)(dev + 0x41868); p[6] = *(void **)(dev + 0x41870); p[7] = *(void **)(dev + 0x41878); printf(" ptrs418x: "); for (int bi = 0; bi < 8; ++bi) printf("%d=%p ", bi, p[bi]); printf("\n"); for (int bi = 0; bi < 8; ++bi) { if (!p[bi]) continue; snprintf(nm, sizeof(nm), "%s.b%02d", base, bi); save(nm, p[bi], (size_t)nn * 2); } } /* smoother output buffer (0x41f10+0x10) and 0x41f20 target */ { void *smo = *(void **)(dev + 0x41f10); if (smo) { void *sout = *(void **)((unsigned char *)smo + 0x10); if (sout) { snprintf(nm, sizeof(nm), "%s.smo", base); save(nm, sout, (size_t)nn * 2); } void *acc = *(void **)((unsigned char *)smo + 0x18); if (acc) { snprintf(nm, sizeof(nm), "%s.smoacc", base); save(nm, acc, (size_t)nn * 4); /* u32 accumulator */ } } void *f20 = *(void **)(dev + 0x41f20); if (f20) { snprintf(nm, sizeof(nm), "%s.f20", base); save(nm, f20, (size_t)nn * 2); } } /* 0x41ee0 smoother accumulator + frame counters */ { void *e0 = *(void **)(dev + 0x41ee0); void *e0acc = *(void **)((unsigned char *)dev + 0x41ef8); if (e0acc) { snprintf(nm, sizeof(nm), "%s.e0acc", base); save(nm, e0acc, (size_t)nn * 4); } void *e0buf = *(void **)((unsigned char *)dev + 0x41ee8); if (e0buf) { snprintf(nm, sizeof(nm), "%s.e0buf", base); save(nm, e0buf, (size_t)nn * 2); } unsigned int cnt1 = *(unsigned int *)(dev + 0x41ee0 + 0x20); unsigned int cnt2 = *(unsigned int *)(dev + 0x41f10 + 0x20); unsigned int gfc = *(unsigned int *)(0x180073bec); unsigned int ffcst = *(unsigned int *)(0x180073bf4); snprintf(nm, sizeof(nm), "%s.cnt", base); { unsigned int v[4] = {cnt1, cnt2, gfc, ffcst}; save(nm, v, 16); } printf(" cnt: e0=%u f10=%u globframe=%u ffcstate=%u\n", cnt1, cnt2, gfc, ffcst); } /* dump smoother object internals + mode fields */ { unsigned char s1[0x40], s2[0x40]; unsigned int modes[6]; memcpy(s1, dev + 0x41ee0, 0x40); memcpy(s2, dev + 0x41f10, 0x40); modes[0] = *(unsigned int *)(dev + 0x41fd8); modes[1] = *(unsigned int *)(dev + 0x41fdc); modes[2] = *(unsigned int *)(dev + 0x41fe0); modes[3] = *(unsigned int *)(dev + 0x41fe4); modes[4] = *(unsigned int *)(dev + 0x41fdc); modes[5] = *(unsigned int *)(dev + 0x11c); snprintf(nm, sizeof(nm), "%s.smo1", base); save(nm, s1, 0x40); snprintf(nm, sizeof(nm), "%s.smo2", base); save(nm, s2, 0x40); snprintf(nm, sizeof(nm), "%s.modes", base); save(nm, modes, 24); printf(" modes: fd8=%u fdc=%u fe0=%u fe4=%u 11c=%u refp=%p f20p=%p\n", modes[0], modes[1], modes[2], modes[3], modes[5], (void*)refp, (void*)*(void **)(dev + 0x41f20)); } /* stream parameters: transport object = channel_table[chan].slot1 */ { unsigned char *tobj = *(unsigned char **)(0x180073750 + (size_t)chan * 0x4a8 + 8); if (tobj) { unsigned int v[6]; v[0] = *(unsigned int *)(tobj + 0x2d78); v[1] = *(unsigned int *)(tobj + 0x2d88); v[2] = *(unsigned int *)(tobj + 0x2d8c); v[3] = *(unsigned int *)(tobj + 0x2d90); v[4] = *(unsigned int *)(tobj + 0x2d94); v[5] = *(unsigned int *)(tobj + 0x2d98); snprintf(nm, sizeof(nm), "%s.stream", base); save(nm, v, 24); printf(" stream: 2d78=%u 2d88=%u 2d8c=%u 2d90=%u 2d94=%u 2d98=%u\n", v[0], v[1], v[2], v[3], v[4], v[5]); } } } printf(" window hi=%u lo=%u span=%u pixels=%u comp_off=%u shift=%u gain=%u sm=%u ref=%u\n", win_hi, win_lo, win_span, pcount, comp_off, comp_shift, gain, smooth_mode, has_ref); printf(" p47944=%u p47950=%u p47954=%u t_base=%u t_now=%u 41848=%u 41858=%u 41340=%u 41348=%u 41fe0=%u\n", m47944, m47950, m47954, t_base, t_now, m41848, m41858, m41340, m41348, m41fe0); printf(" f3c=%u 41840=%u 41554=%u 41558=%u 4155c=%u 41560=%u b64_0=%u b68_0=%u dev54=%u\n", m41f3c, m41840, m41554, m41558, m4155c, m41560, m41564_0, m41568_0, m54); fflush(stdout); { char nm[128]; snprintf(nm, sizeof(nm), "%s.gray", base); save(nm, g2, (size_t)n); snprintf(nm, sizeof(nm), "%s.rgb", base); save(nm, rgb, (size_t)n * 3); snprintf(nm, sizeof(nm), "%s.raw", base); save(nm, raw, (size_t)nn * 2); snprintf(nm, sizeof(nm), "%s.pal", base); save(nm, pal, 256 * 4); snprintf(nm, sizeof(nm), "%s.cbrgb", base); save(nm, g_cb, (size_t)g_cbw * g_cbh * 3); if (rct) { snprintf(nm, sizeof(nm), "%s.t32", base); save(nm, t32, (size_t)nn * 4); } } /* header block dump: 0xaf0..0xaf0+0x60 (hdr + w/h + extra) */ unsigned char hdrblk[0x60]; memcpy(hdrblk, hdr, sizeof(hdrblk)); { char nm[128]; snprintf(nm, sizeof(nm), "%s.hdr", base); save(nm, hdrblk, sizeof(hdrblk)); } /* color bar data */ if (G_Bar) { void *bdata = NULL, *binfo = NULL; int rcb = G_Bar(chan, &bdata, &binfo); printf(" bar rc=%d data=%p info=%p\n", rcb, bdata, binfo); if (rcb && bdata) { char nm[128]; snprintf(nm, sizeof(nm), "%s.bar", base); save(nm, bdata, 4096); snprintf(nm, sizeof(nm), "%s.barinfo", base); save(nm, binfo ? binfo : bdata, 64); } } /* temperature points */ printf("[%d] frames=%d fcnt=%u rc_rgb=%d rc_temp=%d cb=%dx%d\n", k, g_frames, fcnt, rcr, rct, g_cbw, g_cbh); for (int p = 0; p < np; ++p) { unsigned char res[64] = {0}; if (T_Temp) T_Temp(pts[p][0], pts[p][1], res); double tr = *(double *)(res + 16); double ta = *(double *)(res + 24); int rx = pts[p][0] / 2, ry = pts[p][1] / 2; unsigned int rawv = raw[ry * nw + rx]; unsigned char gv = g2[pts[p][1] * w + pts[p][0]]; unsigned int tv = rct ? t32[pts[p][1] * w + pts[p][0]] : 0; printf(" pt(%3d,%3d) raw@(%3d,%3d)=%5u gray=%3u temp32=%10u tempRaw=%.2f tempArm=%.2f\n", pts[p][0], pts[p][1], rx, ry, rawv, gv, tv, tr, ta); } fflush(stdout); Sleep(100); } /* summary stats of raw/gray from last frame */ { unsigned long long sr = 0, sg = 0; unsigned int mnr = 0xffff, mxr = 0, mng = 0xff, mxg = 0; unsigned int hist[256] = {0}; for (int i = 0; i < nn; ++i) { unsigned int r = raw[i]; sr += r; if (r < mnr) mnr = r; if (r > mxr) mxr = r; } for (int i = 0; i < n; ++i) { unsigned int g = g2[i]; sg += g; hist[g]++; if (g < mng) mng = g; if (g > mxg) mxg = g; } printf("raw160: min=%u max=%u mean=%.1f gray320: min=%u max=%u mean=%.1f\n", mnr, mxr, (double)sr / nn, mng, mxg, (double)sg / n); printf("gray histogram (nonzero bins):\n"); for (int i = 0; i < 256; ++i) if (hist[i]) printf(" %3d:%6u\n", i, hist[i]); fflush(stdout); } /* scan device struct for interesting constant values */ { printf("struct scan:\n"); /* 1. look for window values as u32/u16 in wide range */ int tw32[] = {22500, 23700, 25167, 31707, 5797, 1200}; for (int off = 0x100; off < 0x10000; off += 4) { int v = *(int *)(dev + off); for (int t = 0; t < 6; ++t) if (v == tw32[t]) printf(" dev+0x%04x u32 = %d (t%d)\n", off, v, t); } for (int off = 0x100; off < 0x10000; off += 2) { short v = *(short *)(dev + off); for (int t = 0; t < 6; ++t) if (v == tw32[t]) printf(" dev+0x%04x u16 = %d (t%d)\n", off, v, t); } /* 2. look for 1024-byte monotone 0..255 table (LUT) */ for (int off = 0x100; off < 0x20000 - 1024; off += 16) { const unsigned char *p = dev + off; int ok = 1, last = -1; for (int i = 0; i < 1024; i += 8) { int v = p[i]; if (v < last || v > 255) { ok = 0; break; } if (p[i] != p[i+1] && p[i+1] != p[i]) { /* non-strict ok */ } last = v; } if (!ok) continue; /* require at least 32 distinct values and spans > 100 */ int mn = 255, mx = 0; for (int i = 0; i < 1024; ++i) { if (p[i] < mn) mn = p[i]; if (p[i] > mx) mx = p[i]; } if (mx - mn > 100) { printf(" LUT candidate dev+0x%04x: min=%d max=%d first=%d last=%d\n", off, mn, mx, p[0], p[1023]); } } /* 3. look for window as double */ for (int off = 0x100; off < 0x10000; off += 8) { double v = *(double *)(dev + off); if (v > 20000.0 && v < 40000.0 && fabs(v - 25167.0) < 10.0) printf(" dev+0x%04x double ~= %.1f\n", off, v); } fflush(stdout); } T_Stop(); printf("done\n"); return 0; }