BBB 0.0.10 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. data/lib/BBB.rb +13 -17
  2. data/lib/BBB/application.rb +4 -21
  3. data/lib/BBB/circuit.rb +18 -33
  4. data/lib/BBB/components/analog_component.rb +29 -6
  5. data/lib/BBB/components/led.rb +39 -9
  6. data/lib/BBB/components/pinnable.rb +90 -4
  7. data/lib/BBB/components/servo.rb +43 -0
  8. data/lib/BBB/pins/analog_pin.rb +39 -0
  9. data/lib/BBB/pins/digital_pin.rb +106 -0
  10. data/lib/BBB/pins/io/ain.rb +58 -0
  11. data/lib/BBB/pins/io/gpio.rb +77 -0
  12. data/lib/BBB/pins/io/mapped.rb +39 -0
  13. data/lib/BBB/pins/io/pin_mapper.rb +224 -0
  14. data/lib/BBB/pins/io/pwm.rb +61 -0
  15. data/lib/BBB/pins/pinnable.rb +78 -0
  16. data/lib/BBB/pins/pwm_pin.rb +43 -0
  17. data/lib/BBB/version.rb +1 -1
  18. data/spec/application_spec.rb +1 -26
  19. data/spec/circuit_spec.rb +0 -1
  20. data/spec/components/analog_component_spec.rb +36 -0
  21. data/spec/components/led_spec.rb +14 -19
  22. data/spec/components/pinnable_spec.rb +73 -8
  23. data/spec/components/servo_spec.rb +6 -0
  24. data/spec/pins/analog_pin_spec.rb +33 -0
  25. data/spec/pins/digital_input_pin_spec.rb +13 -0
  26. data/spec/pins/digital_output_pin_spec.rb +14 -0
  27. data/spec/pins/digital_pin_spec.rb +66 -0
  28. data/spec/pins/io/mapped_spec.rb +41 -0
  29. data/spec/{board → pins/io}/pin_mapper_spec.rb +2 -2
  30. data/spec/pins/pinnable_spec.rb +68 -0
  31. data/spec/pins/pwm_pin_spec.rb +29 -0
  32. metadata +34 -37
  33. data/lib/BBB/adc/analog_pin.rb +0 -42
  34. data/lib/BBB/adc/setup.rb +0 -20
  35. data/lib/BBB/board/base.rb +0 -45
  36. data/lib/BBB/board/json_pin_mapper.rb +0 -203
  37. data/lib/BBB/board/pin_mapper.rb +0 -20
  38. data/lib/BBB/board/test_board.rb +0 -12
  39. data/lib/BBB/gpio/base.rb +0 -56
  40. data/lib/BBB/gpio/digital_pin.rb +0 -69
  41. data/lib/BBB/gpio/pin_converter.rb +0 -28
  42. data/lib/BBB/io/analog_pin.rb +0 -24
  43. data/lib/BBB/io/digital_pin.rb +0 -67
  44. data/lib/BBB/io/mock_pin.rb +0 -8
  45. data/lib/BBB/io/pinnable.rb +0 -12
  46. data/spec/adc/analog_pin_spec.rb +0 -100
  47. data/spec/adc/setup_spec.rb +0 -9
  48. data/spec/board/board_spec.rb +0 -49
  49. data/spec/gpio/base_spec.rb +0 -48
  50. data/spec/gpio/digital_pin_spec.rb +0 -100
  51. data/spec/gpio/pin_converter_spec.rb +0 -19
  52. data/spec/io/digital_pin_spec.rb +0 -14
  53. data/spec/io/mock_pin_spec.rb +0 -13
  54. data/spec/io/pinnable_spec.rb +0 -13
data/lib/BBB.rb CHANGED
@@ -1,30 +1,26 @@
1
- require "BBB/version"
2
-
3
1
  require "json"
2
+ require "stringio"
4
3
 
5
- require "BBB/board/base"
6
- require "BBB/board/test_board"
7
- require "BBB/board/json_pin_mapper"
8
- require "BBB/board/pin_mapper"
4
+ require "BBB/version"
9
5
 
10
6
  require "BBB/circuit"
11
7
  require "BBB/exceptions"
12
8
 
13
- require "BBB/gpio/base"
14
- require "BBB/gpio/digital_pin"
15
- require "BBB/gpio/pin_converter"
9
+ require "BBB/pins/io/pin_mapper"
10
+ require "BBB/pins/io/mapped"
11
+ require "BBB/pins/io/ain"
12
+ require "BBB/pins/io/gpio"
13
+ require "BBB/pins/io/pwm"
16
14
 
17
- require "BBB/adc/setup"
18
- require "BBB/adc/analog_pin"
19
-
20
- require "BBB/io/pinnable"
21
- require "BBB/io/digital_pin"
22
- require "BBB/io/analog_pin"
23
- require "BBB/io/mock_pin"
15
+ require "BBB/pins/pinnable"
16
+ require "BBB/pins/digital_pin"
17
+ require "BBB/pins/analog_pin"
18
+ require "BBB/pins/pwm_pin"
24
19
 
25
20
  require "BBB/components/pinnable"
26
- require "BBB/components/led"
27
21
  require "BBB/components/analog_component"
22
+ require "BBB/components/led"
23
+ require "BBB/components/servo"
28
24
 
29
25
  require "BBB/application"
30
26
 
@@ -1,42 +1,25 @@
1
1
  module BBB
2
2
  class Application
3
3
 
4
- def self.board(board)
5
- @_board = board
6
- connect unless @_circuit.nil?
7
- end
8
-
9
4
  def self.circuit(circuit)
10
5
  @_circuit = circuit
11
- connect unless @_board.nil?
12
- end
13
-
14
- def self._board
15
- @_board
6
+ define_convenience_methods(circuit)
16
7
  end
17
8
 
18
9
  def self._circuit
19
10
  @_circuit
20
11
  end
21
12
 
22
- def self.connect
23
- @_circuit.components.each_pair do |name, component|
24
- component.pins.each do |pin|
25
- @_board.connect_io_pin(pin)
26
- end
27
-
13
+ def self.define_convenience_methods(c)
14
+ c.components.keys.each do |name|
28
15
  define_method(name) do
29
16
  circuit.send(name)
30
17
  end
31
18
  end
32
19
  end
33
20
 
34
- def board
35
- @board ||= self.class._board
36
- end
37
-
38
21
  def circuit
39
- @circuit ||= self.class._circuit
22
+ self.class._circuit
40
23
  end
41
24
 
42
25
  def start
data/lib/BBB/circuit.rb CHANGED
@@ -1,56 +1,49 @@
1
1
  module BBB
2
2
  ##
3
- # The idea here is to attach a piece of equipment to a circuit. The circuit
4
- # will later be connected to a board.
3
+ # The idea here is to attach a piece of equipment to a circuit.
5
4
  #
6
5
  # A component (e.g. Led or Servo) will define generic pins, like
7
- # DigitalInput or AnalogOutput. And then, when the circuit gets attached to
8
- # the board those pins will be "connected" to their "physical" counterparts
9
- # on the board.
10
- #
11
- # This allows you to develop generic circuits that can be attached to any
12
- # board. At least, in theory :-)
6
+ # DigitalInput or AnalogOutput. And then, when the component gets attached to
7
+ # the circuit those pins will be initialized using the file system.
13
8
  #
14
9
  # For now the attachment will be made onto specific pin numbers. For the BBB
15
10
  # this might for example be :P8_3, however, the plan is to, in a future
16
11
  # release, make sure that there are converters between the different kind of
17
12
  # boards. For example by mapping P8_3 on BBB to P1 on an Arduino.
18
13
  #
19
- # As of now, the act of "attaching" something onto the circuit equals
20
- # setting up a component with generic pins.
21
- #
22
14
  class Circuit
23
- attr_reader :components
15
+ attr_reader :components, :mock
24
16
 
25
17
  def components
26
18
  @components ||= {}
27
19
  end
28
20
 
21
+ def mock?
22
+ @mock == true
23
+ end
24
+
29
25
  ##
30
26
  # Attach a component of a certain type to the circuit
31
27
  #
32
28
  # @param component [Class] The class of the object you # want to attach.
33
29
  # @param opts [Hash] Hash of options that setup the component
34
30
  #
31
+ # @option opts [Symbol] :pin The pin position for the component
35
32
  # @option opts [Array<Symbol>] :pins The list of pin numbers used on the
36
- # circuit.
33
+ # circuit.
34
+ # @options opts [Symbol] :as The name of the component
37
35
  #
38
36
  def attach(component, opts={})
39
- if component.kind_of?(Class)
40
- component = component.new
41
- end
37
+ name = opts.delete(:as)
38
+ component = component.new if component.kind_of?(Class)
39
+ pin_positions = opts.delete(:pins) || [opts.delete(:pin)]
40
+ pin_options = {:mock=>self.mock?}.merge!(opts)
42
41
 
43
- if pin_positions = opts[:pins] || [opts[:pin]]
44
- component_pins = component.pins
45
- verify_pin_argument_count(component_pins.count, pin_positions.count)
46
- component.register_pin_positions(pin_positions)
47
- end
48
-
49
- name = opts.fetch(:as)
50
- register_component(component, name)
42
+ component.initialize_pins(pin_positions, pin_options)
43
+ define_method_for_component(component, name)
51
44
  end
52
45
 
53
- def register_component(component, name)
46
+ def define_method_for_component(component, name)
54
47
  components[name] = component
55
48
  eigenclass = class << self; self; end
56
49
  eigenclass.class_eval do
@@ -60,13 +53,5 @@ module BBB
60
53
  end
61
54
  end
62
55
 
63
- def verify_pin_argument_count(type_count, position_count)
64
- if type_count != position_count
65
- raise PinsDoNotMatchException,
66
- "#{object.to_s} requires #{types_count} but received #{position_count} pin arguments."
67
- end
68
- end
69
-
70
-
71
56
  end
72
57
  end
@@ -1,22 +1,45 @@
1
1
  module BBB
2
2
  module Components
3
+ ##
4
+ # An AnalogComponent is a component that reads from an analog input (AIN) on
5
+ # the board. You can use a generic analog component for, for example,
6
+ # temperature or light sensors.
7
+ #
8
+ # The BeagleBoneBlack has 12 bit (4096) AIN pins. So the expected value of
9
+ # an analog pin is between 0 and 4096.
10
+ #
3
11
  class AnalogComponent
4
12
  include Pinnable
5
13
 
6
- attr_reader :pin, :pins
7
-
8
- def initialize
9
- @pin = BBB::IO::AnalogPin.new
10
- @pins = [@pin]
11
- end
14
+ uses BBB::Pins::AnalogPin
12
15
 
16
+ ##
17
+ # Read from an initialized pin, if the pins have not been initialized yet,
18
+ # this method might actually raise an exception.
19
+ #
20
+ # @raise MethodNotFoundException
21
+ #
22
+ # @return Integer
23
+ #
13
24
  def read
14
25
  pin.read
15
26
  end
16
27
 
28
+ ##
29
+ # @see #read
30
+ #
17
31
  def value
18
32
  read
19
33
  end
34
+
35
+ ##
36
+ # Convenience method to grab the first pin in the pins array
37
+ #
38
+ # @return BBB::Pins::AnalogPin
39
+ #
40
+ def pin
41
+ pins.first
42
+ end
20
43
  end
21
44
  end
22
45
  end
@@ -1,31 +1,61 @@
1
1
  module BBB
2
2
  module Components
3
+ ##
4
+ # The LED class is the component interface into a digital pin. In a way it's
5
+ # nothing more than a straight forward port of a digital pin. You can use a
6
+ # led component when you want to use digital pins, or simply define your own
7
+ # class and extend it from the LED.
8
+ #
9
+ # The Led class does not perform any sort of caching or smart calls, it
10
+ # forwards everything to the pin. In your own applications you might want to
11
+ # tune this behavior by adding some kind of caching.
12
+ #
3
13
  class Led
4
14
  include Pinnable
5
- attr_reader :state, :pin
6
15
 
7
- def initialize
8
- @state = :low
9
- @pin = BBB::IO::DigitalPin.new(:output)
10
- @pins = [@pin]
16
+ uses BBB::Pins::DigitalOutputPin
17
+
18
+ ##
19
+ # Convenience method to grab the first pin in the pins array
20
+ #
21
+ # @return BBB::Pins::DigitalOutputPin
22
+ #
23
+ def pin
24
+ pins.first
11
25
  end
12
26
 
27
+ ##
28
+ # Turns on the LED
29
+ # @return void
30
+ #
13
31
  def on!
14
32
  pin.on!
15
- @state = :high
16
33
  end
17
34
 
35
+ ##
36
+ # Turns off the LED
37
+ # @return void
38
+ #
18
39
  def off!
19
40
  pin.off!
20
- @state = :low
21
41
  end
22
42
 
43
+ ##
44
+ # Checks if the LED is turned on.
45
+ #
46
+ # @return Boolean
47
+ #
23
48
  def on?
24
- state == :high
49
+ pin.on?
25
50
  end
26
51
 
52
+ ##
53
+ # Checks if the LED is turned off.
54
+ #
55
+ # @return Boolean
56
+ #
27
57
  def off?
28
- state == :low
58
+ pin.off?
29
59
  end
30
60
 
31
61
  end
@@ -3,13 +3,99 @@ module BBB
3
3
  module Pinnable
4
4
  attr_reader :pins
5
5
 
6
- def register_pin_positions(*positions)
7
- positions.flatten!
8
- pins.each_with_index do |pin, index|
9
- pin.position=positions[index]
6
+ module ClassMethods
7
+ ##
8
+ # Register the use of classes of pins to a class. These classes will be
9
+ # initialized upon #initialize_pins
10
+ #
11
+ # @param pin_classes [Array<Class>] the classes to register on class
12
+ # level.
13
+ #
14
+ def uses(*pin_classes)
15
+ pins.concat(pin_classes)
10
16
  end
17
+
18
+ ##
19
+ # Attribute reader to the class level @pins
20
+ #
21
+ # @return Array<Class>
22
+ #
23
+ def pins
24
+ @pins ||= []
25
+ end
26
+ end
27
+
28
+ def self.included(base)
29
+ base.extend(ClassMethods)
11
30
  end
12
31
 
32
+ ##
33
+ # Initialize the pin classes with their positions and options. Turning
34
+ # them from their Classes into working pin instances.
35
+ #
36
+ # The argument list of the methods is a bit odd. Since it's not
37
+ # possible to have both a splat and an option array as arguments, the
38
+ # method signature only shows a splat of positions. The options are then
39
+ # taken out of the positions, if the last position is actually a Hash as
40
+ # opposed to a Symbol. If the last element of the positions list is not
41
+ # a Hash, the options are set to an empty hash.
42
+ #
43
+ # @param positions [Array<Symbol>] positions the pins should be
44
+ # initialized with.
45
+ # @param opts [Hash] Options to pass along to the pins during
46
+ # initialization.
47
+ #
48
+ # @return Array[Pins]
49
+ #
50
+ def initialize_pins(*positions)
51
+ opts = positions.last.kind_of?(Hash) ? positions.pop : {}
52
+
53
+ verify_pin_position_count(positions)
54
+
55
+ @pins = []
56
+ self.class.pins.each_with_index do |pin, index|
57
+ @pins << pin.new(positions[index], opts)
58
+ end
59
+ after_pin_initialization
60
+ end
61
+
62
+ ##
63
+ # Verifies if the number of pins registered in the @pins array match with
64
+ # the number of pins provided as an argument to the method. This function
65
+ # normally gets called as part of the initialize pins method to verify if
66
+ # the positions given to the initialize_pins method matches the number of
67
+ # registered pins.
68
+ #
69
+ # @param positions [Array<Symbol>] The array of positions
70
+ #
71
+ # @raise [PinsDoNotMatchException] If the pin counts between the positions
72
+ # provided as an argument and the pins in the pins array do not match,
73
+ # this exception gets raised, to prevent hard to debug situations later
74
+ # on in the lifecycle of an application.
75
+ #
76
+ # @return Void
77
+ def verify_pin_position_count(positions)
78
+ if self.class.pins.count != positions.count
79
+ raise PinsDoNotMatchException,
80
+ "#{self.class.to_s} requires #{self.class.pins.count} but received #{positions.count} pin position."
81
+ end
82
+ end
83
+
84
+ ##
85
+ # Method which classes can overwrite to hook into the after pin
86
+ # initialization
87
+ #
88
+ def after_pin_initialization
89
+ end
90
+
91
+ ##
92
+ # Method that is used in the test suite to test if the pinnable module is
93
+ # included in an object
94
+ #
95
+ # @return true
96
+ def pinnable?
97
+ true
98
+ end
13
99
  end
14
100
  end
15
101
  end
@@ -0,0 +1,43 @@
1
+ module BBB
2
+ module Components
3
+ class Servo
4
+ include Pinnable
5
+ #uses Pins::PWMPin
6
+ attr_reader :min_duty, :max_duty, :period
7
+
8
+ def initialize(period=17e6, min_duty=14.6e6, max_duty=16.6e6)
9
+ @period = period
10
+ @min_duty = min_duty
11
+ @max_duty = max_duty
12
+ end
13
+
14
+ def after_pin_initialization
15
+ pin.period = 17e6
16
+ pin.duty = (min_duty + duty_range / 2)
17
+ pin.run = 0
18
+ end
19
+
20
+ def angle(degrees)
21
+ value = degrees / 180.to_f * duty_range + min_duty
22
+ pin.duty = value
23
+ end
24
+
25
+ def activate!
26
+ pin.run = 1
27
+ end
28
+
29
+ def deactivate!
30
+ pin.run = 0
31
+ end
32
+
33
+ def pin
34
+ pins.first
35
+ end
36
+
37
+ def duty_range
38
+ max_duty - min_duty
39
+ end
40
+
41
+ end
42
+ end
43
+ end