BBB 0.0.3 → 0.0.4
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.
- 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"
|