# 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 = "usb_cable_tester" # local QEDA parts parts_local = [] parts_local << "ic_mcu_st_stm32f103xc@LQFP144" parts_local << "connector_usb-a-3.0_fci_10117835" parts_local << "connector_usb-b-3.0_amphenol_gsb4211" parts_local << "connector_usb-mini-b_edac_690-005-299-043" parts_local << "connector_usb-micro-b-3.0_gct_usb3110" parts_local << "connector_usb-micro-b-2.0_ali_32910334970" parts_local << "connector_usb-c_hro_type-c-31-m-04" parts_local << "connector_lightning_iphone5" parts_local << "vreg_ldo_torex_xc6206" parts_local << "connector_battery_18650" parts_local << "display_lcd_lcm1602" parts_local << "display_lcd_i2cadapter" parts_local << "display_oled_0.96in" parts_local << "vreg_pmic_tpower_tp4056" parts_local << "transistor_pmos_nxp_bss84" parts_local << "mechanical_button_6mm" parts_local << "connector_XH-2.54-2P" # the corresponding files library = parts_local.collect {|part| "library/#{part.split('@')[0].downcase}.yaml"} # github QEDA parts parts_github = [] parts_github << "ecs/csm-7" parts_github << "capacitor/c0603" parts_github << "resistor/r0603" parts_github << "diode/led0603" # path to qeda" qeda = "../qeda/bin/qeda" # ========== # main tasks # ========== desc "main building task" task :default => [:print, :fabrication] desc "print schematic and layout (as pdf)" prints = [ "#{name}.sch.pdf", "#{name}.brd.ps", "#{name}.brd-top.png", "#{name}.brd-bottom.png" ] task :print => prints 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" ] fab = [ "#{name}.brd.zip" ] task :fabrication => fab CLEAN.include(gerbers) CLOBBER.include(fab) desc "generate footprints from parts" task :library => library do # reset sh "#{qeda} reset" # configure sh "#{qeda} config pattern.preferManufacturer false" sh "#{qeda} config pattern.densityLevel M" sh "#{qeda} config pattern.smoothPadCorners true" # add local files parts_local.each do |part| sh "#{qeda} add #{part}" end # from github library parts_github.each do |part| sh "#{qeda} add #{part}" end # generate outputs 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) # =============== # file generation # =============== desc "generate printable version (PDF) of schematic" rule ".sch.pdf" => ".standalone.sch" do |t| sh "lepton-cli export --color --paper iso_a4 --layout landscape --color --output #{t.name} #{t.source} 2> /dev/null" end desc "generate printable version (PostScript) of board layout" rule ".brd.ps" => ".lht" do |t| sh "pcb-rnd -x ps --psfile #{t.name} #{t.source} 2> /dev/null" end desc "generate photo realistic picture from layout (top side)" rule ".brd-top.png" => ".lht" do |t| sh "pcb-rnd -x png --dpi 1200 --photo-mode --outfile #{t.name} #{t.source} 2> /dev/null" end desc "generate photo realistic picture from layout (bottom side)" rule ".brd-bottom.png" => ".lht" do |t| sh "pcb-rnd -x png --dpi 1200 --photo-mode --photo-flip-y --outfile #{t.name} #{t.source} 2> /dev/null" end desc "generate schematic with all symbols embedded" rule ".standalone.sch" => ".sch" do |t| sh "cp #{t.source} #{t.name}" sh "lepton-embed --embed #{t.name} 2> /dev/null" end desc "archive gerbers" rule ".brd.zip" => ".lht" do |t| base = File.basename(t.source, ".lht") sh "pcb-rnd -x cam gerber:JLC_PCB --outfile #{base}.brd #{t.source} 2> /dev/null" gerbers = [ "#{base}.brd.asb", "#{base}.brd.ast", "#{base}.brd.gbl", "#{base}.brd.gbo", "#{base}.brd.gbp", "#{base}.brd.gbs", "#{base}.brd.gko", "#{base}.brd.gtl", "#{base}.brd.gto", "#{base}.brd.gtp", "#{base}.brd.gts", "#{base}.brd.xln" ] fab = [ "#{name}.brd.zip" ] sh "zip --quiet #{t.name} #{gerbers.join(' ')}" 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 note file from schematic, listing the 'note' attributes from elements" rule ".notes.txt" => ".sch" do |t| notes_data = bom2(t.prerequisites[0], ["note", "value"]) File.open(t.name,"w") do |notes_file| notes_data.each do |note| next unless note['note'] note['note'] = note['note'].gsub('. ',".\n").gsub(/\n+$/,'') notes_file.puts "#{note['value']} (#{note['refdes']}):\n#{note['note']}\n\n" 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.gsub!(/(\d[Mkmµ]?)\?/, '\1Ω') # UTF-8 characters like Ω are replaced with ? by gnetlist list.gsub!(/(https?:\/\/[^:]*):/, '"\1":') # ':' (like in links) are not protected # parse bom2 csv = CSV.parse(list,{:col_sep => ":"}) 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