circuits 0.4.3 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- OTFhZjhiMjI3ODFkN2IzMmUyOGUwMGFkYjBiZTJhZmQ3YjVmMDhkOA==
4
+ YzIxYzBlMDM5ZmJjYjliOWZkODEwM2QxNGUwYmE5ZGIxMWZlYzFkZg==
5
5
  data.tar.gz: !binary |-
6
- M2RkOGE5YjkwOWNhNjA5NzcxOWM0ZTc4OTNiYTAxZDk2YTcxZmFmYg==
6
+ Y2E3NDYzMjVmMWY3OWI4MjliZmE5NTRlMTIyMDAwZTRmMGM5ZjNhZg==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NWExY2I5NGI4NDEyZGM4ZDFhZmY0NjdmYzM5OWIxYWY0Y2IwYWNlMTg5NjRj
10
- YjJlYzFiMDYxZmFlZjdmMzIwY2I1ZWQ0MmJmZGJkMDZlYTFkNTZmMjk2YjVk
11
- NmRmNGNhZDU2Y2YzYTE0Y2JhNGE2MTgxNjIwODgzY2Q3ZTIxYzk=
9
+ MTJhMDdmNzE2ZDYyMjAzYjkyMGJlMmRkNmNhYjc4NTZhMzliYmM1MzZiNjdh
10
+ OGUwMzY2ZWM0OThjYTQyNDIwYTZmOWMxYTdlOTA3ODAwZDhiZjI2NmE0NjEy
11
+ ZTA1MDg2MTE4NmMyMWI2YTgzYzhjMzRiNmQzOTY4MGZhNTM5YjM=
12
12
  data.tar.gz: !binary |-
13
- N2E3YjI0MjkyYjBjN2I0YjA0NTZjYjVkMmM3ZGRhMWNlODNkOTIwNzJlMTdm
14
- OTgwMGJjNDBjYWMyZjhhOTIxZDcwNDNjNDM1YzkyY2U5NmJhNTJiNTI4ZmEw
15
- YzExMTc5MTM5MWRmNDQzYzhkMTA3NTA4YTk2OTcwZTc5YjE4NGI=
13
+ MjM5YzM1OTE2MTZlZDc4ZjdlNDI1ODgzNTkxNmUxZWVjYjgyNGFkNDU4Yjlh
14
+ MTZiNjY0MDM5OGJlMzRiNjc0ZjU3YjM5MzU3NzM5ZWQyNDVmZTE2ZjRlYTdl
15
+ MDVhZjViYjc2MTlhNTc5ZWU1NGYzM2E5YzYzMGIxMDI5MmYyZDM=
@@ -1,22 +1,19 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # Logical AND Operator
6
- class And
7
- include Component
6
+ class And < Base
7
+ def initialize(opts = {})
8
+ @input_count = 2
9
+ @output_count = 1
10
+ super opts
11
+ end
8
12
 
9
13
  # Sets the output to be the result of a logical AND of the inputs
10
14
  def tick
11
15
  outputs[0].set(inputs.map(&:get).inject(:&))
12
16
  end
13
-
14
- private
15
-
16
- def set_defaults
17
- @input_count = 2
18
- @output_count = 1
19
- end
20
17
  end
21
18
  end
22
19
  end
@@ -0,0 +1,114 @@
1
+ require 'circuits/terminal/input'
2
+ require 'circuits/terminal/output'
3
+
4
+ module Circuits
5
+ # A component has a set of inputs an outputs. Every `tick` a componnent
6
+ # computes its outputs, but the componnent will wait for the `tock` before the
7
+ # componnent updates its own outputs
8
+ module Component
9
+ # Base class to extend
10
+ class Base
11
+ # Creates the Component with inputs and outputs
12
+ # @param opts [Hash] options to create the Component with
13
+ # @option opts [Array<Input>, FixNum] :inputs The array of inputs to use,
14
+ # or the number of inputs to create
15
+ def initialize(opts = {})
16
+ create_inputs opts
17
+ create_outputs opts
18
+ end
19
+
20
+ # Does the internal computation and sets the outputs
21
+ def tick
22
+ fail NotImplementedError
23
+ end
24
+
25
+ # Sets all the outputs expose what was set in #tick
26
+ def tock
27
+ outputs.each(&:tock)
28
+ end
29
+
30
+ # Gets the teminal assigned to the port
31
+ # @param port [Symbol] The symbol that represents the terminal
32
+ # @return [Input, Output] The terminal
33
+ def [](port)
34
+ p = port_mappings[port]
35
+ case p[:type]
36
+ when :input
37
+ inputs[p[:number]]
38
+ when :output
39
+ outputs[p[:number]]
40
+ end
41
+ end
42
+
43
+ # Assigns to an input or output
44
+ # @param port [Symbol] The symbol that represents the terminal
45
+ # @param terminal [Input, Output] The terminal to assign
46
+ # @return [Input, Output] The terminal that was passed in
47
+ def []=(port, terminal)
48
+ p = port_mappings[port]
49
+ case p[:type]
50
+ when :input
51
+ inputs[p[:number]] = terminal
52
+ when :output
53
+ outputs[p[:number]] = terminal
54
+ end
55
+ end
56
+
57
+ # the inputs of this component
58
+ attr_reader :inputs
59
+
60
+ # the outputs of this component
61
+ attr_reader :outputs
62
+
63
+ private
64
+
65
+ def create_inputs(opts)
66
+ if opts[:inputs].class == Array
67
+ @inputs = opts[:inputs]
68
+ @input_count = @inputs.length
69
+ elsif opts[:inputs].class == Fixnum
70
+ @input_count = opts[:inputs]
71
+ end
72
+ @inputs ||= @input_count.times.collect { Circuits::Terminal::Input.new }
73
+ end
74
+
75
+ def create_outputs(opts)
76
+ if opts[:outputs].class == Array
77
+ @outputs = opts[:outputs]
78
+ @output_count = @outputs.length
79
+ elsif opts[:outputs].class == Fixnum
80
+ @output_count = opts[:outputs]
81
+ end
82
+ @outputs ||= @output_count.times.collect do
83
+ Circuits::Terminal::Output.new
84
+ end
85
+ end
86
+
87
+ def port_mappings
88
+ return @port_mappings unless @port_mappings.nil?
89
+ @port_mappings = {}
90
+ input_mappings.each { |x| @port_mappings.merge!(x) }
91
+ output_mappings.each { |x| @port_mappings.merge!(x) }
92
+ @port_mappings
93
+ end
94
+
95
+ def input_mappings
96
+ return [{ in: { type: :input, number: 0 } }] if @input_count == 1
97
+ @input_count.times.collect do |i|
98
+ { num_to_port(i) => { type: :input, number: i } }
99
+ end
100
+ end
101
+
102
+ def output_mappings
103
+ return[{ out: { type: :output, number: 0 } }] if @output_count == 1
104
+ @output_count.times.collect do |i|
105
+ { num_to_port(i + @input_count) => { type: :output, number: i } }
106
+ end
107
+ end
108
+
109
+ def num_to_port(i)
110
+ (i + 'a'.ord).chr.to_sym
111
+ end
112
+ end
113
+ end
114
+ end
@@ -1,22 +1,19 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # Logical NAND Operator
6
- class Nand
7
- include Component
6
+ class Nand < Base
7
+ def initialize(opts = {})
8
+ @input_count = 2
9
+ @output_count = 1
10
+ super opts
11
+ end
8
12
 
9
13
  # Sets the output to be the result of a logical NAND of the inputs
10
14
  def tick
11
15
  outputs[0].set(!inputs.map(&:get).inject(:&))
12
16
  end
13
-
14
- private
15
-
16
- def set_defaults
17
- @input_count = 2
18
- @output_count = 1
19
- end
20
17
  end
21
18
  end
22
19
  end
@@ -1,22 +1,19 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # Logical NOR Operator
6
- class Nor
7
- include Component
6
+ class Nor < Base
7
+ def initialize(opts = {})
8
+ @input_count = 2
9
+ @output_count = 1
10
+ super opts
11
+ end
8
12
 
9
13
  # Sets the output to be the result of a logical OR of the inputs
10
14
  def tick
11
15
  outputs[0].set(!inputs.map(&:get).inject(:|))
12
16
  end
13
-
14
- private
15
-
16
- def set_defaults
17
- @input_count = 2
18
- @output_count = 1
19
- end
20
17
  end
21
18
  end
22
19
  end
@@ -1,22 +1,19 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # Logical NOT Operator
6
- class Not
7
- include Component
6
+ class Not < Base
7
+ def initialize(opts = {})
8
+ @input_count = 1
9
+ @output_count = 1
10
+ super opts
11
+ end
8
12
 
9
13
  # Sets the output to be the result of a logical NOT of the inputs
10
14
  def tick
11
15
  outputs[0].set(!inputs[0].get)
12
16
  end
13
-
14
- private
15
-
16
- def set_defaults
17
- @input_count = 1
18
- @output_count = 1
19
- end
20
17
  end
21
18
  end
22
19
  end
@@ -1,22 +1,19 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # Logical OR Operator
6
- class Or
7
- include Component
6
+ class Or < Base
7
+ def initialize(opts = {})
8
+ @input_count = 2
9
+ @output_count = 1
10
+ super opts
11
+ end
8
12
 
9
13
  # Sets the output to be the result of a logical OR of the inputs
10
14
  def tick
11
15
  outputs[0].set(inputs.map(&:get).inject(:|))
12
16
  end
13
-
14
- private
15
-
16
- def set_defaults
17
- @input_count = 2
18
- @output_count = 1
19
- end
20
17
  end
21
18
  end
22
19
  end
@@ -1,14 +1,19 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # SR NAND Latch
6
- class SrNand
7
- include Component
6
+ class SrNand < Base
7
+ def initialize(opts = {})
8
+ set_defaults
9
+ super opts
10
+ create_sub_components
11
+ link_sub_components
12
+ end
8
13
 
9
14
  # Computes the outputs based on the inputs and previous state
10
15
  def tick
11
- update_internal_components
16
+ update_sub_components
12
17
  self[:q].set nand_1[:out].get
13
18
  self[:not_q].set nand_2[:out].get
14
19
  end
@@ -17,13 +22,13 @@ module Circuits
17
22
 
18
23
  attr_reader :nand_1, :nand_2, :sub_components
19
24
 
20
- def create_internal_components
25
+ def create_sub_components
21
26
  @nand_1 = Nand.new
22
27
  @nand_2 = Nand.new
23
28
  @sub_components = [@nand_1, @nand_2]
24
29
  end
25
30
 
26
- def link_internal_components
31
+ def link_sub_components
27
32
  nand_1[:a] = self[:not_s]
28
33
  nand_2[:a] = self[:not_r]
29
34
  nand_1[:b] = nand_2[:out]
@@ -41,12 +46,7 @@ module Circuits
41
46
  }
42
47
  end
43
48
 
44
- def setup
45
- create_internal_components
46
- link_internal_components
47
- end
48
-
49
- def update_internal_components
49
+ def update_sub_components
50
50
  2.times.each do
51
51
  sub_components.each(&:tick)
52
52
  sub_components.each(&:tock)
@@ -1,10 +1,15 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # SR NOR Latch
6
- class SrNor
7
- include Component
6
+ class SrNor < Base
7
+ def initialize(opts = {})
8
+ set_defaults
9
+ super opts
10
+ create_internal_components
11
+ link_internal_components
12
+ end
8
13
 
9
14
  # Computes the outputs based on the inputs and previous state
10
15
  def tick
@@ -41,11 +46,6 @@ module Circuits
41
46
  }
42
47
  end
43
48
 
44
- def setup
45
- create_internal_components
46
- link_internal_components
47
- end
48
-
49
49
  def update_internal_components
50
50
  2.times.each do
51
51
  sub_components.each(&:tick)
@@ -1,22 +1,19 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # Logical XNOR Operator
6
- class Xnor
7
- include Component
6
+ class Xnor < Base
7
+ def initialize(opts = {})
8
+ @input_count = 2
9
+ @output_count = 1
10
+ super opts
11
+ end
8
12
 
9
13
  # Sets the output to be the result of a logical XNOR of the inputs
10
14
  def tick
11
15
  outputs[0].set(!inputs.map(&:get).inject(:^))
12
16
  end
13
-
14
- private
15
-
16
- def set_defaults
17
- @input_count = 2
18
- @output_count = 1
19
- end
20
17
  end
21
18
  end
22
19
  end
@@ -1,22 +1,19 @@
1
- require 'circuits/component'
1
+ require 'circuits/component/base'
2
2
 
3
3
  module Circuits
4
4
  module Component
5
5
  # Logical XOR Operator
6
- class Xor
7
- include Component
6
+ class Xor < Base
7
+ def initialize(opts = {})
8
+ @input_count = 2
9
+ @output_count = 1
10
+ super opts
11
+ end
8
12
 
9
13
  # Sets the output to be the result of a logical XOR of the inputs
10
14
  def tick
11
15
  outputs[0].set(inputs.map(&:get).inject(:^))
12
16
  end
13
-
14
- private
15
-
16
- def set_defaults
17
- @input_count = 2
18
- @output_count = 1
19
- end
20
17
  end
21
18
  end
22
19
  end
@@ -1,5 +1,5 @@
1
1
  # Circuits allows you to express logical circuits in code
2
2
  module Circuits
3
3
  # The version of the Circuits gem
4
- VERSION = '0.4.3'
4
+ VERSION = '0.5.0'
5
5
  end
@@ -1,114 +1,102 @@
1
- require 'spec_helper'
2
- require 'circuits/component'
3
-
4
- # Mock component to include Circuits::Component for function accessability
5
- class MockComponent1
6
- include Circuits::Component
7
-
8
- def set_defaults
9
- @input_count = 1
10
- @output_count = 1
11
- end
12
- end
13
-
14
- # Mock component to include Circuits::Component for function accessability
15
- class MockComponent2
16
- include Circuits::Component
17
- end
18
-
19
- describe Circuits::Component do
20
- context 'when using defaults' do
21
- subject { MockComponent1.new }
22
-
23
- it 'has one input' do
24
- expect(subject.inputs.count).to eq(1)
25
- end
26
-
27
- it 'has one output' do
28
- expect(subject.outputs.count).to eq(1)
29
- end
30
-
31
- describe '#[]=' do
32
- let(:new_input) { double('new_input') }
33
- let(:new_output) { double('new_output') }
34
-
35
- before do
36
- subject[:in] = new_input
37
- subject[:out] = new_output
38
- end
39
-
40
- it 'has the new input available as :in' do
41
- expect(subject[:in]).to eq(new_input)
42
- end
43
-
44
- it 'has the new output available as :out' do
45
- expect(subject[:out]).to eq(new_output)
46
- end
47
- end
48
- end
49
-
50
- context 'when specifying input and output count' do
51
- subject { MockComponent1.new(inputs: 2, outputs: 2) }
52
-
53
- it 'has one input' do
54
- expect(subject.inputs.count).to eq(2)
55
- end
56
-
57
- it 'has one output' do
58
- expect(subject.outputs.count).to eq(2)
59
- end
60
- end
61
-
62
- context 'when supplying inputs and outputs' do
63
- let(:inputs) { [double('input')] }
64
- let(:outputs) { [double('output')] }
65
-
66
- subject { MockComponent1.new(inputs: inputs, outputs: outputs) }
67
-
68
- describe '#tick' do
69
- it 'raises NotImplementedError' do
70
- expect { subject.tick }.to raise_error(NotImplementedError)
71
- end
72
- end
73
-
74
- describe '#tock' do
75
- it 'tocks the outputs' do
76
- expect(outputs[0]).to receive(:tock)
77
- subject.tock
78
- end
79
- end
80
-
81
- describe '#[]' do
82
- context 'one input and one output' do
83
- it 'has the input available as :in' do
84
- expect(subject[:in]).to eq(inputs[0])
85
- end
86
-
87
- it 'has the output available as :out' do
88
- expect(subject[:out]).to eq(outputs[0])
89
- end
90
- end
91
-
92
- context 'two inputs and two outputs' do
93
- let(:inputs) { [double('input_1'), double('input_2')] }
94
- let(:outputs) { [double('output_1'), double('output_2')] }
95
-
96
- it 'has the inputs available as :a and :b' do
97
- expect(subject[:a]).to eq(inputs[0])
98
- expect(subject[:b]).to eq(inputs[1])
99
- end
100
-
101
- it 'has the outputs available as :c and :d' do
102
- expect(subject[:c]).to eq(outputs[0])
103
- expect(subject[:d]).to eq(outputs[1])
104
- end
105
- end
106
- end
107
- end
108
-
109
- context 'when you do not override #set_defaults' do
110
- it 'raises NotImplementedError' do
111
- expect { MockComponent2.new }.to raise_error(NotImplementedError)
112
- end
113
- end
114
- end
1
+ require 'spec_helper'
2
+ require 'circuits/component/base'
3
+
4
+ # Mock component to include Circuits::Component::Base
5
+ class MockComponent < Circuits::Component::Base
6
+ def initialize(opts = {})
7
+ @input_count = 1
8
+ @output_count = 1
9
+ super opts
10
+ end
11
+ end
12
+
13
+ describe Circuits::Component::Base do
14
+ context 'when using defaults' do
15
+ subject { MockComponent.new }
16
+
17
+ it 'has one input' do
18
+ expect(subject.inputs.count).to eq(1)
19
+ end
20
+
21
+ it 'has one output' do
22
+ expect(subject.outputs.count).to eq(1)
23
+ end
24
+
25
+ describe '#[]=' do
26
+ let(:new_input) { double('new_input') }
27
+ let(:new_output) { double('new_output') }
28
+
29
+ before do
30
+ subject[:in] = new_input
31
+ subject[:out] = new_output
32
+ end
33
+
34
+ it 'has the new input available as :in' do
35
+ expect(subject[:in]).to eq(new_input)
36
+ end
37
+
38
+ it 'has the new output available as :out' do
39
+ expect(subject[:out]).to eq(new_output)
40
+ end
41
+ end
42
+ end
43
+
44
+ context 'when specifying input and output count' do
45
+ subject { MockComponent.new(inputs: 2, outputs: 2) }
46
+
47
+ it 'has one input' do
48
+ expect(subject.inputs.count).to eq(2)
49
+ end
50
+
51
+ it 'has one output' do
52
+ expect(subject.outputs.count).to eq(2)
53
+ end
54
+ end
55
+
56
+ context 'when supplying inputs and outputs' do
57
+ let(:inputs) { [double('input')] }
58
+ let(:outputs) { [double('output')] }
59
+
60
+ subject { MockComponent.new(inputs: inputs, outputs: outputs) }
61
+
62
+ describe '#tick' do
63
+ it 'raises NotImplementedError' do
64
+ expect { subject.tick }.to raise_error(NotImplementedError)
65
+ end
66
+ end
67
+
68
+ describe '#tock' do
69
+ it 'tocks the outputs' do
70
+ expect(outputs[0]).to receive(:tock)
71
+ subject.tock
72
+ end
73
+ end
74
+
75
+ describe '#[]' do
76
+ context 'one input and one output' do
77
+ it 'has the input available as :in' do
78
+ expect(subject[:in]).to eq(inputs[0])
79
+ end
80
+
81
+ it 'has the output available as :out' do
82
+ expect(subject[:out]).to eq(outputs[0])
83
+ end
84
+ end
85
+
86
+ context 'two inputs and two outputs' do
87
+ let(:inputs) { [double('input_1'), double('input_2')] }
88
+ let(:outputs) { [double('output_1'), double('output_2')] }
89
+
90
+ it 'has the inputs available as :a and :b' do
91
+ expect(subject[:a]).to eq(inputs[0])
92
+ expect(subject[:b]).to eq(inputs[1])
93
+ end
94
+
95
+ it 'has the outputs available as :c and :d' do
96
+ expect(subject[:c]).to eq(outputs[0])
97
+ expect(subject[:d]).to eq(outputs[1])
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: circuits
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.3
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Henry Muru Paenga
@@ -124,8 +124,8 @@ files:
124
124
  - Rakefile
125
125
  - circuits.gemspec
126
126
  - lib/circuits.rb
127
- - lib/circuits/component.rb
128
127
  - lib/circuits/component/and.rb
128
+ - lib/circuits/component/base.rb
129
129
  - lib/circuits/component/nand.rb
130
130
  - lib/circuits/component/nor.rb
131
131
  - lib/circuits/component/not.rb
@@ -140,6 +140,7 @@ files:
140
140
  - lib/circuits/version.rb
141
141
  - spec/spec_helper.rb
142
142
  - spec/unit/circuits/component/and_spec.rb
143
+ - spec/unit/circuits/component/base_spec.rb
143
144
  - spec/unit/circuits/component/nand_spec.rb
144
145
  - spec/unit/circuits/component/nor_spec.rb
145
146
  - spec/unit/circuits/component/not_spec.rb
@@ -148,7 +149,6 @@ files:
148
149
  - spec/unit/circuits/component/sr_nor_spec.rb
149
150
  - spec/unit/circuits/component/xnor_spec.rb
150
151
  - spec/unit/circuits/component/xor_spec.rb
151
- - spec/unit/circuits/component_spec.rb
152
152
  - spec/unit/circuits/terminal/input_spec.rb
153
153
  - spec/unit/circuits/terminal/output_spec.rb
154
154
  homepage: https://github.com/meringu/circuits
@@ -178,6 +178,7 @@ summary: Express logical circuits in code
178
178
  test_files:
179
179
  - spec/spec_helper.rb
180
180
  - spec/unit/circuits/component/and_spec.rb
181
+ - spec/unit/circuits/component/base_spec.rb
181
182
  - spec/unit/circuits/component/nand_spec.rb
182
183
  - spec/unit/circuits/component/nor_spec.rb
183
184
  - spec/unit/circuits/component/not_spec.rb
@@ -186,6 +187,5 @@ test_files:
186
187
  - spec/unit/circuits/component/sr_nor_spec.rb
187
188
  - spec/unit/circuits/component/xnor_spec.rb
188
189
  - spec/unit/circuits/component/xor_spec.rb
189
- - spec/unit/circuits/component_spec.rb
190
190
  - spec/unit/circuits/terminal/input_spec.rb
191
191
  - spec/unit/circuits/terminal/output_spec.rb
@@ -1,121 +0,0 @@
1
- require 'circuits/terminal/input'
2
- require 'circuits/terminal/output'
3
-
4
- module Circuits
5
- # A component has a set of inputs an outputs. Every `tick` a componnent
6
- # computes its outputs, but the componnent will wait for the `tock` before the
7
- # componnent updates its own outputs
8
- module Component
9
- # Creates the Component with inputs and outputs
10
- # @param opts [Hash] options to create the Component with
11
- # @option opts [Array<Input>, FixNum] :inputs The array of inputs to use, or
12
- # the number of inputs to create
13
- def initialize(opts = {})
14
- set_defaults
15
- create_inputs opts
16
- create_outputs opts
17
- create_port_mappings
18
- setup
19
- end
20
-
21
- # Does the internal computation and sets the outputs
22
- def tick
23
- fail NotImplementedError
24
- end
25
-
26
- # Sets all the outputs expose what was set in #tick
27
- def tock
28
- outputs.each(&:tock)
29
- end
30
-
31
- # Gets the teminal assigned to the port
32
- # @param port [Symbol] The symbol that represents the terminal
33
- # @return [Input, Output] The terminal
34
- def [](port)
35
- p = @port_mappings[port]
36
- case p[:type]
37
- when :input
38
- @inputs[p[:number]]
39
- when :output
40
- @outputs[p[:number]]
41
- end
42
- end
43
-
44
- # Assigns to an input or output
45
- # @param port [Symbol] The symbol that represents the terminal
46
- # @param terminal [Input, Output] The terminal to assign
47
- # @return [Input, Output] The terminal that was passed in
48
- def []=(port, terminal)
49
- p = @port_mappings[port]
50
- case p[:type]
51
- when :input
52
- @inputs[p[:number]] = terminal
53
- when :output
54
- @outputs[p[:number]] = terminal
55
- end
56
- end
57
-
58
- # the inputs of this component
59
- attr_reader :inputs
60
-
61
- # the outputs of this component
62
- attr_reader :outputs
63
-
64
- private
65
-
66
- def create_inputs(opts)
67
- if opts[:inputs].class == Array
68
- @inputs = opts[:inputs]
69
- @input_count = @inputs.length
70
- elsif opts[:inputs].class == Fixnum
71
- @input_count = opts[:inputs]
72
- end
73
- @inputs ||= @input_count.times.collect { Circuits::Terminal::Input.new }
74
- end
75
-
76
- def create_outputs(opts)
77
- if opts[:outputs].class == Array
78
- @outputs = opts[:outputs]
79
- @output_count = @outputs.length
80
- elsif opts[:outputs].class == Fixnum
81
- @output_count = opts[:outputs]
82
- end
83
- @outputs ||= @output_count.times.collect do
84
- Circuits::Terminal::Output.new
85
- end
86
- end
87
-
88
- def create_port_mappings
89
- return @port_mappings unless @port_mappings.nil?
90
- @port_mappings = {}
91
- input_mappings.each { |x| @port_mappings.merge!(x) }
92
- output_mappings.each { |x| @port_mappings.merge!(x) }
93
- @port_mappings
94
- end
95
-
96
- def input_mappings
97
- return [{ in: { type: :input, number: 0 } }] if @input_count == 1
98
- @input_count.times.collect do |i|
99
- { num_to_port(i) => { type: :input, number: i } }
100
- end
101
- end
102
-
103
- def output_mappings
104
- return[{ out: { type: :output, number: 0 } }] if @output_count == 1
105
- @output_count.times.collect do |i|
106
- { num_to_port(i + @input_count) => { type: :output, number: i } }
107
- end
108
- end
109
-
110
- def num_to_port(i)
111
- (i + 'a'.ord).chr.to_sym
112
- end
113
-
114
- def set_defaults
115
- fail NotImplementedError
116
- end
117
-
118
- def setup
119
- end
120
- end
121
- end