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.
- 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
data/lib/BBB/adc/setup.rb
DELETED
@@ -1,20 +0,0 @@
|
|
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
|
data/lib/BBB/board/base.rb
DELETED
@@ -1,45 +0,0 @@
|
|
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.respond_to?(:mode) && pin.mode == :output
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
def connect_io_pin(pin)
|
33
|
-
converted_pin = pin_converter.convert(pin)
|
34
|
-
pin.pin_io = converted_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
|
@@ -1,203 +0,0 @@
|
|
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
|
data/lib/BBB/board/pin_mapper.rb
DELETED
@@ -1,20 +0,0 @@
|
|
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
|
-
pin_mapping_file = File.expand_path("../../../../resources/pin_mappings.json", __FILE__)
|
9
|
-
MAP = JSONPinMapper.convert(pin_mapping_file)
|
10
|
-
|
11
|
-
def self.map(pin_symbol, type=:gpio)
|
12
|
-
begin
|
13
|
-
MAP.pins.fetch(pin_symbol.upcase.to_sym)
|
14
|
-
rescue Exception => e
|
15
|
-
raise UnknownPinException, "Pin #{pin_symbol} could not be mapped"
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
data/lib/BBB/board/test_board.rb
DELETED
data/lib/BBB/gpio/base.rb
DELETED
@@ -1,56 +0,0 @@
|
|
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 = Board::PinMapper.map(position).gpio
|
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
|
data/lib/BBB/gpio/digital_pin.rb
DELETED
@@ -1,69 +0,0 @@
|
|
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
|
@@ -1,28 +0,0 @@
|
|
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
|
-
opts = {:mock=>mock}.merge(opts)
|
15
|
-
|
16
|
-
base_class = pin.class.to_s.split("::").last
|
17
|
-
if GPIO.const_defined?(base_class)
|
18
|
-
klass = GPIO::const_get(base_class.to_sym)
|
19
|
-
return klass.new(pin.position, pin.mode, opts)
|
20
|
-
elsif ADC.const_defined?(base_class)
|
21
|
-
klass = ADC::const_get(base_class.to_sym)
|
22
|
-
return klass.new(pin.position, opts)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|