From a330a1fad3c1ccdd926297747c03fe95bcaa6587 Mon Sep 17 00:00:00 2001 From: Nathan Perry Date: Wed, 14 Aug 2024 01:34:16 -0400 Subject: nix: migrate functionality to clef --- clef/nix/board.nix | 37 ++++++++++++++++++++++ clef/nix/default.nix | 58 ++++++++++++++++++++++++++++++++++ clef/nix/fabrication.nix | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ clef/nix/model.nix | 52 ++++++++++++++++++++++++++++++ clef/nix/panel.nix | 46 +++++++++++++++++++++++++++ clef/nix/schematic.nix | 51 ++++++++++++++++++++++++++++++ clef/nix/svg.nix | 82 ++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 408 insertions(+) create mode 100644 clef/nix/board.nix create mode 100644 clef/nix/default.nix create mode 100644 clef/nix/fabrication.nix create mode 100644 clef/nix/model.nix create mode 100644 clef/nix/panel.nix create mode 100644 clef/nix/schematic.nix create mode 100644 clef/nix/svg.nix (limited to 'clef/nix') diff --git a/clef/nix/board.nix b/clef/nix/board.nix new file mode 100644 index 0000000..d67417b --- /dev/null +++ b/clef/nix/board.nix @@ -0,0 +1,37 @@ +{ + runCommand, + + svg, + model, + fabrication, + schematic, + panel, + panelSrc, + + name, + outPath, +}: let + pkg = runCommand name {} '' + set -e + + mkdir -p "$out/${outPath}" + cd "$out/${outPath}" + + echo "populating $(pwd)" + + cp --reflink=auto -vr "${schematic}/share/npry/clef/schematic" ./ + cp --reflink=auto -vr "${svg}/share/npry/clef/svg" ./ + cp --reflink=auto -vr "${fabrication}/share/npry/clef/fab" ./ + cp --reflink=auto -vr "${model}/share/npry/clef/model" ./ + + ${if panelSrc != null then '' + cp --reflink=auto -vr "${panelSrc}/share/npry/clef/panel" ./ + '' else ""} + ''; + +in pkg.overrideAttrs (prevAttrs: { + passthru = (prevAttrs.passthru or {}) // { + inherit schematic fabrication svg model panel panelSrc; + fab = fabrication; + }; +}) diff --git a/clef/nix/default.nix b/clef/nix/default.nix new file mode 100644 index 0000000..4438bbe --- /dev/null +++ b/clef/nix/default.nix @@ -0,0 +1,58 @@ +{ + pkgs, + + src, + main_pcb, + main_sch, + + name, + outPath ? "share/npry/clef", + layers ? 2, + + # set to a list of arguments to be passed to `kikit panelize -p` + panelizeConfigs ? null, +}: let + pcb_path = main_pcb; + sch_path = main_sch; + + pcb_args = { + inherit pcb_path src; + }; + + panelSrc = if panelizeConfigs != null then pkgs.callPackage ./panel.nix (pcb_args // { inherit panelizeConfigs; }) else null; + + panel = if panelizeConfigs != null then + pkgs.callPackage ./. { + src = "${panelSrc}/share/npry/clef/panel"; + main_pcb = "panel.kicad_pcb"; + + name = "${name}.sub.panel"; + outPath = "${outPath}/panel"; + + inherit main_sch layers; + } + else null; + + svg = pkgs.callPackage ./svg.nix (pcb_args // { nLayer = layers; }); + model = pkgs.callPackage ./model.nix pcb_args; + + fabrication = pkgs.callPackage ./fabrication.nix (pcb_args // { + inherit sch_path; + }); + + schematic = pkgs.callPackage ./schematic.nix { + inherit sch_path src; + }; + +in pkgs.callPackage ./board.nix { + inherit + svg + model + fabrication + schematic + name + outPath + panel + panelSrc + ; +} diff --git a/clef/nix/fabrication.nix b/clef/nix/fabrication.nix new file mode 100644 index 0000000..18bc6f6 --- /dev/null +++ b/clef/nix/fabrication.nix @@ -0,0 +1,82 @@ +{ + kicad, + kikit, + zip, + + runCommand, + + nix-filter, + lib, + + src, + pcb_path, + sch_path, + + boardName ? (lib.removeSuffix ".kicad_pcb" (builtins.baseNameOf pcb_path)), + + fabHouse ? "jlcpcb", + withAssembly ? true, +}: let + sharePath = "share/npry/clef/fab"; + + fabSrc = nix-filter { + root = src; + + include = [ + (nix-filter.matchExt "kicad_sch") + (nix-filter.matchExt "kicad_wks") + (nix-filter.matchExt "kicad_pcb") + (nix-filter.matchExt "kicad_pro") + + (_args: path: type: type == "directory") + ]; + }; + +in runCommand "${boardName}.fab" { + nativeBuildInputs = [ + kicad + kikit + zip + ]; + + src = fabSrc; + + allowedRequisites = []; +} '' + set -e + + export HOME=$(mktemp -d) + + echo "board: '${boardName}'" >&2 + + mkdir -p "$out/${sharePath}" + cd "$src" + + kikit fab ${fabHouse} \ + ${if withAssembly then "--assembly" else ""} \ + --no-drc \ + --schematic "${sch_path}" \ + --field 'LCSC Part #,LCSC Part No' \ + --missingError \ + "${pcb_path}" \ + "$out/${sharePath}" + + cd "$out/${sharePath}" + rm -vf "gerbers.zip" + + pushd gerber + + # normalize + for f in ${boardName}-*; do + mv -nv "$f" "''${f#${boardName}-}" + done + + for f in ${boardName}.*; do + mv -nv "$f" "board''${f#${boardName}}" + done + + popd + + zip -vj "gerbers.zip" gerber/* + rm -vrf gerber +'' diff --git a/clef/nix/model.nix b/clef/nix/model.nix new file mode 100644 index 0000000..04bf1b1 --- /dev/null +++ b/clef/nix/model.nix @@ -0,0 +1,52 @@ +{ + kicad, + runCommand, + + nix-filter, + lib, + + withTracks ? false, + withZones ? false, + + src, + pcb_path, + + boardName ? (lib.removeSuffix ".kicad_pcb" (builtins.baseNameOf pcb_path)), +}: let + zonesArg = if withZones then "--include-zones" else ""; + tracksArg = if withTracks then "--include-tracks" else ""; + sharePath = "share/npry/clef/model"; + +in runCommand "${boardName}.model" { + nativeBuildInputs = [ + kicad + ]; + + src = nix-filter { + root = src; + + include = [ + (nix-filter.matchExt "kicad_pcb") + + (nix-filter.matchExt "stp") + (nix-filter.matchExt "step") + (nix-filter.matchExt "wrl") + ]; + }; + + allowedRequisites = []; + + KICAD8_3DMODEL_DIR = "${kicad.libraries.packages3d}/share/kicad/3dmodels"; +} '' + set -e + + export HOME=$(mktemp -d) + + echo "board: '${boardName}'" >&2 + + mkdir -p $out/${sharePath} + cd "$out/${sharePath}" + + kicad-cli pcb export step --subst-models --no-dnp ${tracksArg} ${zonesArg} "$src/${pcb_path}" -o "${boardName}.step" + kicad-cli pcb export glb --subst-models --no-dnp ${tracksArg} ${zonesArg} "$src/${pcb_path}" -o "${boardName}.glb" +'' diff --git a/clef/nix/panel.nix b/clef/nix/panel.nix new file mode 100644 index 0000000..1d88d46 --- /dev/null +++ b/clef/nix/panel.nix @@ -0,0 +1,46 @@ +{ + kikit, + runCommand, + + nix-filter, + lib, + + panelizeConfigs, + src, + pcb_path, + + boardName ? (lib.removeSuffix ".kicad_pcb" (builtins.baseNameOf pcb_path)), +}: let + sharePath = "share/npry/clef/panel"; + + panelSrc = nix-filter { + root = src; + + include = [ + (nix-filter.matchExt "kicad_pcb") + ]; + }; + +in runCommand "${boardName}.panel" { + nativeBuildInputs = [ + kikit + ]; + + allowedRequisites = []; +} '' + set -e + export HOME=$(mktemp -d) + + mkdir -p "$out/${sharePath}" + + # do the panelize here rather than in $out because it creates junk we don't want + cd $HOME + + kikit panelize \ + ${lib.concatMapStrings (conf: "-p ${conf} \\\n") panelizeConfigs} \ + "${panelSrc}/${pcb_path}" \ + "panel.kicad_pcb" + + cp -v panel.kicad_{pcb,pro} "$out/${sharePath}" + cp -v "${src}/"*.kicad_{sch,pro} "$out/${sharePath}" +'' diff --git a/clef/nix/schematic.nix b/clef/nix/schematic.nix new file mode 100644 index 0000000..acc136f --- /dev/null +++ b/clef/nix/schematic.nix @@ -0,0 +1,51 @@ +{ + kicad, + runCommand, + + nix-filter, + lib, + + src, + sch_path, + + schName ? (lib.removeSuffix ".kicad_sch" (builtins.baseNameOf sch_path)), +}: let + sharePath = "share/npry/clef/schematic"; + +in runCommand "${schName}.schematic" { + nativeBuildInputs = [ + kicad + ]; + + src = nix-filter { + root = src; + + include = [ + (nix-filter.matchExt "kicad_sch") + (nix-filter.matchExt "kicad_pro") + ]; + }; +} '' + set -e + export HOME=$(mktemp -d) + + echo "schematic: '${schName}'" >&2 + + mkdir -p "$out/${sharePath}/svg" + cd "$out/${sharePath}" + + kicad-cli sch export pdf -o schematic.pdf $src/${sch_path} + kicad-cli sch export svg -n -o svg $src/${sch_path} + + cd svg + + # normalize + for f in *.svg; do + if [ "$f" = "${schName}.svg" ]; then + mv -nv "$f" "root.svg" + continue + fi + + mv -nv "$f" "''${f#${schName}-}" + done +'' diff --git a/clef/nix/svg.nix b/clef/nix/svg.nix new file mode 100644 index 0000000..fc1a404 --- /dev/null +++ b/clef/nix/svg.nix @@ -0,0 +1,82 @@ +{ + runCommand, + kicad, + + nix-filter, + lib, + + pcb_path, + src, + + withSilk ? true, + withEdgeCuts ? true, + withMirrors ? true, + nLayer ? 2, + + boardName ? (lib.removeSuffix ".kicad_pcb" (builtins.baseNameOf pcb_path)), +}: let + sharePath = "share/npry/clef/svg"; + +in runCommand "${boardName}.svg" { + nativeBuildInputs = [ + kicad + ]; + + src = nix-filter { + root = src; + + include = [ + (nix-filter.matchExt "kicad_pcb") + ]; + }; + + nInnerLayer = if nLayer < 2 then 0 else nLayer - 2; + + allowedRequisites = []; +} '' + set -e + + export HOME=$(mktemp -d) + + echo "board: '${boardName}'" >&2 + + mkdir -p $out/${sharePath} + cd "$out/${sharePath}" + + mksvg() { + local infile=$1 + local layers=$2 + local outfile=$3 + + kicad-cli pcb export svg \ + "$infile" \ + -l "$layers" \ + -o "$outfile.svg" \ + --page-size-mode 2 \ + --exclude-drawing-sheet + + ${if withMirrors then '' + kicad-cli pcb export svg \ + "$infile" \ + -m \ + -l "$layers" \ + -o "$outfile.mirror.svg" \ + --page-size-mode 2 \ + --exclude-drawing-sheet + '' else ""} + } + + mksvg "$src/${pcb_path}" \ + "F.Cu,${if withSilk then "F.Silkscreen," else ""}${if withEdgeCuts then "Edge.Cuts," else ""}" \ + front + + mksvg "$src/${pcb_path}" \ + "B.Cu,${if withSilk then "B.Silkscreen," else ""}${if withEdgeCuts then "Edge.Cuts," else ""}" \ + back + + for i in $(seq 1 $nInnerLayer); do + mksvg "$src/${pcb_path}" \ + "In$i.Cu,${if withEdgeCuts then "Edge.Cuts," else ""}" \ + "in$i" + done +'' -- cgit v1.3.1