diff options
Diffstat (limited to 'hw/clef/nix')
| -rw-r--r-- | hw/clef/nix/board.nix | 39 | ||||
| -rw-r--r-- | hw/clef/nix/bom.nix | 48 | ||||
| -rw-r--r-- | hw/clef/nix/default.nix | 61 | ||||
| -rw-r--r-- | hw/clef/nix/fabrication.nix | 82 | ||||
| -rw-r--r-- | hw/clef/nix/model.nix | 58 | ||||
| -rw-r--r-- | hw/clef/nix/panel.nix | 46 | ||||
| -rw-r--r-- | hw/clef/nix/pkgs/default.nix | 5 | ||||
| -rw-r--r-- | hw/clef/nix/pkgs/interactive_html_bom.nix | 69 | ||||
| -rw-r--r-- | hw/clef/nix/schematic.nix | 54 | ||||
| -rw-r--r-- | hw/clef/nix/svg.nix | 92 |
10 files changed, 554 insertions, 0 deletions
diff --git a/hw/clef/nix/board.nix b/hw/clef/nix/board.nix new file mode 100644 index 0000000..5de46e0 --- /dev/null +++ b/hw/clef/nix/board.nix @@ -0,0 +1,39 @@ +{ + runCommand, + + svg, + model, + fabrication, + schematic, + panel, + panelSrc, + bom, + + 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" ./ + cp --reflink=auto -vr "${bom}/share/npry/clef/bom" ./ + + ${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 bom; + fab = fabrication; + }; +}) diff --git a/hw/clef/nix/bom.nix b/hw/clef/nix/bom.nix new file mode 100644 index 0000000..fbff8ff --- /dev/null +++ b/hw/clef/nix/bom.nix @@ -0,0 +1,48 @@ +{ + runCommand, + interactiveHtmlBom, + + nix-filter, + lib, + + pcb_path, + src, + + boardName ? (lib.removeSuffix ".kicad_pcb" (builtins.baseNameOf pcb_path)), + extraArgs ? [ + "--dark-mode" + "--include-tracks" + "--include-nets" + ], +}: let + sharePath = "share/npry/clef/bom"; + +in runCommand "${boardName}.bom" { + nativeBuildInputs = [ + interactiveHtmlBom + ]; + + INTERACTIVE_HTML_BOM_NO_DISPLAY = 1; + + src = nix-filter { + root = src; + + include = [ + (nix-filter.matchExt "kicad_pcb") + (nix-filter.matchExt "kicad_pro") + (nix-filter.matchExt "kicad_wks") + + (_args: path: type: type == "directory") + ]; + }; +} '' + mkdir -p "$out/${sharePath}" + + cd $src + + generate_interactive_bom \ + --dest-dir "$out/${sharePath}" \ + --no-browser \ + ${lib.concatMapStrings (arg: "${arg} \\\n") extraArgs} \ + "$src/${pcb_path}" +'' diff --git a/hw/clef/nix/default.nix b/hw/clef/nix/default.nix new file mode 100644 index 0000000..419c8fd --- /dev/null +++ b/hw/clef/nix/default.nix @@ -0,0 +1,61 @@ +{ + 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; + + bom = pkgs.callPackage ./bom.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 + bom + fabrication + schematic + name + outPath + panel + panelSrc + ; +} diff --git a/hw/clef/nix/fabrication.nix b/hw/clef/nix/fabrication.nix new file mode 100644 index 0000000..18bc6f6 --- /dev/null +++ b/hw/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/hw/clef/nix/model.nix b/hw/clef/nix/model.nix new file mode 100644 index 0000000..da8be82 --- /dev/null +++ b/hw/clef/nix/model.nix @@ -0,0 +1,58 @@ +{ + 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 "kicad_pro") + + (nix-filter.matchExt "stp") + (nix-filter.matchExt "STP") + (nix-filter.matchExt "step") + (nix-filter.matchExt "STEP") + (nix-filter.matchExt "wrl") + + (_args: path: type: type == "directory") + ]; + }; + + allowedRequisites = []; + + KICAD8_3DMODEL_DIR = "${kicad.libraries.packages3d}/share/kicad/3dmodels"; +} '' + set -e + + export HOME=$(mktemp -d) + + echo "board: '${boardName}'" >&2 + echo "KICAD8_3DMODEL_DIR: $KICAD8_3DMODEL_DIR" >&2 + + mkdir -p $out/${sharePath} + cd "$src" + + kicad-cli pcb export step --subst-models --no-dnp ${tracksArg} ${zonesArg} "${pcb_path}" -o "$out/${sharePath}/${boardName}.step" + kicad-cli pcb export glb --subst-models --no-dnp ${tracksArg} ${zonesArg} "${pcb_path}" -o "$out/${sharePath}/${boardName}.glb" +'' diff --git a/hw/clef/nix/panel.nix b/hw/clef/nix/panel.nix new file mode 100644 index 0000000..1d88d46 --- /dev/null +++ b/hw/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/hw/clef/nix/pkgs/default.nix b/hw/clef/nix/pkgs/default.nix new file mode 100644 index 0000000..a0a9f92 --- /dev/null +++ b/hw/clef/nix/pkgs/default.nix @@ -0,0 +1,5 @@ +{ + pkgs, +}: { + interactiveHtmlBom = pkgs.callPackage ./interactive_html_bom.nix {}; +} diff --git a/hw/clef/nix/pkgs/interactive_html_bom.nix b/hw/clef/nix/pkgs/interactive_html_bom.nix new file mode 100644 index 0000000..8adf7a7 --- /dev/null +++ b/hw/clef/nix/pkgs/interactive_html_bom.nix @@ -0,0 +1,69 @@ +{ + python3Packages, + writeText, + kicad-small, + + fetchFromGitHub, + + version ? "v2.9.0", + thisSrc ? fetchFromGitHub { + owner = "openscopeproject"; + repo = "interactivehtmlbom"; + rev = version; + hash = "sha256-jUHEI0dWMFPQlXei3+0m1ruHzpG1hcRnxptNOXzXDqQ="; + }, +}: + +let + src = thisSrc; + dummySetupPy = writeText "setup.py" '' + #!/usr/bin/env python3 + # vim: set ft=python : + + from setuptools import setup, find_packages + import sys + + packages = find_packages(include=['InteractiveHtmlBom', 'InteractiveHtmlBom.*']) + + setup( + name="InteractiveHtmlBom", + version='${version}', + packages=packages, + install_requires=['wxpython>=4.0', 'jsonschema>=4.1'], + entry_points={ + 'console_scripts': [ + 'generate_interactive_bom=InteractiveHtmlBom.generate_interactive_bom:main' + ] + }, + include_package_data=True + ) + ''; + + dummyManifest = writeText "MANIFEST.in" '' + recursive-include InteractiveHtmlBom/schema * + recursive-include InteractiveHtmlBom/web * + recursive-include InteractiveHtmlBom/dialog/bitmaps * + ''; + +in python3Packages.buildPythonApplication { + pname = "interactive_html_bom"; + + inherit + version + src + ; + + preBuild = '' + cp -nv ${dummySetupPy} setup.py + cp -nv ${dummyManifest} MANIFEST.in + rm pyproject.toml + ''; + + dependencies = with python3Packages; [ + wxpython + jsonschema + kicad-small.base + ]; + + doCheck = false; +} diff --git a/hw/clef/nix/schematic.nix b/hw/clef/nix/schematic.nix new file mode 100644 index 0000000..e931dd4 --- /dev/null +++ b/hw/clef/nix/schematic.nix @@ -0,0 +1,54 @@ +{ + 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") + (nix-filter.matchExt "kicad_wks") + + (_args: path: type: type == "directory") + ]; + }; +} '' + set -e + export HOME=$(mktemp -d) + + echo "schematic: '${schName}'" >&2 + + mkdir -p "$out/${sharePath}/svg" + cd "$src" + + kicad-cli sch export pdf -o "$out/${sharePath}/schematic.pdf" $src/${sch_path} + kicad-cli sch export svg -n -o "$out/${sharePath}/svg" $src/${sch_path} + + cd "$out/${sharePath}/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/hw/clef/nix/svg.nix b/hw/clef/nix/svg.nix new file mode 100644 index 0000000..c93ba87 --- /dev/null +++ b/hw/clef/nix/svg.nix @@ -0,0 +1,92 @@ +{ + runCommand, + kicad, + inkscape, + + 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 + inkscape + ]; + + 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 + + inkscape --actions 'select-all;fit-canvas-to-selection' \ + -o "$outfile.trim.svg" \ + "$outfile.svg" + + ${if withMirrors then '' + kicad-cli pcb export svg \ + "$infile" \ + -m \ + -l "$layers" \ + -o "$outfile.mirror.svg" \ + --page-size-mode 2 \ + --exclude-drawing-sheet + + inkscape --actions 'select-all;fit-canvas-to-selection' \ + -o "$outfile.mirror.trim.svg" \ + "$outfile.mirror.svg" + '' 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 +'' |
