BBB 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,56 @@
1
+ module BBB
2
+ module GPIO
3
+ class Base
4
+ attr_reader :position, :converted_position
5
+ attr_reader :file_class
6
+
7
+ def initialize(position=nil, opts={})
8
+ initialize_base(position, opts)
9
+ end
10
+
11
+ def initialize_base(pin_position, opts)
12
+ @mock = opts.fetch(:mock, false)
13
+ self.position = pin_position
14
+ @file_class = @mock ? StringIO : File
15
+ export
16
+ end
17
+
18
+ def position=(position, mock=false)
19
+ @position = position
20
+ @converted_position = PinMapper.map(position)
21
+ end
22
+
23
+ def gpio_path
24
+ "/sys/class/gpio"
25
+ end
26
+
27
+ def export_path
28
+ gpio_path + "/export"
29
+ end
30
+
31
+ def unexport_path
32
+ gpio_path + "/unexport"
33
+ end
34
+
35
+ def gpio_direction_input
36
+ "in"
37
+ end
38
+
39
+ def gpio_direction_output
40
+ "out"
41
+ end
42
+
43
+ def gpio_pin_dir
44
+ "#{gpio_path}/gpio#{converted_position}"
45
+ end
46
+
47
+ def export
48
+ file_class.open(export_path, "w") { |f| f.write("#{ converted_position }") }
49
+ end
50
+
51
+ def unexport
52
+ file_class.open(unexport_path, "w") { |f| f.write("#{converted_position}") }
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,69 @@
1
+ module BBB
2
+ module GPIO
3
+ class DigitalPin < Base
4
+ attr_reader :mode, :io
5
+
6
+ def initialize(position, mode, opts={})
7
+ initialize_base(position, opts)
8
+ @mode = validate_mode(mode)
9
+ set_mode
10
+ end
11
+
12
+ def direction
13
+ case mode
14
+ when :input
15
+ gpio_direction_input
16
+ when :output
17
+ gpio_direction_output
18
+ end
19
+ end
20
+
21
+ def file_mode
22
+ case mode
23
+ when :input
24
+ "r"
25
+ when :output
26
+ "w+"
27
+ end
28
+ end
29
+
30
+ def set_mode
31
+ direction_file = gpio_pin_dir + "/direction"
32
+ file_class.open(direction_file, "w") {|f| f.write(direction); f.flush}
33
+ end
34
+
35
+ def io
36
+ return @io unless @io.nil?
37
+
38
+ value_file = gpio_pin_dir + "/value"
39
+ @io = file_class.open(value_file, file_mode)
40
+ end
41
+
42
+ def write(value)
43
+ io.rewind
44
+ io.write value_map[value]
45
+ io.flush
46
+ end
47
+
48
+ def read
49
+ io.rewind
50
+ value_map[io.read]
51
+ end
52
+
53
+ private
54
+
55
+ def validate_mode(mode)
56
+ if [:input, :output].include?(mode)
57
+ return mode
58
+ else
59
+ raise UnknownPinModeException, "Pin mode: #{mode} is now known"
60
+ end
61
+ end
62
+
63
+ def value_map
64
+ @value_map ||= {:high=>1, :low=>0, 1=>:high, 0=>:low}
65
+ end
66
+
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,22 @@
1
+ module BBB
2
+ module GPIO
3
+ class PinConverter
4
+ attr_reader :mock
5
+
6
+ def initialize(opts={})
7
+ @mock = opts.fetch(:mock, false)
8
+ end
9
+
10
+ ##
11
+ # Currently only converts IO::DigitalPins
12
+ #
13
+ def convert(pin, opts={})
14
+ base_class = pin.class.to_s.split("::").last
15
+ klass = GPIO::const_get(base_class.to_sym)
16
+ opts = {:mock=>mock}.merge(opts)
17
+ return klass.new(pin.position, pin.mode, opts)
18
+ end
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,67 @@
1
+ module BBB
2
+ module IO
3
+ ##
4
+ # Credit goes to the great work done at the Artoo framework
5
+ # The original idea for this class came from them.
6
+ # https://github.com/hybridgroup/artoo/blob/master/lib/artoo/adaptors/io/digital_pin.rb
7
+ #
8
+ class DigitalPin
9
+ include Pinnable
10
+ attr_reader :mode, :status
11
+ attr_accessor :pin_io
12
+
13
+ ##
14
+ # Digital pin which is abstracted away from any kind of IO.
15
+ # This has the benefit of being able to write a generic application
16
+ # that you can then easily port to a BBB, Pi or Arduino
17
+ #
18
+ # @param pin_num [Symbol]
19
+ # @param mode [Symbol, nil] the mode of the pin, :input or :output. Defaults
20
+ # to :input
21
+ # @pin_io [IO, nil] the IO object
22
+ #
23
+ def initialize(mode=:input, pin_io=nil, position=nil)
24
+ @pin_io = pin_io || MockPin.new
25
+ @mode = mode
26
+ @position = position
27
+ end
28
+
29
+ # Writes to the specified pin Digitally
30
+ # accepts values :high or :low
31
+ def write(value)
32
+ raise ArgumentError unless [:high, :low].include?(value)
33
+ @status = value
34
+ @pin_io.write(value)
35
+ end
36
+
37
+ # Reads digitally from the specified pin on initialize
38
+ def read
39
+ if mode == :input
40
+ pin_io.read
41
+ else
42
+ status
43
+ end
44
+ end
45
+
46
+ # Sets digital write for the pin to HIGH
47
+ def on!
48
+ write(:high)
49
+ end
50
+ #
51
+ # Sets digital write for the pin to LOW
52
+ #
53
+ def off!
54
+ write(:low)
55
+ end
56
+
57
+ def on?
58
+ (status == :high) ? true : false
59
+ end
60
+
61
+ def off?
62
+ !self.on?
63
+ end
64
+
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,8 @@
1
+ require 'stringio'
2
+
3
+ module BBB
4
+ module IO
5
+ class MockPin < StringIO
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,12 @@
1
+ module BBB
2
+ module IO
3
+ module Pinnable
4
+ attr_reader :position
5
+
6
+ def position=(position)
7
+ @position = position
8
+ end
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,84 @@
1
+ module BBB
2
+ class PinMapper
3
+ ##
4
+ # Thanks to artoo-beaglebone
5
+ # https://github.com/hybridgroup/artoo-beaglebone/blob/master/lib/artoo/adaptors/beaglebone.rb
6
+ #
7
+ PINS = {
8
+ :P8_3 => 38,
9
+ :P8_4 => 39,
10
+ :P8_5 => 34,
11
+ :P8_6 => 35,
12
+ :P8_7 => 66,
13
+ :P8_8 => 67,
14
+ :P8_9 => 69,
15
+ :P8_10 => 68,
16
+ :P8_11 => 45,
17
+ :P8_12 => 44,
18
+ :P8_13 => 23,
19
+ :P8_14 => 26,
20
+ :P8_15 => 47,
21
+ :P8_16 => 46,
22
+ :P8_17 => 27,
23
+ :P8_18 => 65,
24
+ :P8_19 => 22,
25
+ :P8_20 => 63,
26
+ :P8_21 => 62,
27
+ :P8_22 => 37,
28
+ :P8_23 => 36,
29
+ :P8_24 => 33,
30
+ :P8_25 => 32,
31
+ :P8_26 => 61,
32
+ :P8_27 => 86,
33
+ :P8_28 => 88,
34
+ :P8_29 => 87,
35
+ :P8_30 => 89,
36
+ :P8_31 => 10,
37
+ :P8_32 => 11,
38
+ :P8_33 => 9,
39
+ :P8_34 => 81,
40
+ :P8_35 => 8,
41
+ :P8_36 => 80,
42
+ :P8_37 => 78,
43
+ :P8_38 => 79,
44
+ :P8_39 => 76,
45
+ :P8_40 => 77,
46
+ :P8_41 => 74,
47
+ :P8_42 => 75,
48
+ :P8_43 => 72,
49
+ :P8_44 => 73,
50
+ :P8_45 => 70,
51
+ :P8_46 => 71,
52
+ :P9_11 => 30,
53
+ :P9_12 => 60,
54
+ :P9_13 => 31,
55
+ :P9_14 => 50,
56
+ :P9_15 => 48,
57
+ :P9_16 => 51,
58
+ :P9_17 => 5,
59
+ :P9_18 => 4,
60
+ :P9_19 => 13,
61
+ :P9_20 => 12,
62
+ :P9_21 => 3,
63
+ :P9_22 => 2,
64
+ :P9_23 => 49,
65
+ :P9_24 => 15,
66
+ :P9_25 => 117,
67
+ :P9_26 => 14,
68
+ :P9_27 => 115,
69
+ :P9_28 => 113,
70
+ :P9_29 => 111,
71
+ :P9_30 => 112,
72
+ :P9_31 => 110
73
+ }
74
+ attr_reader :pins
75
+
76
+ def self.map(pin_symbol)
77
+ begin
78
+ PINS.fetch(pin_symbol.upcase.to_sym)
79
+ rescue Exception => e
80
+ raise UnknownPinException, "Pin #{pin_symbol} could not be mapped"
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,11 @@
1
+ module BBB
2
+ class TestBoard < BBB::Board
3
+
4
+ private
5
+
6
+ def self.pin_converter
7
+ GPIO::PinConverter.new(mock:true)
8
+ end
9
+ end
10
+ end
11
+
data/lib/BBB/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module BBB
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe BBB::Application do
4
+
5
+ it "initializes" do
6
+ lambda { BBB::Application.new }.should_not raise_exception
7
+ end
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
+ class TestLedCircuit < BBB::Circuit
33
+ def initialize
34
+ attach BBB::Components::Led, pin: :P8_3, as: :led
35
+ end
36
+ end
37
+
38
+ class TestConnectionApp < BBB::Application
39
+ board BBB::TestBoard.new
40
+ circuit TestLedCircuit.new
41
+ end
42
+
43
+ it "attaches virtual pins to board pins" do
44
+ app = TestConnectionApp.new
45
+
46
+ app.circuit.respond_to?(:led).should be_true
47
+ app.circuit.led.should_receive(:on!)
48
+ app.led.should eql(app.circuit.led)
49
+
50
+ app.led.on!
51
+ end
52
+
53
+ end
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe BBB::Board do
4
+ let(:bbb) {BBB::TestBoard.new}
5
+
6
+ it "initializes with a converter" do
7
+ BBB::Board.should_not_receive(:pin_converter)
8
+ converter = "SomeConverter"
9
+ board = BBB::Board.new(converter)
10
+ board.pin_converter.should eql(converter)
11
+ end
12
+
13
+ it "initializes with a default configuration" do
14
+ BBB::Board.should_receive(:pin_converter) { 'Default Config' }
15
+ board = BBB::Board.new
16
+ end
17
+
18
+ context "setting pins" do
19
+ Pin = BBB::IO::DigitalPin
20
+
21
+ it "defines input function for input pin" do
22
+ pin = Pin.new(:input, nil, :P8_3)
23
+ bbb.setup_pin(pin)
24
+ bbb.respond_to?("p8_3").should be_true
25
+ end
26
+
27
+ it "defines output function for input pin" do
28
+ pin = Pin.new(:output, nil, :P8_3)
29
+ bbb.setup_pin(pin)
30
+ bbb.respond_to?("p8_3=").should be_true
31
+ end
32
+
33
+ it "enables output function for output pin" do
34
+ pin = Pin.new(:output, nil, :P8_3)
35
+ bbb.setup_pin(pin)
36
+ bbb.p8_3=:low
37
+ pin.status.should eql(:low)
38
+ end
39
+
40
+ it "should keep the reference to the pin" do
41
+ pin = Pin.new(:output, nil, :P8_4)
42
+ bbb.connect_io_pin(pin)
43
+ pin.write :high
44
+ bbb.p8_4.should eql(:high)
45
+ end
46
+
47
+ end
48
+
49
+ end