rake: change Rakefile for KiCAD processing
This commit is contained in:
parent
932d8f9a39
commit
118fcf108c
|
@ -1,36 +1,34 @@
|
||||||
|
# schematic lepton-EDA
|
||||||
|
*.sch
|
||||||
|
|
||||||
|
# board layout pcb-rnd
|
||||||
|
*.lht
|
||||||
*.lht.*
|
*.lht.*
|
||||||
*.versioned.lht
|
|
||||||
|
# KiCAD
|
||||||
|
*.kicad_prl
|
||||||
|
*.kicad_pro-bak
|
||||||
|
*.xml
|
||||||
|
fp-info-cache
|
||||||
|
|
||||||
|
# temporary files
|
||||||
*~
|
*~
|
||||||
*.versioned.sch
|
\#*\#
|
||||||
|
|
||||||
|
# outputs
|
||||||
*.svg
|
*.svg
|
||||||
|
*.png
|
||||||
*.pdf
|
*.pdf
|
||||||
*.ps
|
*.ps
|
||||||
*.zip
|
*.zip
|
||||||
*.brd.*
|
|
||||||
*.ast
|
|
||||||
*.g2l
|
|
||||||
*.g3l
|
|
||||||
*.gbl
|
|
||||||
*.gbo
|
|
||||||
*.gbp
|
|
||||||
*.gbs
|
|
||||||
*.gko
|
|
||||||
*.gtl
|
|
||||||
*.gto
|
|
||||||
*.gtp
|
|
||||||
*.gts
|
|
||||||
*.xln
|
|
||||||
*.tdx
|
|
||||||
\#*\#
|
|
||||||
*.notes.txt
|
|
||||||
*.bom.csv
|
*.bom.csv
|
||||||
*.cost.csv
|
|
||||||
*.cpl.csv
|
*.cpl.csv
|
||||||
|
*.versioned.*
|
||||||
|
fabrication
|
||||||
|
|
||||||
|
# scripts and utilities
|
||||||
*.json
|
*.json
|
||||||
*.rb
|
*.rb
|
||||||
geda/footprints/
|
|
||||||
|
|
||||||
*.kicad_prl
|
# panel files
|
||||||
*.xml
|
panel.*
|
||||||
fp-info-cache
|
|
||||||
fabrication
|
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
package,x,y,rot
|
||||||
|
LEDC2012X80N,0,0,-90
|
||||||
|
UC1608X55N,0,0,90
|
||||||
|
SOT95P237X112-3N,0,0,180
|
|
163
Rakefile
163
Rakefile
|
@ -3,7 +3,13 @@
|
||||||
=begin
|
=begin
|
||||||
Rakefile to manage hardware projects
|
Rakefile to manage hardware projects
|
||||||
|
|
||||||
uses Lepton EDA for schematic and pcb-rnd for board layouts.
|
uses following tools:
|
||||||
|
- QEDA https://github.com/qeda/qeda
|
||||||
|
- PcbDraw https://github.com/yaqwsx/PcbDraw
|
||||||
|
- KiKit https://github.com/yaqwsx/KiKit
|
||||||
|
- KiAuto https://github.com/INTI-CMNB/KiAuto
|
||||||
|
- KiBoM https://github.com/SchrodingersGat/KiBoM
|
||||||
|
|
||||||
Rakefile instead of Makefile for better text file parsing capabilities.
|
Rakefile instead of Makefile for better text file parsing capabilities.
|
||||||
=end
|
=end
|
||||||
require 'rake/clean'
|
require 'rake/clean'
|
||||||
|
@ -14,39 +20,39 @@ require 'csv' # to export BOM and costs
|
||||||
# =================
|
# =================
|
||||||
|
|
||||||
# common name used for file names
|
# common name used for file names
|
||||||
name = "template"
|
name = ENV["NAME"] || "template"
|
||||||
# project version, read from "version" file
|
# project version, read from "version" file
|
||||||
raise "define project version in 'version' file" unless File.exist? "version"
|
raise "define project version in 'version' file" unless File.exist? "version"
|
||||||
version = IO.read("version").split("\n")[0]
|
version = IO.read("version").split("\n")[0]
|
||||||
# current date for stamping output
|
# current date for stamping output
|
||||||
date = Time.now.strftime("%Y-%m-%d")
|
date = Time.now.strftime("%Y-%m-%d")
|
||||||
# revision based on number of changes on schematic or board layout and current git commit
|
# revision based on number of changes on schematic or board layout and current git commit
|
||||||
changes = `git log --pretty=oneline "#{name}.sch" "#{name}.lht" | wc -l`.chomp.to_i
|
changes = `git log --pretty=oneline "#{name}.kicad_sch" "#{name}.kicad_pcb" | wc -l`.chomp.to_i
|
||||||
commit = `git rev-parse --short HEAD`.chomp
|
commit = `git rev-parse --short HEAD`.chomp
|
||||||
revision = "#{changes} (#{commit})"
|
revision = "#{changes} #{commit}"
|
||||||
|
|
||||||
# path to qeda"
|
# path to qeda"
|
||||||
qeda = "qeda"
|
qeda = "~/tmp/qeda/bin/qeda"
|
||||||
|
|
||||||
# ==========
|
# ==========
|
||||||
# main tasks
|
# main tasks
|
||||||
# ==========
|
# ==========
|
||||||
|
|
||||||
desc "main building task"
|
desc "main building task"
|
||||||
task :default => [:print, :fabrication, :bom, :pnp]
|
task :default => [:print, :fabrication, :bom]
|
||||||
|
|
||||||
desc "print schematic and layout (as pdf)"
|
desc "print schematic and layout (as pdf)"
|
||||||
prints = [ "#{name}.sch.pdf", "#{name}.brd.pdf", "#{name}.brd-top.svg", "#{name}.brd-bottom.svg" ]
|
prints = [ "#{name}.sch.pdf", "#{name}.brd-top.png", "#{name}.brd-bot.png" ]
|
||||||
task :print => prints
|
task :print => prints
|
||||||
CLEAN.include([ "#{name}.versioned.sch", "#{name}.versioned.lht" ])
|
CLEAN.include([ "#{name}.versioned.kicad_sch", "#{name}.versioned.kicad_pcb" ])
|
||||||
CLOBBER.include(prints)
|
CLOBBER.include(prints)
|
||||||
|
|
||||||
desc "generate fabrication gerbers (as archive)"
|
desc "generate fabrication files (gerbers/drill/BoM/PnP)"
|
||||||
gerbers = [ "#{name}.brd.asb", "#{name}.brd.ast", "#{name}.brd.gbl", "#{name}.brd.gbo", "#{name}.brd.gbp", "#{name}.brd.gbs", "#{name}.brd.gko", "#{name}.brd.gtl", "#{name}.brd.gto", "#{name}.brd.gtp", "#{name}.brd.gts", "#{name}.brd.xln", "#{name}.brd.g2l", "#{name}.brd.g3l" ]
|
FABRICATION_DIR = "fabrication"
|
||||||
fab = [ "#{name}.brd.zip" ]
|
task :fabrication => [ "#{name}.versioned.kicad_sch", "#{name}.versioned.kicad_pcb" ] do |t|
|
||||||
task :fabrication => fab
|
sh "kikit fab jlcpcb --drc --assembly --missingError --schematic #{t.prerequisites[0]} #{t.prerequisites[1]} #{FABRICATION_DIR}"
|
||||||
CLEAN.include(gerbers)
|
end
|
||||||
CLOBBER.include(fab)
|
CLEAN.include(FABRICATION_DIR)
|
||||||
|
|
||||||
desc "generate symbols and footprints from parts"
|
desc "generate symbols and footprints from parts"
|
||||||
task :library do
|
task :library do
|
||||||
|
@ -54,126 +60,49 @@ task :library do
|
||||||
sh "#{qeda} generate mylib"
|
sh "#{qeda} generate mylib"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "export BOMs from schematic"
|
desc "export Bill of Material (as CSV)"
|
||||||
boms = [ "#{name}.bom.csv" ]
|
boms = [ "#{name}.bom.csv" ]
|
||||||
task :bom => boms
|
task :bom => boms
|
||||||
|
CLEAN.include([ "#{name}.versioned.xml" ])
|
||||||
CLOBBER.include(boms)
|
CLOBBER.include(boms)
|
||||||
|
|
||||||
desc "export PnP placement"
|
|
||||||
pnps = [ "#{name}.cpl.csv" ]
|
|
||||||
task :pnp => pnps
|
|
||||||
CLOBBER.include(pnps)
|
|
||||||
|
|
||||||
# ===============
|
# ===============
|
||||||
# file generation
|
# file generation
|
||||||
# ===============
|
# ===============
|
||||||
|
|
||||||
desc "generate schematic with version information all symbols embedded"
|
desc "generate file with version information"
|
||||||
rule ".versioned.sch" => ".sch" do |t|
|
VERSIONED = [".kicad_sch", ".kicad_pcb", ".kicad_pro"]
|
||||||
sh "cp #{t.source} #{t.name}"
|
VERSIONED.each do |ext|
|
||||||
sh "lepton-embed --embed #{t.name} 2> /dev/null"
|
rule ".versioned" + ext => ext do |t|
|
||||||
sh "sed --in-place 's/\\$version\\$/#{version}/' #{t.name}"
|
sh "cp #{t.source} #{t.name}"
|
||||||
sh "sed --in-place 's/\\$date\\$/#{date}/' #{t.name}"
|
sh "sed --in-place 's/\\$version\\$/#{version}/g' #{t.name}"
|
||||||
sh "sed --in-place 's/\\$revision\\$/#{revision}/' #{t.name}"
|
sh "sed --in-place 's/\\$date\\$/#{date}/g' #{t.name}"
|
||||||
end
|
sh "sed --in-place 's/\\$revision\\$/#{revision}/g' #{t.name}"
|
||||||
|
end
|
||||||
desc "generate board layout with version information"
|
|
||||||
rule ".versioned.lht" => ".lht" do |t|
|
|
||||||
sh "cp #{t.source} #{t.name}"
|
|
||||||
sh "sed --in-place 's/\\$version\\$/#{version}/' #{t.name}"
|
|
||||||
sh "sed --in-place 's/\\$date\\$/#{date}/' #{t.name}"
|
|
||||||
sh "sed --in-place 's/\\$revision\\$/#{revision}/' #{t.name}"
|
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "generate printable version (PDF) of schematic"
|
desc "generate printable version (PDF) of schematic"
|
||||||
rule ".sch.pdf" => ".versioned.sch" do |t|
|
rule ".sch.pdf" => [".versioned.kicad_sch", ".versioned.kicad_pro"] do |t|
|
||||||
sh "lepton-cli export --color --paper=iso_a4 --layout=landscape --output=#{t.name} #{t.source} 2> /dev/null"
|
sh "eeschema_do export #{t.prerequisites[0]} ."
|
||||||
|
sh "mv #{t.prerequisites[0].split('.kicad_sch')[0]}.pdf #{t.name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "generate printable version (PostScript) of board layout"
|
desc "generate render from layout (top side)"
|
||||||
rule ".brd.ps" => ".versioned.lht" do |t|
|
rule ".brd-top.png" => ".versioned.kicad_pcb" do |t|
|
||||||
sh "pcb-rnd -x ps --ps-color --media A4 --psfile #{t.name} #{t.source} 2> /dev/null"
|
sh "pcbdraw --silent #{t.source} --dpi 600 #{t.name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "generate printable version (PDF) of board layout"
|
desc "generate render from layout (bottom side)"
|
||||||
rule ".brd.pdf" => ".brd.ps" do |t|
|
rule ".brd-bot.png" => ".versioned.kicad_pcb" do |t|
|
||||||
sh "ps2pdf -sPAPERSIZE=a4 -dEPSCrop #{t.source} #{t.name}"
|
sh "pcbdraw --silent #{t.source} --dpi 600 --back #{t.name}"
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "generate photo realistic picture from layout (top side)"
|
desc "generate netlist"
|
||||||
rule ".brd-top.svg" => ".versioned.lht" do |t|
|
rule ".versioned.xml" => ".versioned.kicad_sch" do |t|
|
||||||
sh "pcb-rnd -x svg --photo-mode --outfile #{t.name} #{t.source} 1> /dev/null"
|
sh "eeschema_do bom_xml #{t.source} ."
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "generate photo realistic picture from layout (bottom side)"
|
desc "generate BOM"
|
||||||
rule ".brd-bottom.svg" => ".versioned.lht" do |t|
|
rule ".bom.csv" => ".versioned.xml" do |t|
|
||||||
sh "pcb-rnd -x svg --photo-mode --flip --outfile #{t.name} #{t.source} 1> /dev/null"
|
sh "kibom #{t.source} #{t.name}"
|
||||||
end
|
|
||||||
|
|
||||||
desc "archive gerbers"
|
|
||||||
rule ".brd.zip" => ".versioned.lht" do |t|
|
|
||||||
base = File.basename(t.source, ".versioned.lht")
|
|
||||||
dir = "fabrication"
|
|
||||||
sh "mkdir #{dir}" unless File.directory?(dir)
|
|
||||||
sh "pcb-rnd -x cam gerber:JLC_PCB --outfile #{dir}/#{base}.brd #{t.source} 2> /dev/null"
|
|
||||||
sh "zip --quiet #{t.name} #{dir}/*"
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "generate BOM file from schematic"
|
|
||||||
rule ".bom.csv" => ".sch" do |t|
|
|
||||||
attributes = ["device", "value", "description", "footprint", "manufacturer", "mpn", "datasheet", "lcsc", "digikey"]
|
|
||||||
bom_data = bom2(t.prerequisites[0], attributes)
|
|
||||||
CSV.open(t.name, "wb") do |csv|
|
|
||||||
all_attributes = ["refdes","qty"] + attributes
|
|
||||||
csv << all_attributes
|
|
||||||
bom_data.each do |line|
|
|
||||||
csv << all_attributes.collect{|attribute| line[attribute]}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
desc "generate pick-and-place file from board"
|
|
||||||
rule ".cpl.csv" => [".versioned.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
|
|
||||||
# ================
|
|
||||||
|
|
||||||
# generate gnetlist bom2 and parse them
|
|
||||||
# arguments: schematic=schematic to use, attributes=attributes to use for generating bom2
|
|
||||||
# returns an array of hash. key is the attribute name, value is the attribute value
|
|
||||||
def bom2(schematic, attributes)
|
|
||||||
to_return = []
|
|
||||||
# force attributes to be an array
|
|
||||||
attributes = case attributes
|
|
||||||
when String
|
|
||||||
[attributes]
|
|
||||||
when Array
|
|
||||||
attributes
|
|
||||||
else
|
|
||||||
[attributes.to_s]
|
|
||||||
end
|
|
||||||
# generate bom2
|
|
||||||
list = `lepton-netlist --backend bom2 --backend-option attribs=#{attributes*','} --quiet --output - #{schematic} 2> /dev/null`
|
|
||||||
list = list.each_line {|l| '"' + l + '"' + '\n' }
|
|
||||||
list.gsub!(/^(.+)/, '"\1')
|
|
||||||
list.gsub!(/(.+)$/, '\1"')
|
|
||||||
list.gsub!(/(?!http):(?!\/\/)/, '\1":"\2') # protect the values between ':' (such as URLs)
|
|
||||||
# parse bom2
|
|
||||||
csv = CSV.parse(list, col_sep: ":", quote_char: '"')
|
|
||||||
if csv.empty? then
|
|
||||||
$stderr.puts "no parts found for BOM"
|
|
||||||
return []
|
|
||||||
end
|
|
||||||
csv[1..-1].each do |row|
|
|
||||||
line = {}
|
|
||||||
row.each_index do |col|
|
|
||||||
line[csv[0][col]] = row[col] unless row[col] == "unknown"
|
|
||||||
end
|
|
||||||
to_return << line
|
|
||||||
end
|
|
||||||
return to_return
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue