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
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
|