From c6a843d051c247dcf45840348428e4c7c71b5a5d Mon Sep 17 00:00:00 2001 From: david rice Date: Thu, 9 Apr 2026 11:03:35 +0100 Subject: [PATCH] Updates --- __pycache__/analyze_captures.cpython-312.pyc | Bin 14516 -> 25505 bytes __pycache__/csv_preprocessor.cpython-312.pyc | Bin 33060 -> 36581 bytes analyze_captures.py | 82 +++++++++++++++++-- 3 files changed, 77 insertions(+), 5 deletions(-) diff --git a/__pycache__/analyze_captures.cpython-312.pyc b/__pycache__/analyze_captures.cpython-312.pyc index 41c16eced3589b43dadba530e1490dad805da55c..32f8dd07ea317fc4eed94265ae33dec9e6db807e 100644 GIT binary patch literal 25505 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 diff --git a/__pycache__/csv_preprocessor.cpython-312.pyc b/__pycache__/csv_preprocessor.cpython-312.pyc index 7478e7c81761412d834bb71ff092231644b6dd12..0e9ecbb436afc8e6b87c4a83055b4489bfc859cb 100644 GIT binary patch delta 5257 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 J{_YNn{|7=TL0SL+ delta 2568 zcmZ`)drVu`89(RT>x+$zjj;_j5I+DzjDhe73FHAQAtO~_p=r{I+kzpS3&9CVxke#m z*9l2ett4a!9jT&9qh!*wc1!+9b=9q#A|=(TCR3#A-n zqgiqmMlcum8%IsDDJ2{BXOEg?Gsu!`p;>YcHOf|Ml5I3w&ZTDAPAzgC&5<3Tb5g79 zqBc37=E?=sF1tbJp?PwlBF+7=sI-W>6cf!?iWM=sfxGhkhim7)@nw0bn~UsLkHg@3 zDCMW5pJ0#KXF_z{4{;ib6hAG7ca;)IZBwF@3=t3PGGw9NlLonT#et$Bk@`-Ga+xBr zo49B&nAXz(=u1FfPD@jcR)DLkl|b5tQUS7Q#a`N~NXvj7QY3;p5DlJ0wEQAT2X%2J zHo1~kWMT+|E%56HgCCM;2yBJvdRm#`Zw|xWBCP_?t5!TLhj}&ds+AgAvu`y*>T6Ih zvVV=dh9JeH)Lz8tjiY;b{%mWGm=TieVXZ+~6Wz;}Djcj;Fq&)kwZpe%DIM^dYbhy2 z?PwMal3{pzp;O|BThvg-;vAW=h_Dt%a^rzQSX-ymM-TE{!gU!=W~7AH7XnXdY)8GV z;6W4AtU+mts_eGlsi;<(GE8~H0VCKd`)>`*H!2&Vli+P(ONNNKI~y};#c1X+5lxaw zGDvXBsR>kyl+9&GEsbVkzxf>#9?(B)+lg_%-rC-Uai@M}tIdcH>gT%Z2{ZNhaXUM@JIHqQtQJR5oUqsB zKoQA!mKh;y&p-tP4YRwlOAw-#mC9vV;-V(T@Jv7xqc%|bf`+&h&x#v0!?=B==a80_ zF*HQtCQZ-?J1)C|rV*5BPfa?DsGu1kEy5=FY^F~{8hH|hME(5JGS0qlsH_=`9a_W@ z=IU)XW~=W3X)%kby|p60Mc6C7{@RZ~cm?_`_Dc|^&^;@%*=M8E(S))6tv%OA-yB^Q zh)tU6NJ?m3)6|b|v)n$9)iK*O-8COLU;a}0f+fJ3`?^We%D(CIlTQ)5VytEzk-7Cy zK$DVv$(9L2HY?eRNOQTX)UF6agyz91uuM8a&P7vacb77*jts_F?r|^M*gwtw+8@OE ztlHeG_Y4dP%&ho4Ud;f(KFl;UkXuC57Y(qxg${PG&4T?*YinRHDjSTqAt?1aMERgC zU;kXOW4y?O;ks2S?*nx$K*+9IxD2NYsa6gjvtJB{rN43U4!b&B;QoY*|K#u~hre_9 z2LQ|7D@z~pw3X=5y>~I2if+U?>`JtT^=~b;EpZ-)Yn(C*JvULZhT^|$v`5%Lvc_eLu$%UpGj11KsEv`Yv~eTVh211}SDA2Hil ziG)F=61IM9w;>xuGn*TG!^Rs(fOq+n389~d+40>vGsl{Qa9m<X{B}#r!Uw4(pafL5#z!ej;8F z*8ExtHSmQa@TLixpIHxi*hdpDo5NbgimsgN^z(;bC%NOBQx*Xhwe3G>ev_ehCs3$d z-=!G|Cam}9?{On@9s8PmhM0BgI})-%=lNno_~9v!&webaCnvjVmFVsxjyIO7aWotmH%kDXY* z_K^#de3hqEy~E-EbtCi%yL6%r|Al>V;sw)Bff}mxwRXldb>`Zto65de48@%l;y|Ddq>8-NH%VP`P=JeFQ;BC0=4O|GGjV8QR32#lp z8%}s@Q(sgkyzr|_c+2nkaxGF4(fs;odr|2goA_AeG}Oe4)>IWxo5uW$isQ_yOIco3-r~-%Z|%~ zm)*Z(nXGe64jAXu6& uOCmmA*tnb;le^f5Xa2QHvUN0zZ#Qr1Xd%~I4BLW+8-jbA-*Cgv<^KQx^O2PR diff --git a/analyze_captures.py b/analyze_captures.py index c28c5b4..9de6d24 100644 --- a/analyze_captures.py +++ b/analyze_captures.py @@ -29,6 +29,60 @@ from csv_preprocessor import ( DATA_DIR = Path(__file__).parent / "data" REPORTS_DIR = Path(__file__).parent / "reports" +# --------------------------------------------------------------------------- +# Confirmed device configuration — update here if hardware changes +# --------------------------------------------------------------------------- +# Derived values (do not edit — calculated from the constants above): +# HS bit rate = PIXEL_CLK_MHZ × COLOR_DEPTH_BPP / DSI_LANES +# = 72 × 24 / 4 = 432 Mbit/s per lane +# HS bit UI = 1 / 432e6 ≈ 2.315 ns +# Byte clock = 432 / 8 = 54 MHz → 18.518 ns/byte +# +# MIPI D-PHY v1.1 minimum timings at 432 Mbit/s: +# T_LPX ≥ 50 ns +# T_HS-PREPARE 40+4·UI → 85+6·UI = 49.3–98.9 ns +# T_HS-ZERO ≥ 145+10·UI = 168.2 ns +# T_HS-TRAIL ≥ max(8·UI, 60+4·UI) = 69.3 ns +# T_HS-EXIT ≥ 100 ns +# T_CLK-PREPARE 38–95 ns +# T_CLK-ZERO ≥ 300 ns +# T_CLK-POST ≥ 60+52·UI = 180.4 ns +# T_CLK-TRAIL ≥ 60 ns +# +# In byte-clock units (÷ 18.518 ns, round up): +# TLPX = 3 (55.6 ns) +# THS_PREPARE = 3 (55.6 ns — within 49.3–98.9 ns window) +# THS_ZERO = 10 (185.2 ns ≥ 168.2 ns ✓) +# THS_TRAIL = 4 (74.1 ns ≥ 69.3 ns ✓) +# THS_EXIT = 6 (111.1 ns ≥ 100 ns ✓) +# TCLK_PREPARE = 3 (55.6 ns — within 38–95 ns ✓) +# TCLK_ZERO = 17 (314.8 ns ≥ 300 ns ✓) +# TCLK_POST = 10 (185.2 ns ≥ 180.4 ns ✓) +# TCLK_TRAIL = 4 (74.1 ns ≥ 60 ns ✓) +DEVICE_CONFIG = { + "dsi_host": "NXP i.MX 8M Mini (Samsung DSIM IP, sec-dsim/samsung-dsim driver)", + "dsi_bridge": "Texas Instruments SN65DSI83 (MIPI-to-LVDS)", + "pixel_clock_mhz": 72, + "dsi_lanes": 4, + "color_format": "RGB888 (24 bpp)", + "hs_bit_rate_mbps": 432, # 72 × 24 / 4 + "hs_ui_ns": 2.315, # 1 / 432e6 + "byte_clock_mhz": 54, # 432 / 8 + "byte_period_ns": 18.518, + "vddio_v": 1.8, + # Correct DSIM PHY timing register values (byte-clock units, see derivation above) + # Samsung DSIM field mapping (sec_mipi_dsim.c / samsung-dsim.c): + # PHYTIMING (0xb4): [15:8]=TLPX, [7:0]=THS_EXIT + # PHYTIMING1 (0xb8): [31:24]=TCLK_PREPARE, [23:16]=TCLK_ZERO, + # [15:8]=TCLK_POST, [7:0]=TCLK_TRAIL + # PHYTIMING2 (0xbc): [23:16]=THS_TRAIL, [15:8]=THS_ZERO, [7:0]=THS_PREPARE + "dsim_phytiming_target": { + "PHYTIMING (0xb4)": "0x00000306 (TLPX=3→55.6ns, THS_EXIT=6→111ns)", + "PHYTIMING1 (0xb8)": "0x03110A04 (TCLK_PREPARE=3, TCLK_ZERO=17→315ns, TCLK_POST=10→185ns, TCLK_TRAIL=4→74ns)", + "PHYTIMING2 (0xbc)": "0x00040A03 (THS_TRAIL=4→74ns, THS_ZERO=10→185ns, THS_PREPARE=3→56ns)", + }, +} + CLAUDE_MODEL = "claude-opus-4-6" SYSTEM_PROMPT = ( "You are an expert in MIPI D-PHY signal integrity analysis. " @@ -41,11 +95,10 @@ SYSTEM_PROMPT = ( "lp (single-ended LP-11/LP-00/HS burst including SoT sequence), " "pwr (1.8 V supply captured during the LP→HS transition), " "and reg (DSIM register snapshot — DSIM_PHYTIMING at 0x32e100b4, " - "DSIM_PHYTIMING1 at 0xb8, DSIM_PHYTIMING2 at 0xbc control LP state durations " - "and PHY clock timing; DSIM_CLKCTRL at 0x08 and DSIM_ESCMODE at 0x14 affect " - "LP escape mode and HS entry sequencing). " + "DSIM_PHYTIMING1 at 0xb8, DSIM_PHYTIMING2 at 0xbc control LP/HS state durations; " + "timing fields are in byte-clock units where 1 unit = 18.518 ns at 432 Mbit/s). " "Analyse the data for trends, degradation, anomalies, or consistent spec concerns " - "across captures. Correlate register values with observed LP timing violations. " + "across captures. Correlate register field values with observed LP timing violations. " "Be concise and actionable." ) @@ -148,6 +201,23 @@ def process_capture( def build_prompt(all_summaries: list[str], flicker_suspects: list = None, flicker_count: int = 0, total_sessions: int = 0) -> str: + cfg = DEVICE_CONFIG + target = cfg["dsim_phytiming_target"] + config_section = ( + f"Device under test:\n" + f" DSI host: {cfg['dsi_host']}\n" + f" DSI bridge: {cfg['dsi_bridge']}\n" + f" Pixel clock: {cfg['pixel_clock_mhz']} MHz\n" + f" DSI lanes: {cfg['dsi_lanes']} data lanes\n" + f" Color format: {cfg['color_format']}\n" + f" HS bit rate: {cfg['hs_bit_rate_mbps']} Mbit/s per lane\n" + f" HS UI: {cfg['hs_ui_ns']:.3f} ns\n" + f" Byte clock: {cfg['byte_clock_mhz']} MHz ({cfg['byte_period_ns']:.3f} ns/byte)\n" + f" VDDIO: {cfg['vddio_v']} V\n" + f" Correct DSIM PHY timing register targets (byte-clock units):\n" + + "\n".join(f" {k}: {v}" for k, v in target.items()) + ) + body = "\n\n".join(all_summaries) flicker_section = "" @@ -177,11 +247,13 @@ def build_prompt(all_summaries: list[str], flicker_suspects: list = None, "Below are pre-processed summaries of MIPI D-PHY captures from a Digi ConnectCore " "8M Mini SOM (NXP i.MX 8M Mini) driving a SN65DSI83 MIPI-to-LVDS bridge. " "The system occasionally flickers at display pipeline load. " - "Each capture has up to four data sets per lane (CLK and DAT0):\n" + "Each capture has up to five data sets per lane (CLK and DAT0):\n" " sig — high-res HS differential (rise/fall times)\n" " proto — long-window HS differential (jitter, clock freq, amplitude)\n" " lp — single-ended LP state capture at pipeline startup (LP-11, SoT sequence, HS bursts)\n" " pwr — 1.8 V supply rail captured during LP→HS transition (droop, ripple, spec)\n" + " reg — DSIM PHY timing register snapshot from running device\n" + f"\n{config_section}\n" f"{flicker_section}\n" f"{body}\n\n" "Please:\n"