Add
This commit is contained in:
@@ -42,6 +42,39 @@ REGISTER_COMMANDS = [
|
||||
SN65_I2C_BUS = 4 # i2c-4 on this board
|
||||
SN65_I2C_ADDR = 0x2C # SN65DSI83 fixed 7-bit I2C address
|
||||
|
||||
# Settling-period poll — started in a background thread immediately after each
|
||||
# kiosk kill+restart. Samples csr_0a and csr_e5 every SETTLING_INTERVAL_S for
|
||||
# SETTLING_DURATION_S seconds. Results stored in _settling_log and returned by
|
||||
# GET /sn65_settling so the host can correlate DSI errors with LP captures.
|
||||
SETTLING_DURATION_S = 1.5 # seconds to poll after restart
|
||||
SETTLING_INTERVAL_S = 0.010 # 10 ms between I2C reads
|
||||
|
||||
_settling_log: list = []
|
||||
_settling_lock: threading.Lock = threading.Lock()
|
||||
|
||||
|
||||
def _run_settling_poll() -> None:
|
||||
"""Poll SN65DSI83 csr_0a + csr_e5 at 10 ms intervals for 1.5 s after restart."""
|
||||
t_start = time.time()
|
||||
t_end = t_start + SETTLING_DURATION_S
|
||||
readings: list = []
|
||||
while time.time() < t_end:
|
||||
t_ms = round((time.time() - t_start) * 1000, 1)
|
||||
val_0a, _ = _i2c_read_byte(SN65_I2C_BUS, SN65_I2C_ADDR, 0x0A)
|
||||
val_e5, _ = _i2c_read_byte(SN65_I2C_BUS, SN65_I2C_ADDR, 0xE5)
|
||||
readings.append({
|
||||
"t_ms": t_ms,
|
||||
"csr_0a": f"0x{val_0a:02x}" if val_0a is not None else None,
|
||||
"csr_e5": f"0x{val_e5:02x}" if val_e5 is not None else None,
|
||||
"pll_lock": bool(val_0a & 0x80) if val_0a is not None else None,
|
||||
"clk_det": bool(val_0a & 0x08) if val_0a is not None else None,
|
||||
"any_error": bool(val_e5) if val_e5 is not None else None,
|
||||
})
|
||||
time.sleep(SETTLING_INTERVAL_S)
|
||||
with _settling_lock:
|
||||
_settling_log.clear()
|
||||
_settling_log.extend(readings)
|
||||
|
||||
# Known Samsung DSIM register names (base 0x32E10000, i.MX 8M Mini)
|
||||
_DSIM_NAMES = {
|
||||
0x32e10004: "DSIM_STATUS",
|
||||
@@ -107,6 +140,9 @@ def control_display():
|
||||
_video_proc.kill()
|
||||
_video_proc.wait()
|
||||
time.sleep(0.15) # let DSI reach LP-11
|
||||
# Start settling poll immediately — captures csr_e5 error flags
|
||||
# during DSI startup so the host can determine root cause of flicker.
|
||||
threading.Thread(target=_run_settling_poll, daemon=True).start()
|
||||
try:
|
||||
log = open("/tmp/kiosk.log", "w")
|
||||
_video_proc = subprocess.Popen(
|
||||
@@ -182,6 +218,21 @@ def _i2c_read_byte(bus: int, addr: int, reg: int) -> tuple[int | None, str]:
|
||||
return None, str(e)
|
||||
|
||||
|
||||
@app.route("/sn65_settling", methods=["GET"])
|
||||
def get_sn65_settling():
|
||||
"""Return the most recent post-restart settling poll (csr_0a + csr_e5 over 1.5 s)."""
|
||||
with _settling_lock:
|
||||
readings = list(_settling_log)
|
||||
error_readings = [r for r in readings if r.get("any_error")]
|
||||
return jsonify({
|
||||
"n_readings": len(readings),
|
||||
"n_error": len(error_readings),
|
||||
"duration_s": SETTLING_DURATION_S,
|
||||
"interval_ms": int(SETTLING_INTERVAL_S * 1000),
|
||||
"readings": readings,
|
||||
}), 200
|
||||
|
||||
|
||||
@app.route("/sn65_registers", methods=["GET"])
|
||||
def get_sn65_registers():
|
||||
"""Read SN65DSI83 CSR 0x0A (PLL/CLK status) and 0xE5 (error flags) via I2C."""
|
||||
|
||||
Reference in New Issue
Block a user