parent
d3cf455b07
commit
cc3b6cdcfe
@ -0,0 +1,181 @@ |
||||
# encoding: utf-8 |
||||
# ruby: 2.1.0 |
||||
=begin |
||||
Rakefile to manage hardware projects |
||||
|
||||
uses Lepton EDA for schematic and pcb-rnd for board layouts. |
||||
Rakefile instead of Makefile for better text file parsing capabilities. |
||||
=end |
||||
require 'rake/clean' |
||||
require 'csv' # to export BOM and costs |
||||
|
||||
# ================= |
||||
# project variables |
||||
# ================= |
||||
|
||||
# common name used for file names |
||||
name = "template" |
||||
# project version, read from "version" file |
||||
raise "define project version in 'version' file" unless File.exist? "version" |
||||
version = IO.read("version").split("\n")[0] |
||||
# current date for stamping output |
||||
date = Time.now.strftime("%Y-%m-%d") |
||||
# 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 |
||||
commit = `git rev-parse --short HEAD`.chomp |
||||
revision = "#{changes} (#{commit})" |
||||
|
||||
# path to qeda" |
||||
qeda = "qeda" |
||||
|
||||
# ========== |
||||
# main tasks |
||||
# ========== |
||||
|
||||
desc "main building task" |
||||
task :default => [:print, :fabrication, :bom] |
||||
|
||||
desc "print schematic and layout (as pdf)" |
||||
prints = [ "#{name}.sch.pdf", "#{name}.brd.pdf", "#{name}.brd-top.svg", "#{name}.brd-bottom.svg" ] |
||||
task :print => prints |
||||
CLEAN.include([ "#{name}.versioned.sch", "#{name}.versioned.lht" ]) |
||||
CLOBBER.include(prints) |
||||
|
||||
desc "generate fabrication gerbers (as archive)" |
||||
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" ] |
||||
fab = [ "#{name}.brd.zip" ] |
||||
task :fabrication => fab |
||||
CLEAN.include(gerbers) |
||||
CLOBBER.include(fab) |
||||
|
||||
desc "generate symbols and footprints from parts" |
||||
task :library do |
||||
sh "#{qeda} config output geda" |
||||
sh "#{qeda} generate ." |
||||
sh "#{qeda} config output coraleda" |
||||
sh "#{qeda} generate ." |
||||
end |
||||
|
||||
desc "export netlist from schematic" |
||||
net = [ "#{name}.tdx" ] |
||||
task :netlist => net |
||||
CLOBBER.include(net) |
||||
|
||||
desc "export notes from schematic" |
||||
notes = [ "#{name}.notes.txt" ] |
||||
task :notes => notes |
||||
CLOBBER.include(notes) |
||||
|
||||
desc "export BOMs from schematic" |
||||
boms = [ "#{name}.bom.csv" ] |
||||
task :bom => boms |
||||
CLOBBER.include(boms) |
||||
|
||||
# =============== |
||||
# file generation |
||||
# =============== |
||||
|
||||
desc "generate schematic with version information all symbols embedded" |
||||
rule ".versioned.sch" => ".sch" do |t| |
||||
sh "cp #{t.source} #{t.name}" |
||||
sh "lepton-embed --embed #{t.name} 2> /dev/null" |
||||
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 |
||||
|
||||
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 |
||||
|
||||
desc "generate printable version (PDF) of schematic" |
||||
rule ".sch.pdf" => ".versioned.sch" do |t| |
||||
sh "lepton-cli export --color --paper iso_a4 --layout landscape --output #{t.name} #{t.source} 2> /dev/null" |
||||
end |
||||
|
||||
desc "generate printable version (PostScript) of board layout" |
||||
rule ".brd.ps" => ".versioned.lht" do |t| |
||||
sh "pcb-rnd -x ps --ps-color --media A4 --psfile #{t.name} #{t.source} 2> /dev/null" |
||||
end |
||||
|
||||
desc "generate printable version (PDF) of board layout" |
||||
rule ".brd.pdf" => ".brd.ps" do |t| |
||||
sh "ps2pdf -sPAPERSIZE=a4 -dEPSCrop #{t.source} #{t.name}" |
||||
end |
||||
|
||||
desc "generate photo realistic picture from layout (top side)" |
||||
rule ".brd-top.svg" => ".versioned.lht" do |t| |
||||
sh "pcb-rnd -x svg --photo-mode --outfile #{t.name} #{t.source} 2> /dev/null" |
||||
end |
||||
|
||||
desc "generate photo realistic picture from layout (bottom side)" |
||||
rule ".brd-bottom.svg" => ".versioned.lht" do |t| |
||||
sh "pcb-rnd -x svg --photo-mode --flip --outfile #{t.name} #{t.source} 2> /dev/null" |
||||
end |
||||
|
||||
desc "archive gerbers" |
||||
rule ".brd.zip" => ".versioned.lht" do |t| |
||||
base = File.basename(t.source, ".versioned.lht") |
||||
puts base |
||||
sh "pcb-rnd -x cam gerber:JLC_PCB --outfile #{base}.brd #{t.source} 2> /dev/null" |
||||
sh "zip --quiet #{t.name} #{base}.brd.xln #{base}.brd.a* #{base}.brd.g*" |
||||
end |
||||
|
||||
desc "export netlist from schematic" |
||||
rule ".tdx" => ".sch" do |t| |
||||
sh "lepton-netlist -g tEDAx -o #{t.name} #{t.source} 2> /dev/null" |
||||
end |
||||
|
||||
desc "generate BOM file from schematic" |
||||
rule ".bom.csv" => ".sch" do |t| |
||||
attributes = ["device", "value", "description", "footprint", "manufacturer", "mpn", "datasheet", "lcsc-sku", "digikey-sku", "aliexpress-sku"] |
||||
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 |
||||
|
||||
# ================ |
||||
# 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: '"') |
||||
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 |
||||
|
Loading…
Reference in new issue