BBB 0.0.10 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/BBB.rb +13 -17
- data/lib/BBB/application.rb +4 -21
- data/lib/BBB/circuit.rb +18 -33
- data/lib/BBB/components/analog_component.rb +29 -6
- data/lib/BBB/components/led.rb +39 -9
- data/lib/BBB/components/pinnable.rb +90 -4
- data/lib/BBB/components/servo.rb +43 -0
- data/lib/BBB/pins/analog_pin.rb +39 -0
- data/lib/BBB/pins/digital_pin.rb +106 -0
- data/lib/BBB/pins/io/ain.rb +58 -0
- data/lib/BBB/pins/io/gpio.rb +77 -0
- data/lib/BBB/pins/io/mapped.rb +39 -0
- data/lib/BBB/pins/io/pin_mapper.rb +224 -0
- data/lib/BBB/pins/io/pwm.rb +61 -0
- data/lib/BBB/pins/pinnable.rb +78 -0
- data/lib/BBB/pins/pwm_pin.rb +43 -0
- data/lib/BBB/version.rb +1 -1
- data/spec/application_spec.rb +1 -26
- data/spec/circuit_spec.rb +0 -1
- data/spec/components/analog_component_spec.rb +36 -0
- data/spec/components/led_spec.rb +14 -19
- data/spec/components/pinnable_spec.rb +73 -8
- data/spec/components/servo_spec.rb +6 -0
- data/spec/pins/analog_pin_spec.rb +33 -0
- data/spec/pins/digital_input_pin_spec.rb +13 -0
- data/spec/pins/digital_output_pin_spec.rb +14 -0
- data/spec/pins/digital_pin_spec.rb +66 -0
- data/spec/pins/io/mapped_spec.rb +41 -0
- data/spec/{board → pins/io}/pin_mapper_spec.rb +2 -2
- data/spec/pins/pinnable_spec.rb +68 -0
- data/spec/pins/pwm_pin_spec.rb +29 -0
- metadata +34 -37
- data/lib/BBB/adc/analog_pin.rb +0 -42
- data/lib/BBB/adc/setup.rb +0 -20
- data/lib/BBB/board/base.rb +0 -45
- data/lib/BBB/board/json_pin_mapper.rb +0 -203
- data/lib/BBB/board/pin_mapper.rb +0 -20
- data/lib/BBB/board/test_board.rb +0 -12
- data/lib/BBB/gpio/base.rb +0 -56
- data/lib/BBB/gpio/digital_pin.rb +0 -69
- data/lib/BBB/gpio/pin_converter.rb +0 -28
- data/lib/BBB/io/analog_pin.rb +0 -24
- data/lib/BBB/io/digital_pin.rb +0 -67
- data/lib/BBB/io/mock_pin.rb +0 -8
- data/lib/BBB/io/pinnable.rb +0 -12
- data/spec/adc/analog_pin_spec.rb +0 -100
- data/spec/adc/setup_spec.rb +0 -9
- data/spec/board/board_spec.rb +0 -49
- data/spec/gpio/base_spec.rb +0 -48
- data/spec/gpio/digital_pin_spec.rb +0 -100
- data/spec/gpio/pin_converter_spec.rb +0 -19
- data/spec/io/digital_pin_spec.rb +0 -14
- data/spec/io/mock_pin_spec.rb +0 -13
- data/spec/io/pinnable_spec.rb +0 -13
@@ -0,0 +1,61 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
module IO
|
4
|
+
class PWM
|
5
|
+
include Mapped
|
6
|
+
|
7
|
+
attr_reader :handles, :position
|
8
|
+
|
9
|
+
def initialize(position)
|
10
|
+
@position = position
|
11
|
+
self.export
|
12
|
+
@handles = get_file_handles
|
13
|
+
end
|
14
|
+
|
15
|
+
def path
|
16
|
+
return @path unless @path.nil?
|
17
|
+
@path = Dir.glob("/sys/devices/ocp.*/pwm_test_#{pin_map.key}.*").first
|
18
|
+
end
|
19
|
+
|
20
|
+
def get_file_handles
|
21
|
+
handles = {}
|
22
|
+
files = %w(duty period polarity run)
|
23
|
+
|
24
|
+
files.each do |file|
|
25
|
+
file_path = File.expand_path(file, path)
|
26
|
+
handles[file.to_sym] = File.open(file_path, "r+")
|
27
|
+
end
|
28
|
+
|
29
|
+
return handles
|
30
|
+
end
|
31
|
+
|
32
|
+
def export
|
33
|
+
cape_dir = "/sys/devices/bone_capemgr.*/slots"
|
34
|
+
dir = Dir.glob(cape_dir)
|
35
|
+
if dir.length == 0
|
36
|
+
raise BoardError, "unable to access the capemgr directory: #{cape_dir}"
|
37
|
+
end
|
38
|
+
|
39
|
+
pin_map_key = pin_map.key # This calls the pin map, which raises an error in case pin can't be mapped.
|
40
|
+
system("echo am33xx_pwm > #{dir.first}")
|
41
|
+
system("echo bone_pwm_#{pin_map_key} > #{dir.first}")
|
42
|
+
end
|
43
|
+
|
44
|
+
def write(symbol, value)
|
45
|
+
handle = handles[symbol]
|
46
|
+
handle.rewind
|
47
|
+
handle.write(value)
|
48
|
+
handle.flush
|
49
|
+
return value
|
50
|
+
end
|
51
|
+
|
52
|
+
def read(symbol)
|
53
|
+
handle = handles[symbol]
|
54
|
+
handle.rewind
|
55
|
+
handle.read.to_i
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
##
|
4
|
+
# Module which is included in all pins. The module provides the basic
|
5
|
+
# interface for a BBB::Pin and also takes care of selecting the right IO
|
6
|
+
# class to work with.
|
7
|
+
#
|
8
|
+
# It defines a #pinnable? method to test if the module is properly included
|
9
|
+
# in a pin.
|
10
|
+
#
|
11
|
+
module Pinnable
|
12
|
+
attr_reader :position, :opts
|
13
|
+
|
14
|
+
##
|
15
|
+
# Initializes a Pin
|
16
|
+
#
|
17
|
+
# @param position [Symbol] The position of the pin
|
18
|
+
# @option opts [Boolean] :mock whether or not to use MockIO
|
19
|
+
#
|
20
|
+
def initialize(position, opts={})
|
21
|
+
@position = position
|
22
|
+
@opts = opts
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Returns an instance of the IO class for the pin and memoizes this.
|
27
|
+
#
|
28
|
+
# @return [IO]
|
29
|
+
#
|
30
|
+
def io
|
31
|
+
@io ||= mock? ? mock_io : default_io
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Return wheter or not this is a mock pin
|
36
|
+
#
|
37
|
+
# @return [Boolean]
|
38
|
+
#
|
39
|
+
def mock?
|
40
|
+
@mock ||= @opts.fetch(:mock, false)
|
41
|
+
end
|
42
|
+
|
43
|
+
##
|
44
|
+
# Always returns true, method is used to test if module is included.
|
45
|
+
#
|
46
|
+
# @return [Boolean] true
|
47
|
+
#
|
48
|
+
def pinnable?
|
49
|
+
true
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
##
|
55
|
+
# If a class includes the Pinnable module, it should overwrite the
|
56
|
+
# default_io method. If this is not done, the module raises an error to
|
57
|
+
# point the developer into the right direction.
|
58
|
+
#
|
59
|
+
# The default_io method should return an instantiated object that makes
|
60
|
+
# the inteface between the filesystem, drivers etc, and the ruby code.
|
61
|
+
# Probably the object will behave like an IO object, relying on the linux
|
62
|
+
# kernel and drivers to get things done on the board.
|
63
|
+
#
|
64
|
+
def default_io
|
65
|
+
raise NotImplementedError
|
66
|
+
end
|
67
|
+
|
68
|
+
##
|
69
|
+
# The IO instance used for mock pins. By default this is StringIO.new,
|
70
|
+
# however, each class should determine if it defines its own MockIO class.
|
71
|
+
# An example of which can be found at the PWMPin.
|
72
|
+
#
|
73
|
+
def mock_io
|
74
|
+
StringIO.new
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
class PWMPin
|
4
|
+
include Pinnable
|
5
|
+
|
6
|
+
%w(duty polarity period run).each do |method|
|
7
|
+
define_method("#{method}=".to_sym) do |value|
|
8
|
+
io.write(method.to_sym, value.to_i)
|
9
|
+
end
|
10
|
+
|
11
|
+
define_method(method.to_sym) do
|
12
|
+
io.read(method.to_sym)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def period_hz(herz)
|
17
|
+
self.period = 1/herz*10e9
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def default_io
|
23
|
+
IO::PWM.new(position)
|
24
|
+
end
|
25
|
+
|
26
|
+
class MockIO < StringIO
|
27
|
+
def write(symbol, value)
|
28
|
+
super(value)
|
29
|
+
end
|
30
|
+
|
31
|
+
def read(symbol)
|
32
|
+
rewind
|
33
|
+
super().to_i
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def mock_io
|
38
|
+
MockIO.new
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
data/lib/BBB/version.rb
CHANGED
data/spec/application_spec.rb
CHANGED
@@ -6,29 +6,6 @@ describe BBB::Application do
|
|
6
6
|
lambda { BBB::Application.new }.should_not raise_exception
|
7
7
|
end
|
8
8
|
|
9
|
-
class MockCircuit
|
10
|
-
def components; {}; end
|
11
|
-
end
|
12
|
-
|
13
|
-
class TestBoardApp < BBB::Application
|
14
|
-
board "board"
|
15
|
-
circuit MockCircuit.new
|
16
|
-
end
|
17
|
-
|
18
|
-
it "defaults board to class variable board" do
|
19
|
-
TestBoardApp.instance_variable_get('@_board').should eql("board")
|
20
|
-
end
|
21
|
-
|
22
|
-
it "sets the board as an instance variable" do
|
23
|
-
app = TestBoardApp.new
|
24
|
-
app.board.should eql("board")
|
25
|
-
end
|
26
|
-
|
27
|
-
it "sets a circuit" do
|
28
|
-
app = TestBoardApp.new
|
29
|
-
app.circuit.class.should eql(MockCircuit)
|
30
|
-
end
|
31
|
-
|
32
9
|
class TestLedCircuit < BBB::Circuit
|
33
10
|
def initialize
|
34
11
|
attach BBB::Components::Led, pin: :P8_3, as: :led
|
@@ -36,7 +13,6 @@ describe BBB::Application do
|
|
36
13
|
end
|
37
14
|
|
38
15
|
class TestConnectionApp < BBB::Application
|
39
|
-
board BBB::Board::TestBoard.new
|
40
16
|
circuit TestLedCircuit.new
|
41
17
|
|
42
18
|
def run
|
@@ -49,13 +25,12 @@ describe BBB::Application do
|
|
49
25
|
|
50
26
|
app.circuit.respond_to?(:led).should be_true
|
51
27
|
app.circuit.led.should_receive(:on!)
|
52
|
-
app.led.should eql(app.circuit.led)
|
53
28
|
|
29
|
+
app.led.should eql(app.circuit.led)
|
54
30
|
app.led.on!
|
55
31
|
end
|
56
32
|
|
57
33
|
class FunctionsInApp < BBB::Application
|
58
|
-
board BBB::Board::TestBoard.new
|
59
34
|
circuit TestLedCircuit.new
|
60
35
|
|
61
36
|
def run
|
data/spec/circuit_spec.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe BBB::Components::AnalogComponent do
|
4
|
+
let(:component) { BBB::Components::AnalogComponent.new }
|
5
|
+
let(:component_class) { BBB::Components::AnalogComponent }
|
6
|
+
|
7
|
+
it "includes Pinnable module" do
|
8
|
+
component.pinnable?.should be_true
|
9
|
+
end
|
10
|
+
|
11
|
+
it "registers AnalogPin" do
|
12
|
+
component_class.pins.should eql([BBB::Pins::AnalogPin])
|
13
|
+
end
|
14
|
+
|
15
|
+
context "initialized" do
|
16
|
+
before :each do
|
17
|
+
@c = component
|
18
|
+
@c.initialize_pins(:P8_13)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "#pin" do
|
22
|
+
@c.pin.class.should eql(BBB::Pins::AnalogPin)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "#read" do
|
26
|
+
@c.pin.should_receive(:read)
|
27
|
+
@c.read
|
28
|
+
end
|
29
|
+
|
30
|
+
it "#value aliasses #read" do
|
31
|
+
@c.should_receive(:read)
|
32
|
+
@c.value
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/spec/components/led_spec.rb
CHANGED
@@ -3,42 +3,37 @@ require 'spec_helper'
|
|
3
3
|
describe BBB::Components::Led do
|
4
4
|
let(:led) {BBB::Components::Led.new}
|
5
5
|
|
6
|
+
before :each do
|
7
|
+
led.initialize_pins(:P8_4, mock: true)
|
8
|
+
end
|
9
|
+
|
6
10
|
it "initializes off" do
|
7
|
-
led.off
|
11
|
+
led.off?
|
8
12
|
end
|
9
13
|
|
10
14
|
it "set state: on" do
|
15
|
+
led.pin.should_receive(:on!)
|
11
16
|
led.on!
|
12
|
-
led.on?.should be_true
|
13
17
|
end
|
14
18
|
|
15
19
|
it "set state: off" do
|
16
|
-
led.
|
20
|
+
led.pin.should_receive(:off!)
|
17
21
|
led.off!
|
18
|
-
led.off?.should be_true
|
19
22
|
end
|
20
23
|
|
21
24
|
it "check state: on?" do
|
22
|
-
led.
|
23
|
-
led.on
|
24
|
-
led.on?.should be_true
|
25
|
+
led.pin.should_receive(:on?)
|
26
|
+
led.on?
|
25
27
|
end
|
26
28
|
|
27
|
-
it "
|
28
|
-
led.
|
29
|
-
led.
|
30
|
-
led.off!
|
31
|
-
led.state.should eql(:low)
|
29
|
+
it "check state: on?" do
|
30
|
+
led.pin.should_receive(:off?)
|
31
|
+
led.off?
|
32
32
|
end
|
33
33
|
|
34
34
|
context "#pinnable include" do
|
35
|
-
it "responds to pinnable
|
36
|
-
led.
|
37
|
-
end
|
38
|
-
|
39
|
-
it "sets the right pin position" do
|
40
|
-
led.register_pin_positions(:P8_3)
|
41
|
-
led.pin.position.should eql(:P8_3)
|
35
|
+
it "responds to pinnable?" do
|
36
|
+
led.pinnable?.should be_true
|
42
37
|
end
|
43
38
|
end
|
44
39
|
|
@@ -1,19 +1,84 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe BBB::Components::Pinnable do
|
4
|
+
class DummyPin
|
5
|
+
include BBB::Pins::Pinnable
|
6
|
+
end
|
7
|
+
|
4
8
|
class DummyComponent
|
5
9
|
include BBB::Components::Pinnable
|
10
|
+
uses DummyPin
|
11
|
+
end
|
12
|
+
|
13
|
+
class DoubleDummyComponent
|
14
|
+
include BBB::Components::Pinnable
|
15
|
+
uses DummyPin, DummyPin
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:dummy) { DummyComponent }
|
19
|
+
let(:double_dummy) { DoubleDummyComponent }
|
20
|
+
|
21
|
+
context "#initialize_pins" do
|
22
|
+
it "with single position" do
|
23
|
+
DummyPin.should_receive(:new).once.and_return(@mock_pin)
|
24
|
+
c = dummy.new
|
25
|
+
c.initialize_pins(:P8_3)
|
26
|
+
c.pins[0].should eql(@mock_pin)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "with single position and options" do
|
30
|
+
DummyPin.should_receive(:new).with(:P8_3, {:key=>"value"}).once
|
31
|
+
.and_return(@mock_pin)
|
32
|
+
c = dummy.new
|
33
|
+
c.initialize_pins(:P8_3, key: "value")
|
34
|
+
c.pins[0].should eql(@mock_pin)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "with multiple positions" do
|
38
|
+
DummyPin.should_receive(:new).exactly(2).times.and_return(@mock_pin)
|
39
|
+
c = double_dummy.new
|
40
|
+
c.initialize_pins(:P8_3, :P8_4)
|
41
|
+
c.pins[0].should eql(@mock_pin)
|
42
|
+
c.pins[1].should eql(@mock_pin)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "with multiple positions and options" do
|
46
|
+
DummyPin.should_receive(:new).with(:P8_3, {:key=>"value"}).once
|
47
|
+
.and_return(@mock_pin)
|
48
|
+
DummyPin.should_receive(:new).with(:P8_4, {:key=>"value"}).once
|
49
|
+
.and_return(@mock_pin)
|
50
|
+
c = double_dummy.new
|
51
|
+
c.initialize_pins(:P8_3, :P8_4, key: "value")
|
52
|
+
c.pins[0].should eql(@mock_pin)
|
53
|
+
c.pins[1].should eql(@mock_pin)
|
54
|
+
end
|
55
|
+
|
56
|
+
it "verifies the pin count" do
|
57
|
+
c = dummy.new
|
58
|
+
c.should_receive(:verify_pin_position_count).with([:P8_3])
|
59
|
+
c.initialize_pins(:P8_3)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "#verify_pin_position_count" do
|
64
|
+
|
65
|
+
it "raises exception when counts don't match" do
|
66
|
+
c = dummy.new
|
67
|
+
lambda do
|
68
|
+
c.verify_pin_position_count([:foo, :bar])
|
69
|
+
end.should raise_exception(BBB::PinsDoNotMatchException)
|
70
|
+
end
|
6
71
|
|
7
|
-
|
8
|
-
|
9
|
-
|
72
|
+
it "does not raise an exception when counts do match" do
|
73
|
+
c = dummy.new
|
74
|
+
lambda do
|
75
|
+
c.verify_pin_position_count([:foo])
|
76
|
+
end.should_not raise_exception
|
10
77
|
end
|
11
78
|
end
|
12
79
|
|
13
|
-
it "
|
14
|
-
|
15
|
-
|
16
|
-
comp.pins[0].position.should eql(:P8_3)
|
17
|
-
comp.pins[1].position.should eql(:P8_4)
|
80
|
+
it "should respond to pinnable?" do
|
81
|
+
c = dummy.new
|
82
|
+
c.pinnable?.should be_true
|
18
83
|
end
|
19
84
|
end
|