Files

507 lines
23 KiB
C

/* 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 <windows.h>
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
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;
}