• v1.4.2 634df87fe0

    v1.4.2
    tests / fedora:latest (push) Successful in 1m15s
    tests / ubuntu-latest · py3.11 (push) Successful in 1m32s
    tests / ubuntu-latest · py3.13 (push) Successful in 1m1s
    tests / archlinux:latest (push) Successful in 53s
    tests / debian:12 (push) Successful in 51s
    tests / ubuntu:24.04 (push) Successful in 1m8s
    tests / NixOS (FHS wrapper from docs/NIXOS.md) (push) Skipped
    Build PCM package / build (push) Successful in 10s
    Stable

    janik released this 2026-08-31 11:42:51 +07:00 | 0 commits to main since this release

    Launching with nothing usable on the board no longer dead-ends: when
    neither mode can be derived (nothing selected, no marker rectangles,
    no config), the dialog now opens anyway - load-only - instead of
    failing with an error figure.

    • Both mode radios are unchecked and disabled with their reasons
      shown; OK and Save config... are disabled too. Load config... (and
      Cancel) stay live, so a saved config can bootstrap the run without
      first selecting pads or drawing marker rectangles.
    • A loaded file re-derives everything exactly as if it had been
      present at launch - mode, net, terminals, values.
    Downloads
  • v1.4.1 19327c23b1

    v1.4.1
    tests / ubuntu-latest · py3.11 (push) Successful in 54s
    tests / ubuntu-latest · py3.13 (push) Successful in 58s
    tests / archlinux:latest (push) Successful in 41s
    tests / debian:12 (push) Successful in 1m10s
    tests / fedora:latest (push) Successful in 42m6s
    tests / ubuntu:24.04 (push) Successful in 1m15s
    tests / NixOS (FHS wrapper from docs/NIXOS.md) (push) Skipped
    Build PCM package / build (push) Successful in 11s
    Stable

    janik released this 2026-08-27 17:20:35 +07:00 | 1 commits to main since this release

    Dialog completeness: every per-terminal config option is now editable
    in the terminal tables.

    • A Bonded checkbox per row (the config's "bonded" key, previously
      file-only and shown as a text suffix): checked, the terminal's
      contacts short into one internally joined lug - the total value
      stays prescribed, the per-contact split becomes a solve outcome.
      Same-name rectangle groups seed it checked (unchanged default);
      unchecking one falls back to the per-cell area share, and checking
      a single-contact terminal gives it an equipotential-lug contact
      instead of uniform injection. Save config... writes the flag back
      (removed when unchecked - false is the schema default).
    Downloads
  • v1.4.0 26b1cfaa45

    v1.4.0
    tests / archlinux:latest (push) Successful in 39s
    tests / debian:12 (push) Successful in 1m17s
    tests / fedora:latest (push) Successful in 1m8s
    tests / ubuntu:24.04 (push) Successful in 1m23s
    tests / ubuntu-latest · py3.11 (push) Successful in 1m25s
    tests / ubuntu-latest · py3.13 (push) Successful in 1m5s
    tests / NixOS (FHS wrapper from docs/NIXOS.md) (push) Skipped
    Build PCM package / build (push) Successful in 11s
    Stable

    janik released this 2026-08-27 17:01:24 +07:00 | 2 commits to main since this release

    PDN mode, a full configuration-file workflow and a reworked dialog -
    all opt-in: classic runs behave exactly as in 1.3.0 (the analytic test
    suite runs unchanged against the same solver paths).

    PDN mode - multiple supplies and loads on one net:

    • Instead of one driven terminal pair, a run can now model a power
      rail: any number of supply points, each a Thevenin source with a
      configurable output resistance (and optionally its own open-circuit
      voltage), plus any number of loads, each drawing its own prescribed
      current. The solve runs in absolute volts and reports the IR-drop
      map, each supply's delivered current (the Thevenin split - an
      outcome, not an input), and each load's mean and worst-case contact
      voltage, alongside the usual per-layer dissipation, |J| maps and
      per-via currents.
    • The summary carries a source-sink pair table: for every supply x
      load pair, the effective COPPER resistance between the two contacts
      (operating-point independent, source R_out excluded; one extra
      linear solve per terminal, deferred-corrected on the adaptive grid
      too) plus the copper loss attributed to the pair by proportional
      sharing - an attribution convention, but it sums exactly to the
      total copper dissipation, never crosses a copper gap, and pairs
      without a common copper path report "no path". The same table is
      also rendered as a figure (5_source_sink_pairs.png) alongside the
      field maps; terminals are keyed by their unique labels (no
      positional tags), and both outputs note each terminal's component
      hint and comment - the summary in the supplies/loads tables, the
      figure in a terminals legend underneath.
    • The consistency check generalizes: source power = copper loss +
      output-resistance loss + load power (Tellegen), verified on every
      run. Both the uniform-reference and the adaptive grid support PDN
      mode; geometry dumps embed the terminal set (schema v8) and re-solve
      offline via standalone.py with no extra flags. Older dumps load
      unchanged.

    The dialog editor - PDN runs need no JSON at all:

    • The dialog gained a Mode selector: Classic (unchanged - and simply
      called that; a "two-terminal" label would read like a 2-contact cap,
      but classic terminals can bundle many contact parts) or PDN. In PDN
      mode, rectangles on User.1 are supply terminals and rectangles on
      User.2 are load terminals - the same marker layers as classic, but
      each rectangle is its OWN terminal instead of being merged into one
      V+/V- contact. Two editable tables - one for supplies, one for
      loads, each titled with the marker layer its rectangles come from -
      assign each load its current draw and each supply its output
      resistance (plus an optional open-circuit voltage; empty = the
      V-nominal field). PDN is selectable whenever both layers carry at
      least one rectangle; otherwise the radio is disabled with the reason
      shown, and a classic-mode failure (nothing selected, no marker pair)
      no longer kills the launch when PDN rectangles exist - the dialog
      opens in the mode that works.
    • A text item placed inside a rectangle names the terminal; unnamed
      rectangles get automatic names (S1../L1.., stable reading order).
    • A read-only Component column identifies each row: the footprint
      whose pad intersects the contact area (e.g. "U5"), or "near U5"
      when nothing touches it. Purely spatial - it names where the
      terminal sits, it plays no electrical role.
    • Every terminal row picks its contacted copper in a Layer combo,
      like the classic contact scopes: "All selected layers" (a
      rectangle's natural bolted-lug scope) or one specific layer. The
      choice is saved as the terminal-level "contact" key.
    • Every row has an Active checkbox: unchecking it disregards the
      terminal (no solve, value cells may stay blank) WITHOUT deleting it
      • the row is saved as "active": false and can be re-enabled later.
        A free-text Comment column is saved with each terminal ("comment"
        key). Both are editable in config-backed setups too.
    • The tables show only the rectangles that actually sit on the
      selected net: switching the net swaps the visible set, the totals
      line counts the hidden rows, and hidden rows take no part in the
      run - not validated, not solved. Saving keeps them anyway: every
      row lands in the config file, off-net ones as "active": false with
      their values and comments intact, and config-backed runs apply the
      same per-net filter so archived terminals are skipped, never fatal.
    • The terminal tables are height-resizable: each sizes itself to its
      rows, a drag handle between the two redistributes space, and
      enlarging the dialog grows them. In PDN mode the dialog opens at
      ~60% of the screen height (capped at 85%/90% of the screen; the
      KiCad window itself is not reachable through the IPC API, so the
      screen is the reference). The whole form scrolls when it outgrows
      the screen (the error line and the buttons always stay visible at
      the bottom).
    • Numbers understand SI suffixes: 50m = 0.05, 4.7k = 4700, 2M = 2e6
      (case separates milli from mega). This works in every dialog number
      field (R_out, V_oc, I draw, V nominal, test current, cell size,
      thresholds), in the config file (any number may be a string:
      "r_out_ohm": "50m"), and in the CLI's --current / --cell-um /
      --v-nominal. The frequency field keeps its own grammar (142k, 1.5M -
      a lone m means MHz there, as before).

    Bonded terminals - a package's total current with a free per-pin split:

    • A terminal (config key "bonded": true; in the editor, simply give
      several rectangles the same name) shorts all its contacts into one
      lug, the way a multi-pin package joins its pins with internal metal:
      the TOTAL current stays prescribed, but which contact carries how
      much becomes a solve outcome instead of the default per-cell area
      share. Works for loads and supplies (a bonded supply is an
      equipotential lug with its whole output resistance in series), on
      both grids, and the reported per-part currents are the computed
      boundary fluxes. A bonded load may even span disconnected copper
      sheets - the bond is the connection.

    Configuration file - the run, fully specified next to the board:

    • A JSON config next to the board file can specify a complete run:
      every dialog field, the classic terminals by board reference
      (skipping the selection / marker-rectangle step), the select
      physics constants that previously required editing config.py
      (resistivity, copper thickness, via plating), the marker layer
      names - or the whole PDN terminal set. Precedence is simple:
      config.py defaults < config file < dialog edits; the file pre-fills
      the dialog, what the dialog shows is what runs.
    • Terminals are written by board reference: "U7" (all pads of a
      footprint on the net), "U7.3" (one pad), "rect:NAME" (a rectangle
      named by a text item placed inside it - searched on User.3, User.1
      and User.2, so names must be unique across the marker layers),
      explicit rectangles or nearest-via coordinates.
    • Configs can be kept side by side as "fill_res_config..json":
      the config named "default" loads automatically (plain
      "fill_res_config.json" is its legacy spelling, and a board-specific
      ".fill_res_config.json" wins over both), and the Load
      config... button in the dialog pulls in any other config for this
      run - the dialog re-opens seeded entirely from the picked file.
      Save config... asks for the target file name each time (pre-filled
      with the loaded config; ".json" appended when omitted), so writing
      back and branching a variant are both one click; a name outside the
      auto-load set prints a Load-config reminder.
    • Save config... works in both modes: classic saves write the run
      parameters and contact scopes, PDN saves write the whole terminal
      set - named rectangles as live "rect:NAME" references (they follow
      the rectangle wherever it moves), unnamed ones as frozen rect_mm
      coordinates, so label your rectangles if the layout is still
      moving. Full-line // comments and "_"-prefixed keys are allowed;
      invalid files stop the run with the offending key path instead of
      silently running defaults; unknown keys warn (typo guard).
    • A config never pins anything. Its mode is only the STARTING mode
      (a classic-mode file may carry a terminals section and vice versa),
      the net stays switchable, values / layer scopes / active flags /
      comments are editable per run and written back on save (part
      references are preserved verbatim; part-level contacts keep winning
      over the terminal scope), and a classic save over a PDN config
      keeps the whole terminals section - it just flips the starting
      mode. A broken terminal reference disables PDN mode with the reason
      shown instead of killing the launch.
    • A config-backed set is open-ended: any marker rectangle the file
      does not reference yet appears as a NEW terminal row (a note under
      the tables counts them) and Save config... appends it to the file.
      A rectangle named after an existing rect:NAME terminal instead
      joins that terminal as another contact part at resolve time. A
      label colliding with an unrelated terminal name is skipped with a
      note; colliding auto names are renumbered.
    • standalone.py gained --config (run-parameter defaults under the
      explicit flags) and --v-nominal.
    Downloads
  • v1.3.0 24fed64f83

    v1.3.0
    Build PCM package / build (push) Successful in 7s
    Stable

    gitea-actions released this 2026-07-23 13:37:17 +07:00 | 15 commits to main since this release

    The plugin now works on macOS. Results are unchanged from 1.2.2 for
    the same board and settings - nothing in the numerics was touched;
    this release is platform fixes and per-OS documentation.

    macOS (field-tested on KiCad 10):

    • Fixed a crash on launch. KiCad's macOS builds bundle Python 3.9,
      and one module's type annotations were evaluated at import there
      ("unsupported operand type(s) for |: 'type' and 'NoneType'"). The
      plugin now runs on 3.9, and a test walks every shipped module so
      the incompatibility cannot silently return.
    • Fixed every figure - the error figure included - refusing to render
      with "Cannot load backend 'TkAgg' ... as 'qt' is currently
      running". macOS' bundled Python ships tkinter, so matplotlib
      preferred Tk while the selection dialog had already made the
      process a Qt one. Qt (PySide6, a hard dependency) is now always
      the first choice on every platform.
    • A board in a read-only location - such as the demo projects opened
      straight from the mounted installer image - no longer kills the run
      when the results directory cannot be created next to the board.
      Results fall back to a temp directory and the path is printed to
      the Messages panel.
    • The test suite additionally runs against the stack a Mac plugin
      environment actually resolves (Python 3.9, numpy 2.0, scipy 1.13,
      matplotlib 3.9, PySide6 6.10) - 140 tests on both stacks.

    Linux:

    • On ARM64 (aarch64) the plugin environment could never build: pyamg
      publishes no wheels for that platform, KiCad installs wheels only,
      and one unresolvable requirement fails the whole environment.
      pyamg is now skipped there and the solver falls back to Jacobi-CG -
      same results, noticeably slower on large grids. Linux as a whole
      remains untested; reports welcome.

    Documentation:

    • Setup now gives dedicated instructions per operating system: which
      interpreter path to check, how to deploy, and where the plugin's
      Python environment lives on Windows, macOS and Linux (for the
      delete-and-restart recovery). A platform-notes section records what
      is actually tested on each OS and what to expect there.
    Downloads
  • v1.2.2 d05d523995

    v1.2.2
    Build PCM package / build (push) Successful in 7s
    Stable

    grabowski released this 2026-07-22 16:56:37 +07:00 | 20 commits to main since this release

    Results are unchanged from 1.2.1 for the same board and settings. This
    release is about what the plugin tells you while it works, and about no
    longer overstating what a frequency result means.

    Progress while solving:

    • The dialog used to close on OK and leave nothing on screen until the
      figures appeared - minutes, on a real board, with no sign the plugin
      was doing anything. A small window now stays up for that whole
      stretch: the stage running, elapsed seconds, and Cancel.
    • It covers the figure work as well as the solve. Laying out labels and
      writing the four PNGs at full resolution is seconds on a modest board
      and 10-15 on a large one, and that used to be silent too.
    • Cancel stops the solve and returns you to the board with no error
      figure - the run simply reports that it was cancelled.

    Frequency results are described honestly:

    • Nothing advertises "AC resistance" any more. At f > 0 the plugin
      applies the exact 1D foil and barrel skin-effect correction and
      nothing else: proximity redistribution and inductance are not
      modelled, so the number is a lower bound on the resistive rise, not
      an AC impedance simulation. The README headline, the PCM and plugin
      descriptions, the dialog note, the CLI help and the summary line all
      say so now.
    • The computation itself has not changed - only its description. A
      frequency result from 1.2.1 is the same number, previously labelled
      in a way that invited it to be read as an impedance.

    Also in this release:

    • The offline runner takes --progress, so the same busy window can be
      used outside KiCad.
    • The frequency field keeps its specific reason for rejecting an input
      ("1,500" is a thousands separator, "-5" is negative) instead of a
      generic "cannot parse".

    The in-KiCad |J| overlay push remains experimental and opt-in, off by
    default. It writes reference images to User.9-User.12 and replaces what
    is on those layers.

    Downloads
  • v1.2.1 d7c3089031

    v1.2.1
    Build PCM package / build (push) Successful in 9s
    Stable

    grabowski released this 2026-07-22 16:27:46 +07:00 | 24 commits to main since this release

    Bug-fix release. Results are unchanged from 1.2.0 for a board that
    solves cleanly; the fixes are in the in-KiCad overlay push, pad copper
    selection and error reporting.

    Note for anyone coming from 1.1.0 or earlier: 1.2.0 changed the physics
    model (exact SMD and THT pad copper, populated THT holes conducting as
    their solder plug and lead, slotted holes as true stadiums) and fixed an
    adaptive barrel-refinement bug that could make via-field results read up
    to ~13% low. Numbers for an unchanged board differ from 1.1.0 - re-run
    any board you track across versions.

    Fixed:

    • Overlay push: a locked reference image silently survived removal and a
      new one was stacked on top of it. KiCad reports the failure per item
      while the overall request still reads OK; it is now checked, and the
      layer is reported and skipped instead.
    • Overlay push: a run covering fewer layers than the previous one left
      the earlier solve's heatmap on the unused slots, where it read as
      current. Those slots are now cleared.
    • Overlay push: the whole push is one commit, so a single undo reverts
      it rather than just the last layer.
    • Through-hole pad copper was always read from F.Cu even when the joint
      protrudes on B.Cu, mis-sizing the modelled solder coat for pads sized
      differently per copper layer. The solder side is now probed first.
    • A failure before the output directory existed - a broken plugin
      Python environment, typically - reported nothing at all on screen.
      The error figure now falls back to the temp directory.
    • Pads sitting on no single copper layer are noted rather than silently
      skipped, and the frequency field keeps its specific rejection reason
      ("1,500" is a thousands separator, "-5" is negative) as the other
      numeric fields already did.

    The KiCad overlay push remains experimental and opt-in (off by default).
    It writes reference images to User.9-User.12 and replaces what is on
    those layers.

    Downloads
  • v1.2.0 d48a369d3a

    v1.2.0
    Build PCM package / build (push) Successful in 9s
    Stable

    grabowski released this 2026-07-22 15:52:46 +07:00 | 31 commits to main since this release

    Downloads
  • v1.1.0 1eab58f3d1

    v1.1.0
    Build PCM package / build (push) Successful in 12s
    Stable

    gitea-actions released this 2026-07-17 12:32:03 +07:00 | 43 commits to main since this release

    Downloads
  • v1.0.1 139c120e0a

    v1.0.1
    Build PCM package / build (push) Successful in 7s
    Stable

    grabowski released this 2026-07-15 20:01:53 +07:00 | 53 commits to main since this release

    Downloads