From 8490dbbda97066c01518c7eb6e2af096f1dd77a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Tue, 2 Nov 2021 17:02:42 +0100 Subject: [PATCH] add PnP export --- .gitignore | 1 + Rakefile | 18 ++++++++++++---- mass_prop.sh | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++ pnp_fab.tab | 5 +++++ 4 files changed, 78 insertions(+), 4 deletions(-) create mode 100755 mass_prop.sh create mode 100644 pnp_fab.tab diff --git a/.gitignore b/.gitignore index 49a73a3..072f823 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ *.notes.txt *.bom.csv *.cost.csv +*.cpl.csv *.json *.rb geda/footprints/ diff --git a/Rakefile b/Rakefile index 7115912..973cce3 100644 --- a/Rakefile +++ b/Rakefile @@ -33,7 +33,7 @@ qeda = "qeda" # ========== desc "main building task" -task :default => [:print, :fabrication, :bom] +task :default => [:print, :fabrication, :bom, :pnp] desc "print schematic and layout (as pdf)" prints = [ "#{name}.sch.pdf", "#{name}.brd.pdf", "#{name}.brd-top.svg", "#{name}.brd-bottom.svg" ] @@ -56,7 +56,7 @@ task :library do sh "#{qeda} generate ." end -desc "export netlist from schematic" +desc "export netlist" net = [ "#{name}.tdx" ] task :netlist => net CLOBBER.include(net) @@ -66,11 +66,16 @@ notes = [ "#{name}.notes.txt" ] task :notes => notes CLOBBER.include(notes) -desc "export BOMs from schematic" +desc "export BOM" boms = [ "#{name}.bom.csv" ] task :bom => boms CLOBBER.include(boms) +desc "export PnP placement" +pnps = [ "#{name}.cpl.csv" ] +task :pnp => pnps +CLOBBER.include(pnps) + # =============== # file generation # =============== @@ -143,6 +148,12 @@ rule ".bom.csv" => ".sch" do |t| end end +desc "generate pick-and-place file from board" +rule ".cpl.csv" => [".lht", "mass_prop.sh", "pnp_fab.tab"] do |t| + sh "./mass_prop.sh #{t.prerequisites[0]} pnp_fab.tab" # add fab placement offsets + sh "pcb-rnd -x XY --xyfile #{t.name} --xy-unit mm --format 'JLCPCB' --vendor jlcpcb #{t.prerequisites[0]}" # export XY file in JLCPCB format +end + # ================ # helper functions # ================ @@ -178,4 +189,3 @@ def bom2(schematic, attributes) end return to_return end - diff --git a/mass_prop.sh b/mass_prop.sh new file mode 100755 index 0000000..94b3071 --- /dev/null +++ b/mass_prop.sh @@ -0,0 +1,58 @@ +#!/bin/sh + +if test ! $# -eq 2 +then + echo "Need two arguments: a board file name and a tab file name" >&2 + exit 1 +fi + +board="$1" +tab="$2" + +if test ! -f "$board" +then + echo "Board file $board not found" >&2 + exit 1 +fi + +if test ! -f "$tab" +then + echo "Tab file $tab not found" >&2 + exit 1 +fi + +btmp=.tmp.$board + +awk -F "[ \t]*[;][ \t]*" -v "outfn=$btmp" ' + +BEGIN { sq = "'\''" } + +# quote s with single quotes and remove any single quote from it +# (pcb-rnd action syntax does not have escaping) +function squote(s) +{ + gsub("[" sq "]", ".", s) + return sq s sq +} + +# ignore comments +/^[ \t]*#/ { next } + +# generate an unselect-query-propset sequence for each line +(NF > 1) { + print "Unselect(all)" + print "query(select, " squote($1) ")" + for(n = 2; n <= NF; n++) { + if (split($n, A, "=") == 2) + print "propset(selection, " squote(A[1]) "," squote(A[2]) ")" + } +} + +END { + print "Unselect(all)" + print "Save(LayoutAs, " squote(outfn) ")" +} + +' < "$tab" | pcb-rnd --gui batch "$board" && mv "$btmp" "$board" + + diff --git a/pnp_fab.tab b/pnp_fab.tab new file mode 100644 index 0000000..b7d25a3 --- /dev/null +++ b/pnp_fab.tab @@ -0,0 +1,5 @@ +@.a.footprint == "LEDC2012X80N.lht"; a/xy::jlcpcb::rotate=270; +@.a.footprint == "RESC1608X55N.lht"; a/xy::jlcpcb::rotate=90; +@.a.footprint == "CONNECTOR_USB_MICRO-B_C10418.lht"; a/xy::jlcpcb::translate=-1.2mm,0mm; +@.a.footprint == "CONNECTOR_USB_MICRO-B_C10418.lht"; a/xy::jlcpcb::rotate=270; +@.a.footprint == "CONNECTOR_USB-A-2.0_RECEPTACLE_C42428.lht"; a/xy::jlcpcb::translate=0mm,-1.7mm;