kut 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/LICENSE.rdoc +6 -0
  2. data/README.rdoc +20 -0
  3. data/Rakefile.rb +63 -0
  4. data/bin/kut +27 -0
  5. data/doc-src/PINS.rdoc +18 -0
  6. data/examples/example_helper.rb +1 -0
  7. data/examples/net_list/print_cmp_list.rb +101 -0
  8. data/examples/pins/A3P1000_PQFP208.pins +216 -0
  9. data/examples/pins/AT32UC3A0512.pins +151 -0
  10. data/examples/pins/EMP7464S_TQFP100.pins +101 -0
  11. data/examples/pins/ata40conn.pins +44 -0
  12. data/examples/pins/full_sata.pins +25 -0
  13. data/examples/pins/jm20330.pins +85 -0
  14. data/lib/kut.rb +2 -0
  15. data/lib/kut/application.rb +56 -0
  16. data/lib/kut/commands/gost/bom2el_list.rb +171 -0
  17. data/lib/kut/commands/help-cmd.rb +32 -0
  18. data/lib/kut/commands/lib-gen-cmd.rb +88 -0
  19. data/lib/kut/commands/net_list2bom.rb +81 -0
  20. data/lib/kut/eeschema/wire.rb +3 -0
  21. data/lib/kut/kut_module.rb +18 -0
  22. data/lib/kut/library/components.rb +167 -0
  23. data/lib/kut/library/generator.rb +25 -0
  24. data/lib/kut/library/generator/default.rb +123 -0
  25. data/lib/kut/library/generator/gost-con.rb +116 -0
  26. data/lib/kut/library/generator/simple.rb +123 -0
  27. data/lib/kut/library/pins_reader.rb +47 -0
  28. data/lib/kut/library/regexp.rb +18 -0
  29. data/lib/kut/misc/matrix.rb +2 -0
  30. data/lib/kut/misc/point.rb +25 -0
  31. data/lib/kut/misc/rectangle.rb +20 -0
  32. data/lib/kut/net_list/concept.rb +20 -0
  33. data/lib/kut/net_list/kicad.rb +40 -0
  34. data/lib/kut/net_list/pcad.rb +69 -0
  35. data/lib/kut/tests/Rakefile.rb +0 -0
  36. data/lib/kut/tests/rectangle.rb +23 -0
  37. data/test/library_cmp_pin_test.rb +16 -0
  38. data/test/library_pins_reader_test.rb +40 -0
  39. data/test/point_test.rb +17 -0
  40. metadata +100 -0
@@ -0,0 +1,171 @@
1
+ require 'ostruct'
2
+ require 'kut/net_list/kicad'
3
+ require 'kut/net_list/pcad'
4
+ require 'csv'
5
+
6
+ module Kut
7
+ class Bom2EL
8
+ attr_reader :name
9
+ attr_reader :help_banner
10
+
11
+ def initialize
12
+ @name = 'gs-bom2el'
13
+ @help_banner = 'Generate list of elements from bill of materials'
14
+ @generators = []
15
+
16
+ @options = OpenStruct.new
17
+ @options.in_file_name = '-'
18
+ @options.out_file_name = '-'
19
+ @options.separator = ';'
20
+
21
+ @option_parser = OptionParser.new do |opts|
22
+ opts.banner = "Usage: kut #{self.name} [options]"
23
+
24
+ opts.on("-i", "--input INPUT_FILE", "Innput pins file. if - to use stdin.") do |file_name|
25
+ @options.in_file_name = file_name
26
+ end
27
+
28
+ opts.on("-o", "--output OUTPUT_FILE", "Output libary file. if - to use stdout.") do |file_name|
29
+ @options.out_file_name = file_name
30
+ end
31
+
32
+ end
33
+
34
+ end
35
+
36
+ def help(args)
37
+ @option_parser.parse!(args)
38
+ @option_parser.to_s()
39
+ end
40
+
41
+
42
+ #
43
+ def join_ref(ref_list)
44
+ return '' unless ref_list
45
+
46
+ ref_list.sort! { |a, b|
47
+ a =~ /(\D+)(\d*)/
48
+ a_n = $1
49
+ a_val = $2 ? $2.to_i : -1
50
+ b =~ /(\D+)(\d*)/
51
+ b_n = $1
52
+ b_val = $2 ? $2.to_i : -1
53
+
54
+ res = a_n <=> b_n
55
+ res = a_val <=> b_val if res == 0
56
+ res
57
+ }
58
+
59
+ ref_list.first =~ /(\D+)(\d+)/
60
+ prev_pref = $1
61
+ prev_num = $2.to_i
62
+ prev_ref = ref_list.first
63
+
64
+ result = ref_list.first
65
+ ref_list.delete_at(0)
66
+ counter = 0
67
+
68
+ # while ! ref_list.empty?
69
+ # ref = ref_list.first
70
+ # ref_list.delete_at(0)
71
+ # end
72
+
73
+ flag = false
74
+
75
+ ref_list.each { |ref|
76
+ ref =~ /(\D+)(\d+)/
77
+ pref = $1
78
+ num = $2.to_i
79
+
80
+ flag = (pref == prev_pref) && (num == (prev_num + 1))
81
+
82
+ if !flag then
83
+ if counter != 0 then
84
+ result += counter > 1 ? '..' : ','
85
+ result += prev_ref + ',' + ref
86
+ else
87
+ result += ',' + ref
88
+ end
89
+ end
90
+
91
+ #result += '..' + prev_ref + ',' + ref unless flag && counter != 0
92
+ #result += ',' + ref unless flag
93
+
94
+ counter += 1 if flag
95
+ counter = 0 unless flag
96
+
97
+ prev_pref = pref
98
+ prev_num = num
99
+ prev_ref = ref
100
+ }
101
+
102
+ if flag && counter != 0 then
103
+ result += counter > 1 ? '..' : ','
104
+ result += prev_ref
105
+ end
106
+
107
+ result
108
+ end
109
+
110
+ def gs_bom2el(f_in, f_out)
111
+
112
+ sep = @options.separator
113
+
114
+ first_line = true
115
+ header = nil
116
+ rows = []
117
+
118
+ f_in.each_line { |line|
119
+ row = CSV.parse_line(line, sep)
120
+ header = row if first_line
121
+ rows << row unless first_line
122
+ first_line = false if first_line
123
+ }
124
+
125
+ footprint_index = header.index("footprint")
126
+ ref_index = header.index("ref")
127
+ value_index = header.index("value")
128
+
129
+ groups = {}
130
+
131
+ rows.each { |row|
132
+ gr_id = "#{row[value_index]} #{row[footprint_index]}"
133
+ group = groups[gr_id]
134
+ unless group
135
+ group = []
136
+ groups[gr_id] = group
137
+ end
138
+ group << row[ref_index].to_s
139
+ }
140
+
141
+ result = []
142
+
143
+ groups.each { |key, value|
144
+ count = value.size()
145
+ refs = join_ref(value)
146
+ result << "#{refs}#{sep}#{key}#{sep}#{count}\n"
147
+ }
148
+
149
+ result.sort!
150
+ f_out << "refs#{sep}type#{sep}count\n"
151
+ result.each { |v| f_out << v }
152
+ end
153
+
154
+ def run(args)
155
+
156
+ begin @option_parser.parse!(args)
157
+ rescue OptionParser::InvalidOption => e
158
+ $stderr << "Unknow option #{e}\n"
159
+ exit
160
+ end
161
+
162
+ f_in = $stdin
163
+ f_in = File.new(@options.in_file_name) if @options.in_file_name && @options.in_file_name != '-'
164
+ f_out = $stdout
165
+ f_out = File.new(@options.out_file_name, 'w') if @options.out_file_name && @options.out_file_name != '-'
166
+
167
+ gs_bom2el(f_in, f_out)
168
+
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,32 @@
1
+ require 'kut/application'
2
+
3
+ module Kut
4
+ class HelpCommand
5
+ attr_reader :name
6
+ attr_reader :help_banner
7
+
8
+ def initialize
9
+ @name = 'help'
10
+ @help_banner = 'Help for information on a specific command.'
11
+ end
12
+
13
+ def help(args)
14
+ @help_banner
15
+ end
16
+
17
+ def show_cmd_help(cmd_name, args)
18
+ cmd = Kut.application.command_by_name(cmd_name)
19
+ puts cmd.help(args) if cmd
20
+ puts "Help for command #{cmd_name} not found." unless cmd
21
+ exit
22
+ end
23
+
24
+ def run(args)
25
+ Kut.application.show_help() unless args
26
+ Kut.application.show_help() if args.size() == 0
27
+ help_args = args.dup()
28
+ help_args.delete_at(0)
29
+ show_cmd_help(args[0], help_args)
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,88 @@
1
+ require 'ostruct'
2
+ require 'kut/library/generator/simple'
3
+ require 'kut/library/generator/default'
4
+ require 'kut/library/generator/gost-con'
5
+ module Kut
6
+ class LibraryGeneratorCommand
7
+ attr_reader :name
8
+ attr_reader :help_banner
9
+ attr_accessor :generators
10
+
11
+ def initialize
12
+ @name = 'gen-lib'
13
+ @help_banner = 'Generate schema library'
14
+ @generators = []
15
+
16
+ @options = OpenStruct.new
17
+ @options.in_file_name = '-'
18
+ @options.out_file_name = '-'
19
+ @options.generator_name = 'default'
20
+
21
+ @option_parser = OptionParser.new do |opts|
22
+ opts.banner = "Usage: kut #{self.name} [options]"
23
+ opts.on("-G", "--generator GENERATOR_NAME", "Select generator") do |gen_name|
24
+ @options.generator_name = gen_name
25
+ end
26
+
27
+ opts.on("-i", "--input INPUT_FILE", "Innput pins file. if - to use stdin.") do |file_name|
28
+ @options.in_file_name = file_name
29
+ end
30
+
31
+ opts.on("-o", "--output OUTPUT_LIBRARY_FILE", "Output libary file. if - to use stdout.") do |file_name|
32
+ @options.out_file_name = file_name
33
+ end
34
+
35
+ opts.on("--list", "List of avalaible generators") do
36
+ $stderr << "Avalaible generators:\n"
37
+ generators.each { |gen|
38
+ $stderr << "#{' ' * 3}#{gen.name}\n"
39
+ }
40
+ exit
41
+ end
42
+ end
43
+ add_default_generators
44
+ end
45
+
46
+ def add_default_generators
47
+ generators << Kut::Library::DefaultGenerator.new
48
+ generators << Kut::Library::SimpleGenerator.new
49
+ generators << Kut::Library::GOSTConnGenerator.new
50
+ end
51
+
52
+ def find_generator(name)
53
+ generators.each { |g| return g if g.name.to_s() == name }
54
+ nil
55
+ end
56
+
57
+ def help(args)
58
+ #args_cp = args.dup()
59
+ @option_parser.parse!(args)
60
+ gen = find_generator(@options.generator_name)
61
+ gen_help = ''
62
+ gen_help = gen.prepare(args).to_s() if gen
63
+ @option_parser.to_s() + gen_help
64
+ end
65
+
66
+ def run(args)
67
+ args_cp = args.dup
68
+ begin @option_parser.parse!(args)
69
+ rescue OptionParser::InvalidOption => e
70
+ args = [(args_cp - args)[-1]] + args
71
+ end
72
+
73
+ gen = find_generator(@options.generator_name)
74
+ $stderr << "Generator '#{@options.generator_name}' not found.\n" unless gen
75
+ exit unless gen
76
+
77
+ f_in = $stdin
78
+ f_in = File.new(@options.in_file_name) if @options.in_file_name && @options.in_file_name != '-'
79
+ f_out = $stdout
80
+ f_out = File.new(@options.out_file_name, 'w') if @options.out_file_name && @options.out_file_name != '-'
81
+
82
+ f_out << "EESchema-LIBRARY Version 2.0 24/1/1997-18:9:6\n"
83
+ gen.prepare(args)
84
+ f_out << gen.generate(f_in, f_out)
85
+ f_out << "#EndLibrary\n"
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,81 @@
1
+ require 'ostruct'
2
+ require 'kut/net_list/kicad'
3
+ require 'kut/net_list/pcad'
4
+
5
+ module Kut
6
+ class NetList2Bom
7
+ attr_reader :name
8
+ attr_reader :help_banner
9
+
10
+ def initialize
11
+ @name = 'net2bom'
12
+ @help_banner = 'Generatr bill of materials from netlist'
13
+ @generators = []
14
+
15
+ @options = OpenStruct.new
16
+ @options.in_file_name = '-'
17
+ @options.out_file_name = '-'
18
+ @options.net_list_loader = Kut::NetList::KiCadNetList
19
+ @options.separator = ';'
20
+
21
+ @option_parser = OptionParser.new do |opts|
22
+ opts.banner = "Usage: kut #{self.name} [options]"
23
+
24
+ opts.on("-f", "--format NET_LIST_FORMAT", "Netlist file format (kicad - default, pcad)") do |format|
25
+ case format
26
+ when 'pcad' then @options.net_list_loader = Kut::NetList::PCadNetList
27
+ when 'kicad' then @options.net_list_loader = Kut::NetList::KiCadNetList
28
+ else
29
+ $stderr << "Netlist format #{format} isn't supported.\n"
30
+ exit
31
+ end
32
+ end
33
+
34
+ opts.on("-i", "--input INPUT_FILE", "Innput pins file. if - to use stdin.") do |file_name|
35
+ @options.in_file_name = file_name
36
+ end
37
+
38
+ opts.on("-o", "--output OUTPUT_FILE", "Output libary file. if - to use stdout.") do |file_name|
39
+ @options.out_file_name = file_name
40
+ end
41
+
42
+ end
43
+
44
+ end
45
+
46
+ def help(args)
47
+ @option_parser.parse!(args)
48
+ @option_parser.to_s()
49
+ end
50
+
51
+ def net2bom(f_in, f_out)
52
+ net_list = @options.net_list_loader.new(f_in)
53
+ cmp_list = net_list.by_components()
54
+
55
+ sep = @options.separator
56
+
57
+ f_out << "ref#{sep}value#{sep}footprint\n"
58
+
59
+ cmp_list.each{ |cmp|
60
+ f_out << "#{cmp.reference}#{sep}#{cmp.value}#{sep}#{cmp.footprint}\n"
61
+ }
62
+ end
63
+
64
+ def run(args)
65
+
66
+ begin @option_parser.parse!(args)
67
+ rescue OptionParser::InvalidOption => e
68
+ $stderr << "Unknow option #{e}\n"
69
+ exit
70
+ end
71
+
72
+ f_in = $stdin
73
+ f_in = File.new(@options.in_file_name) if @options.in_file_name && @options.in_file_name != '-'
74
+ f_out = $stdout
75
+ f_out = File.new(@options.out_file_name, 'w') if @options.out_file_name && @options.out_file_name != '-'
76
+
77
+ net2bom(f_in, f_out)
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,3 @@
1
+ class Wire
2
+ attr_accessor :startx, :starty, :endx, :endy
3
+ end
@@ -0,0 +1,18 @@
1
+ require 'kut/application'
2
+
3
+ module Kut
4
+ #
5
+ # Kut module singleton methods.
6
+ #
7
+ class << self
8
+ # Current Kut Application
9
+ def application
10
+ @application ||= Kut::Application.new
11
+ end
12
+
13
+ # Set the current Kut application object.
14
+ def application=(app)
15
+ @application = app
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,167 @@
1
+ module Kut
2
+ module Library
3
+
4
+ class Field
5
+ attr_accessor :number, :text, :pos, :dimension, :orientation
6
+ attr_accessor :visibility, :hjustify, :vjustify, :italic, :bold, :name
7
+
8
+ def initialize(params = {})
9
+ #number, text, pos, dimension, orientation, visibility, hjustify, vjustify, italic, bold, name
10
+ if Hash === params
11
+ @number = params[:number] ? params[:number] : 0
12
+ @text = params[:text] ? params[:text] : 'TEXT'
13
+ @pos = params[:pos] ? params[:pos] : [0, 0]
14
+ @dimension = params[:dimension] ? params[:dimension] : 50
15
+ @orientation = params[:orientation] ? params[:orientation] : 'H'
16
+ @visibility = params[:visibility] ? params[:visibility] : 'V'
17
+ @hjustify = params[:hjustify] ? params[:hjustify] : 'C'
18
+ @vjustify = params[:vjustify] ? params[:vjustify] : 'C'
19
+ @italic = params[:italic] ? params[:italic] : 'N'
20
+ @bold = params[:bold] ? params[:bold] : 'N'
21
+ @name = params[:name] ? params[:name] : nil
22
+ end
23
+ #TODO implement raise exception
24
+ end
25
+
26
+ def to_s
27
+ __name = @name ? "\"#{@name}\"" : ''
28
+ "F#{@number} \"#{@text}\" #{@pos[0]} #{@pos[1]} #{@dimension} #{@orientation} #{@visibility} #{@hjustify} #{@vjustify}#{@italic}#{@bold} #{__name}\n"
29
+ end
30
+ end
31
+
32
+ #Implementation of Pin component
33
+ class Pin
34
+ attr_accessor :name, :number, :pos, :length
35
+ attr_accessor :orientation, :snum, :snom, :unit, :convert, :etype
36
+
37
+ #Parametrs name, number, pos, length, orientation, snum, snom, unit, convert, etype
38
+ #Example creation: Pin.new(:name => 'PL2303', :orientation => 'U', :pos => [15, 24])
39
+ def initialize(params = {}) #name, number, posx, posy, length, orientation, snum, snom, unit, convert, etype
40
+ if Hash === params
41
+ @name = params[:name] ? params[:name] : '~'
42
+ @number = params[:number] ? params[:number] : '0'
43
+ @pos = params[:pos] ? params[:pos] : [0, 0]
44
+ @length = params[:length] ? params[:length] : 300
45
+ @orientation = params[:orientation] ? params[:orientation] : 'R'
46
+ @snum = params[:snum] ? params[:snum] : 40
47
+ @snom = params[:snom] ? params[:snom] : 40
48
+ @unit = params[:unit] ? params[:unit] : 0
49
+ @convert = params[:convert] ? params[:convert] : 0
50
+ @etype = params[:etype] ? params[:etype] : 'P'
51
+ end
52
+ #TODO implement raise exception
53
+ end
54
+
55
+ def to_s
56
+ "X #{@name} #{@number} #{@pos[0]} #{@pos[1]} #{@length} #{@orientation} #{@snum} #{@snom} #{@unit} #{@convert} #{@etype}\n"
57
+ end
58
+ end
59
+
60
+ class Text
61
+ attr_accessor :orientation, :pos, :dimension, :unit, :convert, :text
62
+
63
+
64
+ def initialize(params = {}) #:orientation, :pos, :dimension, :unit, :convert, :text
65
+ if Hash === params
66
+ @orientation = params[:orientation] ? params[:orientation] : 0
67
+ @pos = params[:pos] ? params[:pos] : [0, 0]
68
+ @dimension = params[:dimension] ? params[:dimension] : 40
69
+ @unit = params[:unit] ? params[:unit] : 0
70
+ @convert = params[:convert] ? params[:convert] : 0
71
+ @text = params[:text] ? params[:text] : ''
72
+ end
73
+ #TODO implement raise exception
74
+ end
75
+
76
+ def to_s
77
+ "T #{@orientation} #{@pos[0]} #{@pos[1]} #{@dimension} 0 #{@unit} #{@convert} #{@text}\n"
78
+ end
79
+ end
80
+
81
+ class Polygon
82
+ attr_accessor :parts, :convert, :ltrait
83
+ attr_accessor :points, :cc
84
+
85
+ def initialize(params = {}) #:parts, :convert, :ltrait, :points, :cc
86
+ if Hash === params
87
+ @parts = params[:parts] ? params[:parts] : 0
88
+ @points = params[:points] ? params[:points] : []
89
+ @convert = params[:convert] ? params[:convert] : 0
90
+ @ltrait = params[:ltrait] ? params[:ltrait] : 0
91
+ @cc = params[:cc] ? params[:cc] : 'N'
92
+ end
93
+ #TODO implement raise exception
94
+ end
95
+
96
+ def to_s
97
+ result = "P #{@points.length} #{@parts} #{@convert} #{@ltrait}"
98
+ @points.each { |point|
99
+ result += " #{point[0]} #{point[1]}"
100
+ }
101
+ result += " #{@cc}\n"
102
+ end
103
+ end
104
+
105
+ class Rectangle
106
+ attr_accessor :start, :end, :unit, :convert, :ltrait, :cc
107
+
108
+ def initialize(params = {}) #:start, :end, :unit, :convert, :ltrait, :cc
109
+ if Hash === params
110
+ @start = params[:start] ? params[:start] : [0, 0]
111
+ @end = params[:end] ? params[:end] : [0, 0]
112
+ @unit = params[:unit] ? params[:unit] : 0
113
+ @convert = params[:convert] ? params[:convert] : 0
114
+ @ltrait = params[:ltrait] ? params[:ltrait] : 0
115
+ @cc = params[:cc] ? params[:cc] : 'N'
116
+ end
117
+ #TODO implement raise exception
118
+ end
119
+
120
+ def to_s
121
+ "S #{@start[0]} #{@start[1]} #{@end[0]} #{@end[1]} #{@unit} #{@convert} #{@ltrait} #{@cc}\n"
122
+ end
123
+ end
124
+
125
+ class Component
126
+ attr_accessor :name, :reference, :text_offset, :draw_pinnumber, :draw_pinname
127
+ attr_accessor :unit_count, :units_locked, :option_flag
128
+ attr_accessor :alias, :fields, :draws
129
+
130
+ def initialize(params = {})
131
+ if Hash === params
132
+ @name = params[:name] ? params[:name] : ''
133
+ @reference = params[:reference] ? params[:reference] : 'U'
134
+ @text_offset = params[:text_offset] ? params[:text_offset] : 30
135
+ @draw_pinnumber = params[:draw_pinnumber] ? params[:draw_pinnumber] : 'Y'
136
+ @draw_pinname = params[:draw_pinname] ? params[:draw_pinname] : 'Y'
137
+ @unit_count = params[:unit_count] ? params[:unit_count] : 1
138
+ @units_locked = params[:units_locked] ? params[:units_locked] : 'F'
139
+ @option_flag = params[:option_flag] ? params[:option_flag] : 'N'
140
+ @alias = params[:alias] ? params[:alias] : []
141
+ @fields = params[:fields] ? params[:fields] : []
142
+ @draws = params[:draws] ? params[:draws] : []
143
+ end
144
+ #TODO implement raise exception
145
+ end
146
+
147
+ def to_s
148
+ result = "DEF #{@name} #{@reference} 0 #{@text_offset} #{@draw_pinnumber} #{@draw_pinname} #{@unit_count} #{@units_locked} #{@option_flag}\n"
149
+ result += "ALIAS"
150
+ @alias.each { |nm| result += " #{nm}" } if @alias
151
+ result += "\n"
152
+
153
+ @fields.each { |field| result += "#{field.to_s}" } if @fields
154
+
155
+ result += "DRAW\n"
156
+
157
+ @draws.each { |draw| result += "#{draw.to_s}" } if @draws
158
+
159
+ result += "ENDDRAW\n"
160
+
161
+ result += "ENDDEF\n"
162
+ end
163
+
164
+ end
165
+
166
+ end # end module Library
167
+ end # end module Kut