Rebrand Pinscope to Periscope across product and codebase.

Rename the core package to periscopex, update UI/docs/Docker/deploy defaults to periscope.michelebigi.it, and keep legacy version/storage key aliases so existing projects keep working.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-13 20:02:04 +02:00
co-authored by Cursor
parent 556306bf4d
commit 8d2b85600f
177 changed files with 869 additions and 766 deletions
+109
View File
@@ -0,0 +1,109 @@
"""Power-good → enable sequencing when the IC specs declare a sequence.
No RC time constants are invented. Missing power_sequence means skip.
"""
from __future__ import annotations
import re
from backend.periscopex.models import (
ComponentConstraints,
ComponentType,
DesignGraph,
Finding,
)
from backend.periscopex.thermal_check import (
_VIN_PIN,
_VOUT_PIN,
_is_ldo,
_pin_net_by_role,
_specs_values,
)
from backend.periscopex.validate import _match_constraints
_PG_RE = re.compile(r"(?:^|[_/])(PG|PGOOD|PWRGD|POWER_GOOD|POK)(?:$|[_/\d])", re.I)
_EN_RE = re.compile(
r"(?:^|[_/])(EN|ENA|ENABLE|n?SHDN|nEN|EN_N)(?:$|[_/\d])",
re.I,
)
def _has_sequence(comp) -> bool:
values = _specs_values(comp)
raw = values.get("power_sequence")
if raw is None or raw == "" or raw is False:
return False
if isinstance(raw, (int, float)) and raw == 0:
return False
return True
def check_power_sequencing(
graph: DesignGraph,
constraints_map: dict[str, ComponentConstraints] | None = None,
) -> list[Finding]:
cmap = constraints_map or {}
regs: list[tuple] = []
for ref, comp in sorted(graph.components.items()):
if comp.component_type != ComponentType.IC:
continue
cons = _match_constraints(comp.mpn or comp.value, cmap)
vin = _pin_net_by_role(graph, comp, cons, _VIN_PIN)
vout = _pin_net_by_role(graph, comp, cons, _VOUT_PIN)
if not (vin and vout) and not _is_ldo(comp, cons):
continue
pg = _pin_net_by_role(graph, comp, cons, _PG_RE, exclude_re=None)
en = _pin_net_by_role(graph, comp, cons, _EN_RE, exclude_re=None)
regs.append((ref, comp, cons, vin, vout, pg, en))
findings: list[Finding] = []
for dref, dcomp, dcons, dvin, _dvout, _dpg, den in regs:
if not _has_sequence(dcomp):
continue
if not den or not dvin:
continue
upstream = [
row for row in regs
if row[0] != dref and row[4] and row[4] == dvin
]
if not upstream:
continue
uref, ucomp, _ucons, _uvin, _uvout, upg, _uen = upstream[0]
if not upg:
findings.append(Finding(
designator=dref,
mpn=dcomp.mpn or "",
aspect="sequencing",
source="sequencing_check",
status="WARNING",
finding=(
f"{dref} specs declare power_sequence but upstream {uref} "
f"has no PG pin feeding {dref} EN '{den}'."
),
why="Sequence was listed in IC specs; delay milliseconds were not estimated.",
recommendation="Tie the upstream power-good to this enable, or remove the sequence spec if unused.",
reference="power_sequence",
net=den,
pins=[dref, uref],
rule_id="PE-SEQ-001",
))
continue
if upg != den:
findings.append(Finding(
designator=dref,
mpn=dcomp.mpn or "",
aspect="sequencing",
source="sequencing_check",
status="WARNING",
finding=(
f"{uref} PG '{upg}' does not connect to {dref} EN '{den}'."
),
why="Declared power_sequence expects PG to enable the next rail.",
recommendation="Net the upstream PG to the downstream EN.",
reference="power_sequence",
net=den,
pins=[f"{uref}", f"{dref}"],
rule_id="PE-SEQ-001",
))
return findings