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
@@ -0,0 +1,39 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
##
|
4
|
+
# A pin that reads from the ADC converteds on the board. On the Beaglebone
|
5
|
+
# this is AIN1 to 7. The class itself doesn't do much, since most of the
|
6
|
+
# basic functionality is provided by the pinnable module which is included,
|
7
|
+
# as well as the IO::AIN object used for IO to the filesystem
|
8
|
+
#
|
9
|
+
class AnalogPin
|
10
|
+
include Pinnable
|
11
|
+
|
12
|
+
##
|
13
|
+
# Read from the Pin
|
14
|
+
#
|
15
|
+
# @return Integer
|
16
|
+
#
|
17
|
+
def read
|
18
|
+
io.read
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# Return the scale of the Pin. On the BeagleBoneBlack 12 bit pins this is
|
23
|
+
# 4096.
|
24
|
+
#
|
25
|
+
# @return Integer
|
26
|
+
#
|
27
|
+
def scale
|
28
|
+
@scale ||= io.scale
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def default_io
|
34
|
+
IO::AIN.new(position)
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
##
|
4
|
+
# A Digital Pin on the board. The digital pins uses GPIO on the filesystem
|
5
|
+
# to communicate. This class assumes its the only actor on the pin. Therfore
|
6
|
+
# it can cache the status in memory instead of reading it from the
|
7
|
+
# filesystem every time.
|
8
|
+
#
|
9
|
+
# It is advised to use the DigitalInputPin and DigitalOutputPin classes for
|
10
|
+
# clarity, buy, nothings stops you from using a DigitalPin with the :input
|
11
|
+
# or :output direction.
|
12
|
+
#
|
13
|
+
class DigitalPin
|
14
|
+
include Pinnable
|
15
|
+
|
16
|
+
attr_reader :status, :opts
|
17
|
+
|
18
|
+
##
|
19
|
+
# Gets the direction of the pin from the options and memoizes it in the
|
20
|
+
# @direction attribute.
|
21
|
+
#
|
22
|
+
# @return [Symbol] either :input or :output
|
23
|
+
def direction
|
24
|
+
@direction ||= @opts.fetch(:direction)
|
25
|
+
end
|
26
|
+
|
27
|
+
##
|
28
|
+
# Write value to the specified pin Digitally. This might fail hard if you
|
29
|
+
# try to write to an input pin. However, for performance reasons we do not
|
30
|
+
# want to check the direction of the pin every write.
|
31
|
+
#
|
32
|
+
def write(value)
|
33
|
+
@status = value
|
34
|
+
io.write(value)
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# Read value from the pin for input pins, or from memory for output pins.
|
39
|
+
#
|
40
|
+
# @return [Symbol] :high or :low
|
41
|
+
#
|
42
|
+
def status
|
43
|
+
if direction == :input
|
44
|
+
@status = io.read
|
45
|
+
end
|
46
|
+
|
47
|
+
return @status
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# Set the pin into :high state
|
52
|
+
# @return [void]
|
53
|
+
def on!
|
54
|
+
write(:high)
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Set the pin into :low state
|
59
|
+
# @return [void]
|
60
|
+
def off!
|
61
|
+
write(:low)
|
62
|
+
end
|
63
|
+
|
64
|
+
##
|
65
|
+
# Check if the pin state is high
|
66
|
+
# @return [Boolean]
|
67
|
+
def on?
|
68
|
+
status == :high
|
69
|
+
end
|
70
|
+
|
71
|
+
##
|
72
|
+
# Check if the pin state is low
|
73
|
+
# @return [Boolean]
|
74
|
+
def off?
|
75
|
+
!on?
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def default_io
|
81
|
+
IO::GPIO.new(direction, position)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# @see DigitalPin
|
87
|
+
#
|
88
|
+
class DigitalInputPin < DigitalPin
|
89
|
+
def initialize(position, opts={})
|
90
|
+
opts.merge!(:direction=>:input)
|
91
|
+
super(position, opts)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
##
|
96
|
+
# @see DigitalPin
|
97
|
+
#
|
98
|
+
class DigitalOutputPin < DigitalPin
|
99
|
+
def initialize(position, opts={})
|
100
|
+
opts.merge!(:direction=>:output)
|
101
|
+
super(position, opts)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
module IO
|
4
|
+
class AIN
|
5
|
+
include Mapped
|
6
|
+
|
7
|
+
attr_reader :io, :position
|
8
|
+
|
9
|
+
def initialize(position)
|
10
|
+
@position = position
|
11
|
+
self.export
|
12
|
+
@io = get_file_handle
|
13
|
+
end
|
14
|
+
|
15
|
+
def read
|
16
|
+
io.rewind
|
17
|
+
io.read.to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
def scale
|
21
|
+
pin_map.scale
|
22
|
+
end
|
23
|
+
|
24
|
+
def export
|
25
|
+
cape_dir = "/sys/devices/bone_capemgr.*/slots"
|
26
|
+
dir = Dir.glob(cape_dir)
|
27
|
+
if dir.length == 0
|
28
|
+
raise BoardError, "unable to access the capemgr directory: #{cape_dir}"
|
29
|
+
end
|
30
|
+
`echo cape-bone-iio > #{dir.first}`
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_file_handle
|
34
|
+
dir = Dir.glob("/sys/devices/ocp.*/helper.*/")
|
35
|
+
file = File.expand_path("AIN#{pin_map.ain}", dir.first)
|
36
|
+
return File.open(file, "r")
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.setup
|
40
|
+
check_if_kernel_module_is_loaded!
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.check_if_kernel_module_is_loaded!
|
44
|
+
ains = `find /sys/ -name '*AIN*'`.split("\n")
|
45
|
+
|
46
|
+
if ains.size > 0
|
47
|
+
return true
|
48
|
+
else
|
49
|
+
raise ModuleNotLoadedException, "Is seems that the ADC module is not
|
50
|
+
loaded into the kernel. You might want to try: \n
|
51
|
+
sudo modprobe t1_tscadc or add it to the kernel on boot: \n
|
52
|
+
echo 't1_tscadc' >> /etc/modules.conf"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
module IO
|
4
|
+
class GPIO
|
5
|
+
include Mapped
|
6
|
+
|
7
|
+
attr_reader :file_mode, :converted_position, :position, :direction
|
8
|
+
|
9
|
+
def initialize(direction, position)
|
10
|
+
self.direction = direction
|
11
|
+
@position = position
|
12
|
+
@converted_position = pin_map.gpio
|
13
|
+
self.export
|
14
|
+
end
|
15
|
+
|
16
|
+
def direction=(direction)
|
17
|
+
@file_mode = direction == :input ? "r" : "w+"
|
18
|
+
@direction = direction
|
19
|
+
end
|
20
|
+
|
21
|
+
def set_mode
|
22
|
+
direction_file = gpio_pin_dir + "/direction"
|
23
|
+
file_class.open(direction_file, "w") {|f| f.write(direction)}
|
24
|
+
end
|
25
|
+
|
26
|
+
def io
|
27
|
+
return @io unless @io.nil?
|
28
|
+
value_file = gpio_pin_dir + "/value"
|
29
|
+
@io = file_class.open(value_file, file_mode)
|
30
|
+
end
|
31
|
+
|
32
|
+
def write(value)
|
33
|
+
io.write(value_map[value])
|
34
|
+
io.flush
|
35
|
+
end
|
36
|
+
|
37
|
+
def read
|
38
|
+
io.rewind
|
39
|
+
value_map[io.read]
|
40
|
+
end
|
41
|
+
|
42
|
+
def value_map
|
43
|
+
@value_map ||= {:high=>1, :low=>0, 1=>:high, 0=>:low}
|
44
|
+
end
|
45
|
+
|
46
|
+
def gpio_path
|
47
|
+
"/sys/class/gpio"
|
48
|
+
end
|
49
|
+
|
50
|
+
def export_path
|
51
|
+
gpio_path + "/export"
|
52
|
+
end
|
53
|
+
|
54
|
+
def unexport_path
|
55
|
+
gpio_path + "/unexport"
|
56
|
+
end
|
57
|
+
|
58
|
+
def gpio_pin_dir
|
59
|
+
"#{gpio_path}/gpio#{converted_position}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def export
|
63
|
+
file_class.open(export_path, "w") { |f| f.write("#{ converted_position }") }
|
64
|
+
set_mode
|
65
|
+
end
|
66
|
+
|
67
|
+
def unexport
|
68
|
+
file_class.open(unexport_path, "w") { |f| f.write("#{converted_position}") }
|
69
|
+
end
|
70
|
+
|
71
|
+
def file_class
|
72
|
+
File
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
module IO
|
4
|
+
module Mapped
|
5
|
+
##
|
6
|
+
# Get the pin map as taken from the Bonescript. The Pinmap contains
|
7
|
+
# information on things like the pin mode, and the name of the pin on
|
8
|
+
# the filesystem. Checkout the documentation on {BBB::Pins::IO::PinMapper PinMapper} for more
|
9
|
+
# information and examples of the maps.
|
10
|
+
#
|
11
|
+
# @return [Hash] pin_map
|
12
|
+
#
|
13
|
+
def pin_map
|
14
|
+
return @pin_map unless @pin_map.nil?
|
15
|
+
|
16
|
+
map = PinMapper.map(self.position)
|
17
|
+
map_key = self.pin_map_key
|
18
|
+
|
19
|
+
unless map.respond_to?(map_key) && !map.send(map_key).nil?
|
20
|
+
raise ArgumentError, "#{self.position} is not a valid #{map_key.upcase} pin position"
|
21
|
+
end
|
22
|
+
|
23
|
+
@pin_map = map
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# Returns the map key of the current pin. e.g. GPIO or AIN. This key is
|
28
|
+
# used to check if the provided position actually can be used using the
|
29
|
+
# given IO.
|
30
|
+
#
|
31
|
+
# @return [Symbol] Map key
|
32
|
+
#
|
33
|
+
def pin_map_key
|
34
|
+
self.class.to_s.split("::").last.downcase.to_sym
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,224 @@
|
|
1
|
+
module BBB
|
2
|
+
module Pins
|
3
|
+
module IO
|
4
|
+
##
|
5
|
+
# This class provides a convenient way of mapping a JSON representation of the
|
6
|
+
# pins, taken from the bonescript sourcecode, into Ruby objects. After
|
7
|
+
# converting the json to ruby objects the "normal" PinMapper will take the
|
8
|
+
# object structure and provide the actual mapping from the pin header
|
9
|
+
# positions, like p8_3 to the correct GPIO, I2C or WPM endpoints.
|
10
|
+
#
|
11
|
+
# This class should not be used directly to provide these mappings it's simply
|
12
|
+
# a helper class to get from JSON to Ruby.
|
13
|
+
#
|
14
|
+
class PinMapper
|
15
|
+
PIN_MAP_FILE = File.expand_path("../../../../../resources/pin_mappings.json", __FILE__)
|
16
|
+
|
17
|
+
class PinMap < Struct.new(:pins, :uart, :i2c); end
|
18
|
+
|
19
|
+
class Pin < Struct.new(:name, :gpio, :led, :mux, :key, :mux_reg_offset,
|
20
|
+
:options, :eeprom, :pwm, :ain, :scale); end
|
21
|
+
class UART < Struct.new(:devicetree, :rx, :tx); end
|
22
|
+
class I2C < Struct.new(:devicetree, :path, :sda, :scl); end
|
23
|
+
|
24
|
+
attr_reader :data
|
25
|
+
|
26
|
+
##
|
27
|
+
# Initialize a JSONPinMapper
|
28
|
+
#
|
29
|
+
# @param [Hash] hash Hash that was converted from json with the keys
|
30
|
+
# pinIndex, uart and i2c.
|
31
|
+
#
|
32
|
+
def initialize(hash)
|
33
|
+
@data = hash
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
# Factor a new JSONPinMapper based on a json_file that get's parsed to a
|
38
|
+
# hash.
|
39
|
+
#
|
40
|
+
# @param [String] json_filename The file that contains the JSON object with
|
41
|
+
# pin information
|
42
|
+
#
|
43
|
+
# @return JSONPinMapper instance
|
44
|
+
#
|
45
|
+
def self.convert(json_filename)
|
46
|
+
file = File.open(json_filename, "r")
|
47
|
+
hash = JSON.parse(file.read)
|
48
|
+
new(hash).convert
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Map a pin symbol and a type to a pin_map or raise an error when a pin
|
53
|
+
# can't be found.
|
54
|
+
#
|
55
|
+
# @param [Symbol] pin_symbol
|
56
|
+
# @params [Symbol] type Type of the pin.
|
57
|
+
#
|
58
|
+
def self.map(pin_symbol)
|
59
|
+
@map ||= convert(PIN_MAP_FILE)
|
60
|
+
begin
|
61
|
+
@map.pins.fetch(pin_symbol.upcase.to_sym)
|
62
|
+
rescue Exception => e
|
63
|
+
raise UnknownPinException, "Pin #{pin_symbol} could not be mapped"
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Convert from a the data hash to ruby objects
|
69
|
+
#
|
70
|
+
# @return [Struct] with pins, uart and i2c as keys.
|
71
|
+
# pins has a
|
72
|
+
#
|
73
|
+
def convert
|
74
|
+
pins = convert_pins(data["pinIndex"])
|
75
|
+
uart = convert_uart(data["uarts"])
|
76
|
+
i2c = convert_i2c(data["i2c"])
|
77
|
+
|
78
|
+
PinMap.new(pins, uart, i2c)
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Converts an array of pins into a hash with the pin key as a key and a Pin
|
83
|
+
# Struct as a value.
|
84
|
+
#
|
85
|
+
# Here is an example of a piece of the JSON code containing pin info:
|
86
|
+
#
|
87
|
+
# {
|
88
|
+
# "name": "USR0",
|
89
|
+
# "gpio": 53,
|
90
|
+
# "led": "usr0",
|
91
|
+
# "mux": "gpmc_a5",
|
92
|
+
# "key": "USR0",
|
93
|
+
# "muxRegOffset": "0x054",
|
94
|
+
# "options": [
|
95
|
+
# "gpmc_a5",
|
96
|
+
# "gmii2_txd0",
|
97
|
+
# "rgmii2_td0",
|
98
|
+
# "rmii2_txd0",
|
99
|
+
# "gpmc_a21",
|
100
|
+
# "pr1_mii1_rxd3",
|
101
|
+
# "eqep1b_in",
|
102
|
+
# "gpio1_21"
|
103
|
+
# ]
|
104
|
+
# }
|
105
|
+
#
|
106
|
+
# @param [Array<Hash>] array An array of Pin hashes
|
107
|
+
#
|
108
|
+
# @return [Hash] a hash with pin keys as keys and pin objects as values.
|
109
|
+
#
|
110
|
+
def convert_pins(array)
|
111
|
+
hash = {}
|
112
|
+
|
113
|
+
array.each do |pin_hash|
|
114
|
+
pin = Pin.new
|
115
|
+
pin_hash.each_pair do |key, value|
|
116
|
+
pin[underscore(key).to_sym] = value
|
117
|
+
end
|
118
|
+
hash[pin.key.upcase.to_sym] = pin
|
119
|
+
end
|
120
|
+
|
121
|
+
return hash
|
122
|
+
end
|
123
|
+
|
124
|
+
##
|
125
|
+
# Convert a hash of uarts to a hash with the uart folder (e.g. /dev/tty00)
|
126
|
+
# as the key and an uart object as the value.
|
127
|
+
#
|
128
|
+
# Here is an example of an individual UART hash:
|
129
|
+
#
|
130
|
+
# "/dev/ttyO1": {
|
131
|
+
# "devicetree": "BB-UART1",
|
132
|
+
# "rx": "P9_26",
|
133
|
+
# "tx": "P9_24"
|
134
|
+
# }
|
135
|
+
#
|
136
|
+
# @param [Hash] data_hash with strings as keys and hashes as values
|
137
|
+
#
|
138
|
+
# @return [Hash] with strings of uart positions (e.g. /dev/tty00) as keys
|
139
|
+
# and uart objects as values
|
140
|
+
#
|
141
|
+
def convert_uart(data_hash)
|
142
|
+
convert_hash_with_hashes(data_hash, UART)
|
143
|
+
end
|
144
|
+
|
145
|
+
##
|
146
|
+
# Convert a hash of I2Cs to a hash with the I2C folder as the key and a i2c
|
147
|
+
# object as the value
|
148
|
+
#
|
149
|
+
# Here is an example of an individual I2C hash:
|
150
|
+
#
|
151
|
+
# "/dev/i2c-1": {
|
152
|
+
# "devicetree": "BB-I2C1",
|
153
|
+
# "path": "/dev/i2c-2",
|
154
|
+
# "sda": "P9_18",
|
155
|
+
# "scl": "P9_17"
|
156
|
+
# }
|
157
|
+
#
|
158
|
+
# @param [Hash] data_hash with strings as keys and hashes as values
|
159
|
+
#
|
160
|
+
# @return [Hash] with strings of I2C folders as keys and I2C objects as
|
161
|
+
# values
|
162
|
+
#
|
163
|
+
def convert_i2c(data_hash)
|
164
|
+
convert_hash_with_hashes(data_hash, I2C)
|
165
|
+
end
|
166
|
+
|
167
|
+
private
|
168
|
+
|
169
|
+
##
|
170
|
+
# @see #convert_uart
|
171
|
+
#
|
172
|
+
def convert_hash_with_hashes(data_hash, object)
|
173
|
+
hash = {}
|
174
|
+
|
175
|
+
data_hash.each_pair do |filesystem, info_hash|
|
176
|
+
instance = object.new
|
177
|
+
info_hash.each_pair do |key, value|
|
178
|
+
instance[key] = value
|
179
|
+
end
|
180
|
+
|
181
|
+
hash[filesystem] = instance
|
182
|
+
end
|
183
|
+
|
184
|
+
return hash
|
185
|
+
end
|
186
|
+
|
187
|
+
##
|
188
|
+
# Makes an underscored, lowercase form from the expression in the string.
|
189
|
+
#
|
190
|
+
# Gracefully copied from ActiveSupport::Inflections
|
191
|
+
# http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-underscore
|
192
|
+
#
|
193
|
+
# Changes '::' to '/' to convert namespaces to paths.
|
194
|
+
#
|
195
|
+
# 'ActiveModel'.underscore # => "active_model"
|
196
|
+
# 'ActiveModel::Errors'.underscore # => "active_model/errors"
|
197
|
+
#
|
198
|
+
# As a rule of thumb you can think of +underscore+ as the inverse of
|
199
|
+
# +camelize+, though there are cases where that does not hold:
|
200
|
+
#
|
201
|
+
# 'SSLError'.underscore.camelize # => "SslError"
|
202
|
+
def underscore(camel_cased_word)
|
203
|
+
word = camel_cased_word.to_s.dup
|
204
|
+
word.gsub!('::', '/')
|
205
|
+
word.gsub!(/(?:([A-Za-z\d])|^)(#{acronym_regex})(?=\b|[^a-z])/) { "#{$1}#{$1 && '_'}#{$2.downcase}" }
|
206
|
+
word.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
|
207
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
208
|
+
word.tr!("-", "_")
|
209
|
+
word.downcase!
|
210
|
+
word
|
211
|
+
end
|
212
|
+
|
213
|
+
##
|
214
|
+
# Specifies acronyms. This is a shortcut approach to the full acronym
|
215
|
+
# functionality of Rails. Which can be found here:
|
216
|
+
# https://github.com/rails/rails/blob/4e327225947b933d5434509e02e98226c581adc1/activesupport/lib/active_support/inflector/inflections.rb#L47
|
217
|
+
#
|
218
|
+
def acronym_regex
|
219
|
+
/#{%w(I2C UART GPIO).join("|")}/
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|