From c932857e02c78a0395aca618354f8f4d8c59e6d0 Mon Sep 17 00:00:00 2001 From: Nathan Perry Date: Tue, 13 Aug 2024 04:23:03 -0400 Subject: nix: init --- .envrc | 5 ++ .gitignore | 1 + flake.lock | 209 ++++++++++++++++++++++++++++++++++++++++++++++++++++ flake.nix | 104 ++++++++++++++++++++++++++ nix/default.nix | 22 ++++++ nix/fabrication.nix | 65 ++++++++++++++++ nix/model.nix | 53 +++++++++++++ nix/panel.nix | 29 ++++++++ nix/schematics.nix | 0 nix/svg.nix | 64 ++++++++++++++++ 10 files changed, 552 insertions(+) create mode 100644 .envrc create mode 100644 flake.lock create mode 100644 flake.nix create mode 100644 nix/default.nix create mode 100644 nix/fabrication.nix create mode 100644 nix/model.nix create mode 100644 nix/panel.nix create mode 100644 nix/schematics.nix create mode 100644 nix/svg.nix diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..77862e2 --- /dev/null +++ b/.envrc @@ -0,0 +1,5 @@ +if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then + source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4=" +fi + +use flake diff --git a/.gitignore b/.gitignore index 0677ca5..2973796 100644 --- a/.gitignore +++ b/.gitignore @@ -31,4 +31,5 @@ __pycache__/ /production/ /panel/ panel.* +!nix/panel.nix /bom/ diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..c1dfe1e --- /dev/null +++ b/flake.lock @@ -0,0 +1,209 @@ +{ + "nodes": { + "cadquery-src": { + "flake": false, + "locked": { + "lastModified": 1705326221, + "narHash": "sha256-f/qnq5g4FOiit9WQ7zs0axCJBITcAtqF18txMV97Gb8=", + "owner": "CadQuery", + "repo": "cadquery", + "rev": "c44978d60cee2d61bdadf4cb4498286b7034b4c6", + "type": "github" + }, + "original": { + "owner": "CadQuery", + "ref": "2.4.0", + "repo": "cadquery", + "type": "github" + } + }, + "cq": { + "inputs": { + "cadquery-src": "cadquery-src", + "cq-editor-src": "cq-editor-src", + "flake-utils": [ + "flake-utils" + ], + "nixpkgs": [ + "nixpkgs" + ], + "ocp-src": "ocp-src", + "ocp-stubs-src": "ocp-stubs-src", + "pybind11-stubgen-src": "pybind11-stubgen-src", + "pywrap-src": "pywrap-src" + }, + "locked": { + "lastModified": 1723029696, + "narHash": "sha256-awv2fEsTkc749YcedWK1Y5P1xg5NfAosttlFnBsVVdg=", + "owner": "vinszent", + "repo": "cq-flake", + "rev": "27d9ac5b7f1fb5f271070ca0eed6a40c3fcfec17", + "type": "github" + }, + "original": { + "owner": "vinszent", + "ref": "main", + "repo": "cq-flake", + "type": "github" + } + }, + "cq-editor-src": { + "flake": false, + "locked": { + "lastModified": 1701895648, + "narHash": "sha256-mHXEaA6vphps6F0WemdB6fGRY4lzpcxLU7WuYEp8c20=", + "owner": "CadQuery", + "repo": "CQ-editor", + "rev": "4ef178af06d24a53fee87d576f8cada14c0111a3", + "type": "github" + }, + "original": { + "owner": "CadQuery", + "repo": "CQ-editor", + "rev": "4ef178af06d24a53fee87d576f8cada14c0111a3", + "type": "github" + } + }, + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "main", + "repo": "flake-utils", + "type": "github" + } + }, + "nix-filter": { + "locked": { + "lastModified": 1710156097, + "narHash": "sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj+rL8sRQsSM=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "3342559a24e85fc164b295c3444e8a139924675b", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "main", + "repo": "nix-filter", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1723282977, + "narHash": "sha256-oTK91aOlA/4IsjNAZGMEBz7Sq1zBS0Ltu4/nIQdYDOg=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "a781ff33ae258bbcfd4ed6e673860c3e923bf2cc", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "ocp-src": { + "flake": false, + "locked": { + "lastModified": 1701196143, + "narHash": "sha256-PMkMYEVBHt0i7ahgqF8jLhHHp7IRS7hd+JyydovNJ4A=", + "owner": "cadquery", + "repo": "ocp", + "rev": "4b98a5dc79fa900f7429975708f6a8c2e41cecd1", + "type": "github" + }, + "original": { + "owner": "cadquery", + "repo": "ocp", + "rev": "4b98a5dc79fa900f7429975708f6a8c2e41cecd1", + "type": "github" + } + }, + "ocp-stubs-src": { + "flake": false, + "locked": { + "lastModified": 1672527176, + "narHash": "sha256-m9Rg36GYlYfwEfF0PQJWEXf8TyM5HmjeuhJCODiurvY=", + "owner": "cadquery", + "repo": "ocp-stubs", + "rev": "e838ff400d5ee2f4a0579d2a713b19311855288f", + "type": "github" + }, + "original": { + "owner": "cadquery", + "repo": "ocp-stubs", + "type": "github" + } + }, + "pybind11-stubgen-src": { + "flake": false, + "locked": { + "lastModified": 1700678104, + "narHash": "sha256-76u1GcHPPh8oYQeQZDJ4K/so0U7F6rznZ1xa6syqI9s=", + "owner": "CadQuery", + "repo": "pybind11-stubgen", + "rev": "6dc681d838d3ec9a8a9aa4260c8392d3fb700ff0", + "type": "github" + }, + "original": { + "owner": "CadQuery", + "repo": "pybind11-stubgen", + "type": "github" + } + }, + "pywrap-src": { + "flake": false, + "locked": { + "lastModified": 1676015766, + "narHash": "sha256-QhAvJHV5tFq9bjKOzEpcudZNnmUmNVrJ+BLCZJhO31g=", + "owner": "CadQuery", + "repo": "pywrap", + "rev": "f3bcde70fd66a2d884fa60a7a9d9f6aa7c3b6e16", + "type": "github" + }, + "original": { + "owner": "CadQuery", + "repo": "pywrap", + "type": "github" + } + }, + "root": { + "inputs": { + "cq": "cq", + "flake-utils": "flake-utils", + "nix-filter": "nix-filter", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..2059ac7 --- /dev/null +++ b/flake.nix @@ -0,0 +1,104 @@ +# vim: ft=nix : +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05"; + flake-utils.url = "github:numtide/flake-utils/main"; + nix-filter.url = "github:numtide/nix-filter/main"; + + cq = { + url = "github:vinszent/cq-flake/main"; + inputs.nixpkgs.follows = "nixpkgs"; + inputs.flake-utils.follows = "flake-utils"; + }; + }; + + description = "tiny kite-borne sensor node"; + + outputs = { self, nixpkgs, flake-utils, ... } @ inputs: let + kicadOverlay = final: prev: { + opencascade-occt_7_6 = prev.opencascade-occt_7_6.overrideAttrs (finalAttrs: prevAttrs: { + buildInputs = (prevAttrs.buildInputs or []) ++ [ + prev.rapidjson + ]; + + cmakeFlags = (prevAttrs.cmakeFlags or []) ++ [ + "-DUSE_RAPIDJSON=1" + ]; + }); + + kicad = prev.kicad.override { + with3d = true; + withI18n = false; + + addons = with prev.kicadAddons; [ + kikit + kikit-library + ]; + }; + + kikit = let + version = "1.6.0"; + + in prev.kikit.overridePythonAttrs { + inherit version; + + src = final.fetchFromGitHub { + owner = "yaqwsx"; + repo = "KiKit"; + rev = "refs/tags/v${version}"; + hash = "sha256-r8LQcy3I6hmcrU/6HfPAYJd+cEZdhad6DUldC9HvXZU="; + }; + + doCheck = false; + }; + }; + + mkPkgs = system: import nixpkgs { + inherit system; + + overlays = [ + kicadOverlay + (final: prev: { nix-filter = inputs.nix-filter.lib; }) + + (final: prev: { + inherit (inputs.cq.packages.${system}) cadquery; + }) + ]; + }; + + mkPackages = pkgs: pkgs.callPackages ./nix {}; + + in (flake-utils.lib.eachDefaultSystem (system: + let + pkgs = mkPkgs system; + packages = mkPackages pkgs; + + full_package = (pkgs.emptyFile).overrideAttrs ({ + passthru = packages; + }); + + in { + packages = { + default = full_package; + ocularium = full_package; + }; + + devShells.default = pkgs.mkShell { + name = "devshell"; + version = self.rev or "dirty"; + + packages = with pkgs; [ + kicad + kikit + ]; + }; + + legacyPackages = pkgs // self.packages; + }) + ) // { + overlays = { + default = final: prev: self.packages.${prev.system}; + kicad = kicadOverlay; + }; + }; +} diff --git a/nix/default.nix b/nix/default.nix new file mode 100644 index 0000000..2c5ac7a --- /dev/null +++ b/nix/default.nix @@ -0,0 +1,22 @@ +{ + pkgs, +}: let + panel = pkgs.callPackage ./panel.nix {}; + svgs = pkgs.callPackage ./svg.nix { inherit panel; }; + model = pkgs.callPackage ./model.nix { inherit panel; }; + fabrication = pkgs.callPackage ./fabrication.nix { inherit panel; }; + + full = pkgs.symlinkJoin { + name = "ocularium"; + paths = [ + panel + svgs + model + fabrication + ]; + }; + +in { + inherit panel svgs model fabrication full; + fab = fabrication; +} diff --git a/nix/fabrication.nix b/nix/fabrication.nix new file mode 100644 index 0000000..82a5d3f --- /dev/null +++ b/nix/fabrication.nix @@ -0,0 +1,65 @@ +{ + kicad, + kikit, + zip, + + runCommand, + nix-filter, + + panel, +}: let + schSrc = nix-filter { + root = ./..; + + include = [ + (nix-filter.matchExt "kicad_sch") + ]; + }; + + pcbSrc = nix-filter { + root = ./..; + + include = [ + (nix-filter.matchExt "kicad_pcb") + (nix-filter.matchExt "kicad_pro") + ]; + }; + +in runCommand "ocularium.fab" { + nativeBuildInputs = [ + kicad + kikit + zip + ]; + + src = panel; + + allowedRequisites = []; +} '' + set -e + + mkdir -p $out/share/npry/ocularium/fab + mkdir -p $out/share/npry/ocularium/panel/fab + + export HOME=$(mktemp -d) + + cd $out/share/npry/ocularium/fab + + kikit fab jlcpcb --assembly \ + --no-drc \ + --schematic ${schSrc}/okm.kicad_sch \ + --field 'LCSC Part #,LCSC Part No' \ + --missingError \ + ${pcbSrc}/okm.kicad_pcb . + rm -rf gerber + + cd ../panel + + kikit fab jlcpcb --assembly \ + --no-drc \ + --schematic ${schSrc}/okm.kicad_sch \ + --field 'LCSC Part #,LCSC Part No' \ + --missingError \ + $src/share/npry/ocularium/panel.kicad_pcb . + rm -rf gerber +'' diff --git a/nix/model.nix b/nix/model.nix new file mode 100644 index 0000000..daa86ca --- /dev/null +++ b/nix/model.nix @@ -0,0 +1,53 @@ +{ + kicad, + runCommand, + + nix-filter, + + panel, + + withTracks ? false, + withZones ? false, +}: let + zonesArg = if withZones then "--include-zones" else ""; + tracksArg = if withTracks then "--include-tracks" else ""; + +in runCommand "ocularium.model" { + nativeBuildInputs = [ + kicad + ]; + + src = nix-filter { + root = ./..; + + exclude = [ + "nix" + ".gitignore" + "flake.nix" + "flake.lock" + ".envrc" + "kikit" + ]; + }; + + allowedRequisites = []; + + KICAD8_3DMODEL_DIR = "${kicad.libraries.packages3d}/share/kicad/3dmodels"; +} '' + set -e + + mkdir -p $out/share/npry/ocularium/model + mkdir -p $out/share/npry/ocularium/panel/model + + export HOME=$(mktemp -d) + + cd $out/share/npry/ocularium/model + + kicad-cli pcb export step --subst-models --no-dnp ${tracksArg} ${zonesArg} $src/okm.kicad_pcb -o ocularium.step + kicad-cli pcb export glb --subst-models --no-dnp ${tracksArg} ${zonesArg} $src/okm.kicad_pcb -o ocularium.glb + + cd ../panel/model + + kicad-cli pcb export step --subst-models --no-dnp ${tracksArg} ${zonesArg} ${panel}/share/npry/ocularium/panel.kicad_pcb -o panel.step + kicad-cli pcb export glb --subst-models --no-dnp ${tracksArg} ${zonesArg} ${panel}/share/npry/ocularium/panel.kicad_pcb -o panel.glb +'' diff --git a/nix/panel.nix b/nix/panel.nix new file mode 100644 index 0000000..41f55dd --- /dev/null +++ b/nix/panel.nix @@ -0,0 +1,29 @@ +{ + kicad, + kikit, + nix-filter, + runCommand, +}: runCommand "ocularium.panel" { + nativeBuildInputs = [ + kicad + kikit + ]; + + src = nix-filter { + root = ./..; + + include = [ + "kikit" + (nix-filter.matchExt "kicad_pcb") + ]; + }; +} '' + set -e + export HOME=$(mktemp -d) + + mkdir -p $out/share/npry/ocularium + cd $HOME + + kikit panelize -p :jlcTooling -p $src/kikit/jlc_edge_rails.json $src/okm.kicad_pcb panel.kicad_pcb + cp panel.kicad_{pcb,pro} $out/share/npry/ocularium +'' diff --git a/nix/schematics.nix b/nix/schematics.nix new file mode 100644 index 0000000..e69de29 diff --git a/nix/svg.nix b/nix/svg.nix new file mode 100644 index 0000000..3d93ecc --- /dev/null +++ b/nix/svg.nix @@ -0,0 +1,64 @@ +{ + runCommand, + kicad, + nix-filter, + + panel, +}: runCommand "ocularium.svg" { + nativeBuildInputs = [ + kicad + ]; + + src = nix-filter { + root = ./..; + + exclude = [ + "nix" + ".gitignore" + "flake.nix" + "flake.lock" + ".envrc" + "kikit" + "models" + ]; + }; + + allowedRequisites = []; +} '' + set -e + + export HOME=$(mktemp -d) + + mkdir -p $out/share/npry/ocularium/svg + mkdir -p $out/share/npry/ocularium/panel/svg + + mksvg() { + local infile=$1 + local layers=$2 + local outfile=$3 + + kicad-cli pcb export svg \ + "$infile.kicad_pcb" \ + -l "$layers" \ + -o $outfile.svg \ + --page-size-mode 2 \ + --exclude-drawing-sheet + } + + readonly okm="$src/okm" + readonly panel="${panel}/share/npry/ocularium/panel" + + cd $out/share/npry/ocularium/svg + + mksvg "$okm" "F.Cu,F.Silkscreen,Edge.Cuts" front + mksvg "$okm" "B.Cu,B.Silkscreen,Edge.Cuts" back + mksvg "$okm" "In1.Cu,Edge.Cuts" in1 + mksvg "$okm" "In2.Cu,Edge.Cuts" in2 + + cd ../panel/svg + + mksvg "$panel" "F.Cu,F.Silkscreen,Edge.Cuts" front + mksvg "$panel" "B.Cu,B.Silkscreen,Edge.Cuts" back + mksvg "$panel" "In1.Cu,Edge.Cuts" in1 + mksvg "$panel" "In2.Cu,Edge.Cuts" in2 +'' -- cgit v1.3.1