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