1
|
require 'rake/clean'
|
2
|
|
3
|
# ==============
|
4
|
# important info
|
5
|
# ==============
|
6
|
|
7
|
target = "simtrace"
|
8
|
version = IO.read("version").chomp
|
9
|
date = Time.now.strftime("%Y-%m-%d")
|
10
|
revision = `git log --pretty=oneline "#{target}.sch" | wc -l`.chomp.to_i
|
11
|
# symbol library for gschem
|
12
|
LIB = "lib/symbols/"
|
13
|
# gEDA scheme
|
14
|
GEDA_SCHEME_DIRS=["/usr/share/gEDA/scheme","/usr/local/gEDA/scheme"].collect{|path| File.directory?(path) ? path : nil}.compact
|
15
|
unless GEDA_SCHEME_DIRS.size==0 then
|
16
|
GEDA_SCHEME_DIR=GEDA_SCHEME_DIRS[0]
|
17
|
else
|
18
|
GEDA_SCHEME_DIR=nil
|
19
|
puts "warning: could not find gEDA scheme directory. can not print schematic"
|
20
|
end
|
21
|
|
22
|
|
23
|
# schema
|
24
|
sch = "#{target}.sch"
|
25
|
# schema with version
|
26
|
vsch = "#{target}_v#{version}.#{revision.to_s.rjust(3,'0')}.sch"
|
27
|
|
28
|
|
29
|
# ================
|
30
|
# helper functions
|
31
|
# ================
|
32
|
|
33
|
# read schema
|
34
|
# return a list of components
|
35
|
def read_sch(path)
|
36
|
# get all symbols
|
37
|
symbols = read_symbols(LIB)
|
38
|
# read schema
|
39
|
text = IO.read(path)
|
40
|
# parse all elements
|
41
|
elements = []
|
42
|
element = {}
|
43
|
block = false
|
44
|
text.each_line do |line|
|
45
|
l = line.chomp
|
46
|
if l=="{" then
|
47
|
block = true
|
48
|
element[:block] = {} unless element[:block]
|
49
|
elsif l=="}" then
|
50
|
block = false
|
51
|
elsif block then
|
52
|
# only take attributes
|
53
|
if l.include?("=") then
|
54
|
k,v = l.split("=")
|
55
|
element[:block][k] = v
|
56
|
end
|
57
|
elsif !block then
|
58
|
elements << element unless element.empty?
|
59
|
element = {}
|
60
|
element[:line] = l
|
61
|
element[:type] = l[0,1]
|
62
|
if element[:type]=="C" then
|
63
|
element[:symbol] = l.split(" ")[-1]
|
64
|
# get the default attributes (if any)
|
65
|
element[:block] = symbols[element[:symbol]].dup if symbols[element[:symbol]]
|
66
|
end
|
67
|
else
|
68
|
raise "don't know how to handle line: #{l}"
|
69
|
end
|
70
|
end
|
71
|
return elements
|
72
|
end
|
73
|
|
74
|
# read the attributes from a symbol
|
75
|
# return { name => value }
|
76
|
# warning: it only get uniq attributes (not multiple slots, ...)
|
77
|
def read_symbol(file)
|
78
|
text = IO.read(file)
|
79
|
symbol = {}
|
80
|
block = false
|
81
|
text.each_line do |line|
|
82
|
l = line.chomp
|
83
|
if l=="{" then
|
84
|
block = true
|
85
|
elsif l=="}" then
|
86
|
block = false
|
87
|
elsif block then
|
88
|
next
|
89
|
elsif l.include?("=") then
|
90
|
name = l.split("=")[0]
|
91
|
value = l.split("=")[1..-1]*"="
|
92
|
symbol[name] = value
|
93
|
else
|
94
|
next
|
95
|
end
|
96
|
end
|
97
|
return symbol
|
98
|
end
|
99
|
|
100
|
# read all symbols
|
101
|
# return a list fo symbols { name => symbol } (see read_symbol)
|
102
|
def read_symbols(folder)
|
103
|
symbols = {}
|
104
|
Dir.entries(folder).each do |file|
|
105
|
next unless file =~ /\.sym$/
|
106
|
symbols[file.split("/")[-1]] = read_symbol(folder+"/"+file)
|
107
|
end
|
108
|
return symbols
|
109
|
end
|
110
|
|
111
|
# =========
|
112
|
# the tasks
|
113
|
# =========
|
114
|
|
115
|
task :default => [:version,:print,:pdf,:install,:check]
|
116
|
|
117
|
desc "set version in schema"
|
118
|
task :version => vsch
|
119
|
CLEAN.include(vsch)
|
120
|
CLOBBER.include("#{target}_*.sch")
|
121
|
|
122
|
desc "print schema (into ps)"
|
123
|
task :print => "#{target}.ps"
|
124
|
CLEAN.include("#{target}.ps")
|
125
|
|
126
|
desc "get printed schema in pdf"
|
127
|
task :pdf => "#{target}.pdf"
|
128
|
CLEAN.include("#{target}.pdf")
|
129
|
|
130
|
desc "put printed schema in output folder"
|
131
|
task :install => "#{target}.pdf" do
|
132
|
mkdir "../pcb/schema" unless File.directory? "../pcb/schema"
|
133
|
cp "#{target}.pdf","../pcb/schema/#{target}.pdf"
|
134
|
end
|
135
|
CLOBBER.include("../pcb/schema/#{target}.pdf")
|
136
|
|
137
|
|
138
|
# every component should have: refdes without ?, device, value,
|
139
|
# footprint, manufacturer, documentation, digikey
|
140
|
task :check => sch do
|
141
|
elements = read_sch(sch)
|
142
|
elements.each do |element|
|
143
|
if element[:type]=="C" then
|
144
|
if element[:block] and element[:block]["refdes"] then
|
145
|
name = element[:block]["refdes"]
|
146
|
name += " (#{element[:block]['device']})" if element[:block]["device"]
|
147
|
puts name+" has no ID" if element[:block]["refdes"].include? "?"
|
148
|
["device","value","footprint","manufacturer","manufacturer-part","documentation","digikey-part"].each do |attribute|
|
149
|
puts name+" has no "+attribute unless element[:block][attribute]
|
150
|
break if element[:block]["footprint"] =~ /^HEADER/ or element[:block]["footprint"] =~ /^JUMPER/
|
151
|
end
|
152
|
end
|
153
|
end
|
154
|
end
|
155
|
end
|
156
|
|
157
|
# ===============
|
158
|
# file processing
|
159
|
# ===============
|
160
|
|
161
|
file vsch => sch do
|
162
|
sh "cp #{sch} #{vsch}"
|
163
|
# on \ is to prevent ruby interpreting it, th other is for sed
|
164
|
# the version
|
165
|
sh "sed -i 's/\\(version=\\)\\$Version\\$/\\1#{version}/' #{vsch}"
|
166
|
# the date
|
167
|
sh "sed -i 's/\\(date=\\)\\$Date\\$/\\1#{date}/' #{vsch}"
|
168
|
# the revision
|
169
|
sh "sed -i 's/\\(revision=\\)\\$Revision\\$/\\1#{revision}/' #{vsch}"
|
170
|
end
|
171
|
|
172
|
file "#{target}.ps" => vsch do
|
173
|
if GEDA_SCHEME_DIR then
|
174
|
sh "gschem -p -o #{target}.ps -s #{GEDA_SCHEME_DIR}/print.scm #{vsch} > /dev/null 2>&1"
|
175
|
else
|
176
|
puts "can not print schematic. gEDA scheme directory missing"
|
177
|
end
|
178
|
end
|
179
|
|
180
|
file "#{target}.pdf" => "#{target}.ps" do
|
181
|
sh "ps2pdf -sPAPERSIZE=a4 #{target}.ps"
|
182
|
end
|