diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..33b3108 --- /dev/null +++ b/Rakefile @@ -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 + diff --git a/version b/version new file mode 100644 index 0000000..573541a --- /dev/null +++ b/version @@ -0,0 +1 @@ +0