BBB 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -2
- data/Gemfile +2 -0
- data/examples/analog_pin.rb +31 -0
- data/examples/led.rb +1 -1
- data/examples/sketches.rb +2 -2
- data/lib/BBB/adc/analog_pin.rb +41 -0
- data/lib/BBB/adc/setup.rb +20 -0
- data/lib/BBB/board/base.rb +45 -0
- data/lib/BBB/board/json_pin_mapper.rb +203 -0
- data/lib/BBB/board/pin_mapper.rb +19 -0
- data/lib/BBB/board/test_board.rb +12 -0
- data/lib/BBB/exceptions.rb +0 -1
- data/lib/BBB/gpio/base.rb +2 -2
- data/lib/BBB/io/analog_pin.rb +23 -0
- data/lib/BBB/io/digital_pin.rb +4 -4
- data/lib/BBB/version.rb +1 -1
- data/lib/BBB.rb +11 -3
- data/resources/pin_mappings.json +1535 -0
- data/resources/pin_mappings.json.comment +14 -0
- data/spec/adc/analog_pin_spec.rb +100 -0
- data/spec/adc/setup_spec.rb +9 -0
- data/spec/application_spec.rb +1 -1
- data/spec/{board_spec.rb → board/board_spec.rb} +6 -6
- data/spec/{pin_mapper_spec.rb → board/pin_mapper_spec.rb} +4 -4
- metadata +21 -15
- data/lib/BBB/board.rb +0 -41
- data/lib/BBB/pin_mapper.rb +0 -84
- data/lib/BBB/test_board.rb +0 -11
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'BBB'
|
2
|
+
|
3
|
+
##
|
4
|
+
# Setup the AnalogPin Circuit
|
5
|
+
#
|
6
|
+
class Circuit < BBB::Circuit
|
7
|
+
def initialize
|
8
|
+
# Attach temperature sensor to pin P9_40
|
9
|
+
attach BBB::Components::Analog, pin: :P9_40, as: :thermometer
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
##
|
14
|
+
# Setup the actual Applicaiton
|
15
|
+
#
|
16
|
+
class TemperatureExampleApp < BBB::Application
|
17
|
+
# Run this on the BeagleBoneBlack
|
18
|
+
board BBB::Board.new
|
19
|
+
|
20
|
+
# Connect the circuit to the board
|
21
|
+
circuit Circuit.new
|
22
|
+
|
23
|
+
# This is the basic run loop
|
24
|
+
def run
|
25
|
+
puts thermometer.read
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Initialize the app
|
30
|
+
app = TemperatureExampleApp.new
|
31
|
+
app.start
|
data/examples/led.rb
CHANGED
data/examples/sketches.rb
CHANGED
@@ -0,0 +1,41 @@
|
|
1
|
+
module BBB
|
2
|
+
module ADC
|
3
|
+
class AnalogPin
|
4
|
+
attr_reader :position, :pin_map, :mock
|
5
|
+
attr_reader :file_handle
|
6
|
+
|
7
|
+
def initialize(position, opts={})
|
8
|
+
self.position = position
|
9
|
+
@mock = opts.fetch(:mock, false)
|
10
|
+
@file_handle = get_file_handle(mock)
|
11
|
+
end
|
12
|
+
|
13
|
+
def position=(position)
|
14
|
+
map = Board::PinMapper.map(position, :ain)
|
15
|
+
unless map.respond_to?(:ain) && !map.ain.nil?
|
16
|
+
raise ArgumentError, "#{position} is not a valid AIN pin position"
|
17
|
+
end
|
18
|
+
|
19
|
+
@pin_map = map
|
20
|
+
@position = position
|
21
|
+
end
|
22
|
+
|
23
|
+
def ain_path
|
24
|
+
"/sys/devices/ocp.3/helper.15/AIN#{pin_map.ain}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def read
|
28
|
+
file_handle.read
|
29
|
+
end
|
30
|
+
|
31
|
+
def scale
|
32
|
+
pin_map.scale
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_file_handle(mock=false)
|
36
|
+
mock ? StringIO.new : File.open(ain_path, "r")
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module BBB
|
2
|
+
module ADC
|
3
|
+
def self.setup
|
4
|
+
check_if_kernel_module_is_loaded!
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.check_if_kernel_module_is_loaded!
|
8
|
+
ains = `find /sys/ -name '*AIN*'`.split("\n")
|
9
|
+
|
10
|
+
if ains.size > 0
|
11
|
+
return true
|
12
|
+
else
|
13
|
+
raise ModuleNotLoadedException, "Is seems that the ADC module is not
|
14
|
+
loaded into the kernel. You might want to try: \n
|
15
|
+
sudo modprobe t1_tscadc or add it to the kernel on boot: \n
|
16
|
+
echo 't1_tscadc' >> /etc/modules.conf"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module BBB
|
2
|
+
module Board
|
3
|
+
##
|
4
|
+
# Base class, designed and tested on BeagleBone Black Revision A5C
|
5
|
+
#
|
6
|
+
class Base
|
7
|
+
attr_reader :gpio, :pin_converter
|
8
|
+
|
9
|
+
def initialize(pin_converter=nil)
|
10
|
+
@pin_converter = pin_converter || self.class.pin_converter
|
11
|
+
@pins = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
##
|
15
|
+
# Define methods for a GPIO::PIN
|
16
|
+
#
|
17
|
+
def setup_pin(pin)
|
18
|
+
@pins[pin.position] = pin
|
19
|
+
|
20
|
+
metaclass = class << self; self; end
|
21
|
+
metaclass.class_eval do
|
22
|
+
define_method("p#{pin.position.to_s[1..-1]}") do
|
23
|
+
@pins[pin.position].read
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method("p#{pin.position.to_s[1..-1]}=") do |value|
|
27
|
+
@pins[pin.position].write value
|
28
|
+
end if pin.mode == :output
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def connect_io_pin(pin)
|
33
|
+
gpio_pin = pin_converter.convert(pin)
|
34
|
+
pin.pin_io = gpio_pin
|
35
|
+
setup_pin(pin)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def self.pin_converter
|
41
|
+
GPIO::PinConverter.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,203 @@
|
|
1
|
+
module BBB
|
2
|
+
module Board
|
3
|
+
##
|
4
|
+
# This class provides a convenient way of mapping a JSON representation of the
|
5
|
+
# pins, taken from the bonescript sourcecode, into Ruby objects. After
|
6
|
+
# converting the json to ruby objects the "normal" PinMapper will take the
|
7
|
+
# object structure and provide the actual mapping from the pin header
|
8
|
+
# positions, like p8_3 to the correct GPIO, I2C or WPM endpoints.
|
9
|
+
#
|
10
|
+
# This class should not be used directly to provide these mappings it's simply
|
11
|
+
# a helper class to get from JSON to Ruby.
|
12
|
+
#
|
13
|
+
class JSONPinMapper
|
14
|
+
class PinMap < Struct.new(:pins, :uart, :i2c); end
|
15
|
+
class Pin < Struct.new(:name, :gpio, :led, :mux, :key, :mux_reg_offset,
|
16
|
+
:options, :eeprom, :pwm, :ain, :scale); end
|
17
|
+
class UART < Struct.new(:devicetree, :rx, :tx); end
|
18
|
+
class I2C < Struct.new(:devicetree, :path, :sda, :scl); end
|
19
|
+
|
20
|
+
attr_reader :data
|
21
|
+
|
22
|
+
##
|
23
|
+
# Initialize a JSONPinMapper
|
24
|
+
#
|
25
|
+
# @param [Hash] hash Hash that was converted from json with the keys
|
26
|
+
# pinIndex, uart and i2c.
|
27
|
+
#
|
28
|
+
def initialize(hash)
|
29
|
+
@data = hash
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# Factor a new JSONPinMapper based on a json_file that get's parsed to a
|
34
|
+
# hash.
|
35
|
+
#
|
36
|
+
# @param [String] json_filename The file that contains the JSON object with
|
37
|
+
# pin information
|
38
|
+
#
|
39
|
+
# @return JSONPinMapper instance
|
40
|
+
#
|
41
|
+
def self.convert(json_filename)
|
42
|
+
file = File.open(json_filename, "r")
|
43
|
+
hash = JSON.parse(file.read)
|
44
|
+
new(hash).convert
|
45
|
+
end
|
46
|
+
|
47
|
+
##
|
48
|
+
# Convert from a the data hash to ruby objects
|
49
|
+
#
|
50
|
+
# @return [Struct] with pins, uart and i2c as keys.
|
51
|
+
# pins has a
|
52
|
+
#
|
53
|
+
def convert
|
54
|
+
pins = convert_pins(data["pinIndex"])
|
55
|
+
uart = convert_uart(data["uarts"])
|
56
|
+
i2c = convert_i2c(data["i2c"])
|
57
|
+
|
58
|
+
PinMap.new(pins, uart, i2c)
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# Converts an array of pins into a hash with the pin key as a key and a Pin
|
63
|
+
# Struct as a value.
|
64
|
+
#
|
65
|
+
# Here is an example of a piece of the JSON code containing pin info:
|
66
|
+
#
|
67
|
+
# {
|
68
|
+
# "name": "USR0",
|
69
|
+
# "gpio": 53,
|
70
|
+
# "led": "usr0",
|
71
|
+
# "mux": "gpmc_a5",
|
72
|
+
# "key": "USR0",
|
73
|
+
# "muxRegOffset": "0x054",
|
74
|
+
# "options": [
|
75
|
+
# "gpmc_a5",
|
76
|
+
# "gmii2_txd0",
|
77
|
+
# "rgmii2_td0",
|
78
|
+
# "rmii2_txd0",
|
79
|
+
# "gpmc_a21",
|
80
|
+
# "pr1_mii1_rxd3",
|
81
|
+
# "eqep1b_in",
|
82
|
+
# "gpio1_21"
|
83
|
+
# ]
|
84
|
+
# }
|
85
|
+
#
|
86
|
+
# @param [Array<Hash>] array An array of Pin hashes
|
87
|
+
#
|
88
|
+
# @return [Hash] a hash with pin keys as keys and pin objects as values.
|
89
|
+
#
|
90
|
+
def convert_pins(array)
|
91
|
+
hash = {}
|
92
|
+
|
93
|
+
array.each do |pin_hash|
|
94
|
+
pin = Pin.new
|
95
|
+
pin_hash.each_pair do |key, value|
|
96
|
+
pin[underscore(key).to_sym] = value
|
97
|
+
end
|
98
|
+
hash[pin.key.upcase.to_sym] = pin
|
99
|
+
end
|
100
|
+
|
101
|
+
return hash
|
102
|
+
end
|
103
|
+
|
104
|
+
##
|
105
|
+
# Convert a hash of uarts to a hash with the uart folder (e.g. /dev/tty00)
|
106
|
+
# as the key and an uart object as the value.
|
107
|
+
#
|
108
|
+
# Here is an example of an individual UART hash:
|
109
|
+
#
|
110
|
+
# "/dev/ttyO1": {
|
111
|
+
# "devicetree": "BB-UART1",
|
112
|
+
# "rx": "P9_26",
|
113
|
+
# "tx": "P9_24"
|
114
|
+
# }
|
115
|
+
#
|
116
|
+
# @param [Hash] data_hash with strings as keys and hashes as values
|
117
|
+
#
|
118
|
+
# @return [Hash] with strings of uart positions (e.g. /dev/tty00) as keys
|
119
|
+
# and uart objects as values
|
120
|
+
#
|
121
|
+
def convert_uart(data_hash)
|
122
|
+
convert_hash_with_hashes(data_hash, UART)
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Convert a hash of I2Cs to a hash with the I2C folder as the key and a i2c
|
127
|
+
# object as the value
|
128
|
+
#
|
129
|
+
# Here is an example of an individual I2C hash:
|
130
|
+
#
|
131
|
+
# "/dev/i2c-1": {
|
132
|
+
# "devicetree": "BB-I2C1",
|
133
|
+
# "path": "/dev/i2c-2",
|
134
|
+
# "sda": "P9_18",
|
135
|
+
# "scl": "P9_17"
|
136
|
+
# }
|
137
|
+
#
|
138
|
+
# @param [Hash] data_hash with strings as keys and hashes as values
|
139
|
+
#
|
140
|
+
# @return [Hash] with strings of I2C folders as keys and I2C objects as
|
141
|
+
# values
|
142
|
+
#
|
143
|
+
def convert_i2c(data_hash)
|
144
|
+
convert_hash_with_hashes(data_hash, I2C)
|
145
|
+
end
|
146
|
+
|
147
|
+
private
|
148
|
+
|
149
|
+
##
|
150
|
+
# @see #convert_uart
|
151
|
+
#
|
152
|
+
def convert_hash_with_hashes(data_hash, object)
|
153
|
+
hash = {}
|
154
|
+
|
155
|
+
data_hash.each_pair do |filesystem, info_hash|
|
156
|
+
instance = object.new
|
157
|
+
info_hash.each_pair do |key, value|
|
158
|
+
instance[key] = value
|
159
|
+
end
|
160
|
+
|
161
|
+
hash[filesystem] = instance
|
162
|
+
end
|
163
|
+
|
164
|
+
return hash
|
165
|
+
end
|
166
|
+
|
167
|
+
##
|
168
|
+
# Makes an underscored, lowercase form from the expression in the string.
|
169
|
+
#
|
170
|
+
# Gracefully copied from ActiveSupport::Inflections
|
171
|
+
# http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-underscore
|
172
|
+
#
|
173
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
174
|
+
#
|
175
|
+
# 'ActiveModel'.underscore # => "active_model"
|
176
|
+
# 'ActiveModel::Errors'.underscore # => "active_model/errors"
|
177
|
+
#
|
178
|
+
# As a rule of thumb you can think of +underscore+ as the inverse of
|
179
|
+
# +camelize+, though there are cases where that does not hold:
|
180
|
+
#
|
181
|
+
# 'SSLError'.underscore.camelize # => "SslError"
|
182
|
+
def underscore(camel_cased_word)
|
183
|
+
word = camel_cased_word.to_s.dup
|
184
|
+
word.gsub!('::', '/')
|
185
|
+
word.gsub!(/(?:([A-Za-z\d])|^)(#{acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
|
186
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
187
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
188
|
+
word.tr!("-", "_")
|
189
|
+
word.downcase!
|
190
|
+
word
|
191
|
+
end
|
192
|
+
|
193
|
+
##
|
194
|
+
# Specifies acronyms. This is a shortcut approach to the full acronym
|
195
|
+
# functionality of Rails. Which can be found here:
|
196
|
+
# https://github.com/rails/rails/blob/4e327225947b933d5434509e02e98226c581adc1/activesupport/lib/active_support/inflector/inflections.rb#L47
|
197
|
+
#
|
198
|
+
def acronym_regex
|
199
|
+
/#{%w(I2C UART GPIO).join("|")}/
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module BBB
|
2
|
+
module Board
|
3
|
+
class PinMapper
|
4
|
+
##
|
5
|
+
# Thanks to BoneScript, see the resources/pin_mappings.json.comment
|
6
|
+
# for reference to the original BoneScript file.
|
7
|
+
#
|
8
|
+
MAP = JSONPinMapper.convert("resources/pin_mappings.json")
|
9
|
+
|
10
|
+
def self.map(pin_symbol, type=:gpio)
|
11
|
+
begin
|
12
|
+
MAP.pins.fetch(pin_symbol.upcase.to_sym)
|
13
|
+
rescue Exception => e
|
14
|
+
raise UnknownPinException, "Pin #{pin_symbol} could not be mapped"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/BBB/exceptions.rb
CHANGED
data/lib/BBB/gpio/base.rb
CHANGED
@@ -12,12 +12,12 @@ module BBB
|
|
12
12
|
@mock = opts.fetch(:mock, false)
|
13
13
|
self.position = pin_position
|
14
14
|
@file_class = @mock ? StringIO : File
|
15
|
-
|
15
|
+
export
|
16
16
|
end
|
17
17
|
|
18
18
|
def position=(position, mock=false)
|
19
19
|
@position = position
|
20
|
-
@converted_position = PinMapper.map(position)
|
20
|
+
@converted_position = Board::PinMapper.map(position).gpio
|
21
21
|
end
|
22
22
|
|
23
23
|
def gpio_path
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module BBB
|
2
|
+
module IO
|
3
|
+
class AnalogPin
|
4
|
+
include Pinnable
|
5
|
+
|
6
|
+
attr_reader :pin_io, :position
|
7
|
+
|
8
|
+
def initialize(pin_io=nil, position=nil)
|
9
|
+
@pin_io = pin_io || MockPin.new
|
10
|
+
@position = position
|
11
|
+
end
|
12
|
+
|
13
|
+
def read
|
14
|
+
pin_io.read
|
15
|
+
end
|
16
|
+
|
17
|
+
def scale
|
18
|
+
pin_io.scale
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/BBB/io/digital_pin.rb
CHANGED
@@ -36,11 +36,11 @@ module BBB
|
|
36
36
|
|
37
37
|
# Reads digitally from the specified pin on initialize
|
38
38
|
def read
|
39
|
-
|
40
|
-
|
41
|
-
|
39
|
+
if mode == :input
|
40
|
+
pin_io.read
|
41
|
+
else
|
42
42
|
status
|
43
|
-
|
43
|
+
end
|
44
44
|
end
|
45
45
|
|
46
46
|
# Sets digital write for the pin to HIGH
|
data/lib/BBB/version.rb
CHANGED
data/lib/BBB.rb
CHANGED
@@ -1,14 +1,22 @@
|
|
1
1
|
require "BBB/version"
|
2
|
-
|
3
|
-
require "
|
2
|
+
|
3
|
+
require "json"
|
4
|
+
|
5
|
+
require "BBB/board/base"
|
6
|
+
require "BBB/board/test_board"
|
7
|
+
require "BBB/board/json_pin_mapper"
|
8
|
+
require "BBB/board/pin_mapper"
|
9
|
+
|
4
10
|
require "BBB/circuit"
|
5
|
-
require "BBB/pin_mapper"
|
6
11
|
require "BBB/exceptions"
|
7
12
|
|
8
13
|
require "BBB/gpio/base"
|
9
14
|
require "BBB/gpio/digital_pin"
|
10
15
|
require "BBB/gpio/pin_converter"
|
11
16
|
|
17
|
+
require "BBB/adc/setup"
|
18
|
+
require "BBB/adc/analog_pin"
|
19
|
+
|
12
20
|
require "BBB/io/pinnable"
|
13
21
|
require "BBB/io/digital_pin"
|
14
22
|
require "BBB/io/mock_pin"
|