beaglebone 1.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.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +6 -0
- data/beaglebone.gemspec +12 -0
- data/examples/ain.rb +92 -0
- data/examples/gpio.rb +196 -0
- data/examples/i2c.rb +110 -0
- data/examples/pwm.rb +63 -0
- data/examples/shiftregister.rb +12 -0
- data/examples/spi.rb +62 -0
- data/examples/uart.rb +64 -0
- data/lib/beaglebone/ain.rb +480 -0
- data/lib/beaglebone/beaglebone.rb +287 -0
- data/lib/beaglebone/gpio.rb +598 -0
- data/lib/beaglebone/i2c.rb +186 -0
- data/lib/beaglebone/pwm.rb +479 -0
- data/lib/beaglebone/shiftregister.rb +21 -0
- data/lib/beaglebone/spi.rb +322 -0
- data/lib/beaglebone/uart.rb +388 -0
- data/lib/beaglebone.rb +8 -0
- metadata +63 -0
@@ -0,0 +1,186 @@
|
|
1
|
+
module Beaglebone
|
2
|
+
|
3
|
+
module I2C
|
4
|
+
|
5
|
+
I2C_SLAVE = 0x0703
|
6
|
+
|
7
|
+
@i2cstatus = {}
|
8
|
+
@i2cmutex = Mutex.new
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :i2cstatus, :i2cmutex
|
12
|
+
|
13
|
+
def write(i2c, address, data)
|
14
|
+
check_i2c_enabled(i2c)
|
15
|
+
|
16
|
+
lock_i2c(i2c) do
|
17
|
+
i2c_fd = get_i2c_status(i2c, :fd_i2c)
|
18
|
+
|
19
|
+
#set the slave address to communicate with
|
20
|
+
i2c_fd.ioctl(I2C_SLAVE, address)
|
21
|
+
|
22
|
+
i2c_fd.syswrite(data)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def read(i2c, address, bytes=1, register=nil)
|
28
|
+
check_i2c_enabled(i2c)
|
29
|
+
|
30
|
+
data = ''
|
31
|
+
lock_i2c(i2c) do
|
32
|
+
i2c_fd = get_i2c_status(i2c, :fd_i2c)
|
33
|
+
|
34
|
+
#set the slave address to communicate with
|
35
|
+
i2c_fd.ioctl(I2C_SLAVE, address)
|
36
|
+
|
37
|
+
i2c_fd.syswrite(register) if register
|
38
|
+
|
39
|
+
data = i2c_fd.sysread(bytes)
|
40
|
+
end
|
41
|
+
|
42
|
+
data
|
43
|
+
end
|
44
|
+
|
45
|
+
def file(i2c)
|
46
|
+
check_i2c_enabled(i2c)
|
47
|
+
get_i2c_status(i2c, :fd_i2c)
|
48
|
+
end
|
49
|
+
|
50
|
+
def setup(i2c)
|
51
|
+
check_i2c_valid(i2c)
|
52
|
+
|
53
|
+
#make sure i2c not already enabled
|
54
|
+
return if get_i2c_status(i2c)
|
55
|
+
|
56
|
+
i2cinfo = I2CS[i2c]
|
57
|
+
|
58
|
+
#ensure dtb is loaded
|
59
|
+
Beaglebone::device_tree_load("#{i2cinfo[:devicetree]}") if i2cinfo[:devicetree]
|
60
|
+
|
61
|
+
#open the i2c device
|
62
|
+
i2c_fd = File.open(i2cinfo[:dev], 'r+')
|
63
|
+
|
64
|
+
Beaglebone::set_pin_status(i2cinfo[:scl], :i2c, i2cinfo[:id])
|
65
|
+
Beaglebone::set_pin_status(i2cinfo[:scl], :type, :i2c)
|
66
|
+
Beaglebone::set_pin_status(i2cinfo[:scl], :fd_i2c, i2c_fd)
|
67
|
+
|
68
|
+
Beaglebone::set_pin_status(i2cinfo[:sda], :i2c, i2cinfo[:id])
|
69
|
+
Beaglebone::set_pin_status(i2cinfo[:sda], :type, :i2c)
|
70
|
+
Beaglebone::set_pin_status(i2cinfo[:sda], :fd_i2c, i2c_fd)
|
71
|
+
|
72
|
+
set_i2c_status(i2c, :fd_i2c, i2c_fd)
|
73
|
+
set_i2c_status(i2c, :mutex, Mutex.new)
|
74
|
+
end
|
75
|
+
|
76
|
+
def disable(i2c)
|
77
|
+
check_i2c_valid(i2c)
|
78
|
+
check_i2c_enabled(i2c)
|
79
|
+
|
80
|
+
disable_i2c_pin(I2CS[i2c][:sda]) if I2CS[i2c][:sda]
|
81
|
+
disable_i2c_pin(I2CS[i2c][:scl]) if I2CS[i2c][:scl]
|
82
|
+
|
83
|
+
delete_i2c_status(i2c)
|
84
|
+
|
85
|
+
#removing i2c tree causes a crash... can't really disable.
|
86
|
+
#Beaglebone::device_tree_unload("#{I2CS[i2c][:devicetree]}") if I2CS[i2c][:devicetree]
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
def cleanup
|
91
|
+
#reset all i2cs we've used and unload the device tree
|
92
|
+
i2cstatus.clone.keys.each { |i2c| disable(i2c)}
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
def disable_i2c_pin(pin)
|
98
|
+
Beaglebone::check_valid_pin(pin, :i2c)
|
99
|
+
|
100
|
+
Beaglebone::delete_pin_status(pin)
|
101
|
+
end
|
102
|
+
|
103
|
+
def check_i2c_valid(i2c)
|
104
|
+
raise ArgumentError, "Invalid i2c Specified #{i2c.to_s}" unless I2CS[i2c] && I2CS[i2c][:sda]
|
105
|
+
i2cinfo = I2CS[i2c.to_sym.upcase]
|
106
|
+
|
107
|
+
unless i2cinfo[:scl] && [nil,:i2c].include?(Beaglebone::get_pin_status(i2cinfo[:scl], :type))
|
108
|
+
raise StandardError, "SCL Pin for #{i2c.to_s} in use"
|
109
|
+
end
|
110
|
+
|
111
|
+
unless i2cinfo[:sda] && [nil,:i2c].include?(Beaglebone::get_pin_status(i2cinfo[:sda], :type))
|
112
|
+
raise StandardError, "SDA Pin for #{i2c.to_s} in use"
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
def check_i2c_enabled(i2c)
|
118
|
+
raise ArgumentError, "i2c not enabled #{i2c.to_s}" unless get_i2c_status(i2c)
|
119
|
+
end
|
120
|
+
|
121
|
+
def lock_i2c(i2c)
|
122
|
+
check_i2c_enabled(i2c)
|
123
|
+
mutex = get_i2c_status(i2c, :mutex)
|
124
|
+
|
125
|
+
mutex.synchronize do
|
126
|
+
yield
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def get_i2c_status(i2c, key = nil)
|
131
|
+
i2cmutex.synchronize do
|
132
|
+
if key
|
133
|
+
i2cstatus[i2c] ? i2cstatus[i2c][key] : nil
|
134
|
+
else
|
135
|
+
i2cstatus[i2c]
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def set_i2c_status(i2c, key, value)
|
141
|
+
i2cmutex.synchronize do
|
142
|
+
i2cstatus[i2c] ||= {}
|
143
|
+
i2cstatus[i2c][key] = value
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def delete_i2c_status(i2c, key = nil)
|
148
|
+
i2cmutex.synchronize do
|
149
|
+
if key.nil?
|
150
|
+
i2cstatus.delete(i2c)
|
151
|
+
else
|
152
|
+
i2cstatus[i2c].delete(key) if i2cstatus[i2c]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
#oo interface
|
161
|
+
class I2CDevice
|
162
|
+
|
163
|
+
def initialize(i2c)
|
164
|
+
@i2c = i2c
|
165
|
+
I2C::setup(@i2c)
|
166
|
+
end
|
167
|
+
|
168
|
+
def read(address, bytes=1, register=nil)
|
169
|
+
I2C::read(@i2c, address, bytes, register)
|
170
|
+
end
|
171
|
+
|
172
|
+
def write(address, data)
|
173
|
+
I2C::write(@i2c, address, data)
|
174
|
+
end
|
175
|
+
|
176
|
+
def disable
|
177
|
+
I2C::disable(@i2c)
|
178
|
+
end
|
179
|
+
|
180
|
+
def file
|
181
|
+
I2C::file(@i2c)
|
182
|
+
end
|
183
|
+
|
184
|
+
end
|
185
|
+
|
186
|
+
end
|
@@ -0,0 +1,479 @@
|
|
1
|
+
# == pwm.rb
|
2
|
+
# This file contains the PWM control methods
|
3
|
+
module Beaglebone #:nodoc:
|
4
|
+
# AIN
|
5
|
+
# procedural methods for PWM control
|
6
|
+
# == Summary
|
7
|
+
# #start is called to enable a PWM pin
|
8
|
+
module PWM
|
9
|
+
|
10
|
+
# Polarity hash
|
11
|
+
POLARITIES = { :NORMAL => 0, :INVERTED => 1 }
|
12
|
+
|
13
|
+
class << self
|
14
|
+
|
15
|
+
# Initialize a PWM pin
|
16
|
+
#
|
17
|
+
# @param pin should be a symbol representing the header pin
|
18
|
+
# @param duty should specify the duty cycle
|
19
|
+
# @param frequency should specify cycles per second
|
20
|
+
# @param polarity optional, should specify the polarity, :NORMAL or :INVERTED
|
21
|
+
# @param run optional, if false, pin will be configured but will not run
|
22
|
+
#
|
23
|
+
# @example
|
24
|
+
# PWM.start(:P9_14, 90, 10, :NORMAL)
|
25
|
+
def start(pin, duty=nil, frequency=nil, polarity=nil, run=true)
|
26
|
+
#make sure the pwm controller dtb is loaded
|
27
|
+
Beaglebone::device_tree_load(TREES[:PWM][:global])
|
28
|
+
|
29
|
+
Beaglebone::check_valid_pin(pin, :pwm)
|
30
|
+
|
31
|
+
#if pin is enabled for something else, disable it
|
32
|
+
if Beaglebone::get_pin_status(pin) && Beaglebone::get_pin_status(pin, :type) != :pwm
|
33
|
+
Beaglebone::disable_pin(pin)
|
34
|
+
end
|
35
|
+
|
36
|
+
#load device tree for pin if not already loaded
|
37
|
+
unless Beaglebone::get_pin_status(pin, :type) == :pwm
|
38
|
+
Beaglebone::device_tree_load("#{TREES[:PWM][:pin]}#{pin}")
|
39
|
+
Beaglebone::set_pin_status(pin, :type, :pwm)
|
40
|
+
end
|
41
|
+
|
42
|
+
duty_fd = File.open("#{pwm_directory(pin)}/duty", 'r+')
|
43
|
+
period_fd = File.open("#{pwm_directory(pin)}/period", 'r+')
|
44
|
+
polarity_fd = File.open("#{pwm_directory(pin)}/polarity", 'r+')
|
45
|
+
run_fd = File.open("#{pwm_directory(pin)}/run", 'r+')
|
46
|
+
|
47
|
+
Beaglebone::set_pin_status(pin, :fd_duty, duty_fd)
|
48
|
+
Beaglebone::set_pin_status(pin, :fd_period, period_fd)
|
49
|
+
Beaglebone::set_pin_status(pin, :fd_polarity, polarity_fd)
|
50
|
+
Beaglebone::set_pin_status(pin, :fd_run, run_fd)
|
51
|
+
|
52
|
+
|
53
|
+
read_period_value(pin)
|
54
|
+
read_duty_value(pin)
|
55
|
+
read_polarity_value(pin)
|
56
|
+
|
57
|
+
run_fd.write('0')
|
58
|
+
run_fd.flush
|
59
|
+
|
60
|
+
set_polarity(pin, polarity) if polarity
|
61
|
+
set_frequency(pin, frequency) if frequency
|
62
|
+
set_duty_cycle(pin, duty) if duty
|
63
|
+
|
64
|
+
if run
|
65
|
+
run_fd.write('1')
|
66
|
+
run_fd.flush
|
67
|
+
end
|
68
|
+
|
69
|
+
raise StandardError, "Could not start PWM: #{pin}" unless read_run_value(pin) == 1
|
70
|
+
true
|
71
|
+
end
|
72
|
+
|
73
|
+
# Returns true if specified pin is enabled in PWM mode, else false
|
74
|
+
def enabled?(pin)
|
75
|
+
return true if Beaglebone::get_pin_status(pin, :type) == :pwm
|
76
|
+
|
77
|
+
return false unless valid?(pin)
|
78
|
+
if Dir.exists?(pwm_directory(pin))
|
79
|
+
|
80
|
+
start(pin, nil, nil, nil, false)
|
81
|
+
return true
|
82
|
+
end
|
83
|
+
false
|
84
|
+
end
|
85
|
+
|
86
|
+
# Stop PWM output on specified pin
|
87
|
+
#
|
88
|
+
# @param pin should be a symbol representing the header pin
|
89
|
+
def stop(pin)
|
90
|
+
Beaglebone::check_valid_pin(pin, :pwm)
|
91
|
+
|
92
|
+
return false unless enabled?(pin)
|
93
|
+
|
94
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless Beaglebone::get_pin_status(pin, :type) == :pwm
|
95
|
+
|
96
|
+
run_fd = Beaglebone::get_pin_status(pin, :fd_run)
|
97
|
+
|
98
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless run_fd
|
99
|
+
|
100
|
+
run_fd.write('0')
|
101
|
+
run_fd.flush
|
102
|
+
|
103
|
+
raise StandardError, "Could not stop PWM: #{pin}" unless read_run_value(pin) == 0
|
104
|
+
true
|
105
|
+
end
|
106
|
+
|
107
|
+
# Start PWM output on specified pin. Pin must have been previously started
|
108
|
+
#
|
109
|
+
# @param pin should be a symbol representing the header pin
|
110
|
+
def run(pin)
|
111
|
+
Beaglebone::check_valid_pin(pin, :pwm)
|
112
|
+
|
113
|
+
return false unless enabled?(pin)
|
114
|
+
|
115
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless Beaglebone::get_pin_status(pin, :type) == :pwm
|
116
|
+
|
117
|
+
run_fd = Beaglebone::get_pin_status(pin, :fd_run)
|
118
|
+
|
119
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless run_fd
|
120
|
+
|
121
|
+
run_fd.write('1')
|
122
|
+
run_fd.flush
|
123
|
+
|
124
|
+
raise StandardError, "Could not start PWM: #{pin}" unless read_run_value(pin) == 1
|
125
|
+
true
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
# Set polarity on specified pin
|
130
|
+
#
|
131
|
+
# @param pin should be a symbol representing the header pin
|
132
|
+
# @param polarity should specify the polarity, :NORMAL or :INVERTED
|
133
|
+
# @example
|
134
|
+
# PWM.set_polarity(:P9_14, :INVERTED)
|
135
|
+
def set_polarity(pin, polarity)
|
136
|
+
check_valid_polarity(polarity)
|
137
|
+
check_pwm_enabled(pin)
|
138
|
+
|
139
|
+
polarity_fd = Beaglebone::get_pin_status(pin, :fd_polarity)
|
140
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless polarity_fd
|
141
|
+
|
142
|
+
polarity_fd.write(POLARITIES[polarity.to_sym].to_s)
|
143
|
+
polarity_fd.flush
|
144
|
+
|
145
|
+
raise StandardError, "Could not set polarity: #{pin}" unless read_polarity_value(pin) == POLARITIES[polarity.to_sym]
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
# Set duty cycle of specified pin in percentage
|
150
|
+
#
|
151
|
+
# @param pin should be a symbol representing the header pin
|
152
|
+
# @param duty should specify the duty cycle in percentage
|
153
|
+
# @example
|
154
|
+
# PWM.set_duty_cycle(:P9_14, 25)
|
155
|
+
def set_duty_cycle(pin, duty, newperiod=nil)
|
156
|
+
|
157
|
+
raise ArgumentError, "Duty cycle must be >= 0 and <= 100, #{duty} invalid" if duty < 0 || duty > 100
|
158
|
+
check_pwm_enabled(pin)
|
159
|
+
|
160
|
+
|
161
|
+
fd = Beaglebone::get_pin_status(pin, :fd_duty)
|
162
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd
|
163
|
+
|
164
|
+
period = newperiod || Beaglebone::get_pin_status(pin, :period)
|
165
|
+
|
166
|
+
value = ((duty * period) / 100).to_i
|
167
|
+
|
168
|
+
fd.write(value.to_s)
|
169
|
+
fd.flush
|
170
|
+
|
171
|
+
raise StandardError, "Could not set duty cycle: #{pin} (#{value})" unless read_duty_value(pin) == value
|
172
|
+
|
173
|
+
value
|
174
|
+
|
175
|
+
end
|
176
|
+
|
177
|
+
|
178
|
+
# Set duty cycle of specified pin in nanoseconds
|
179
|
+
#
|
180
|
+
# @param pin should be a symbol representing the header pin
|
181
|
+
# @param duty should specify the duty cycle in nanoseconds
|
182
|
+
# @example
|
183
|
+
# PWM.set_duty_cycle_ns(:P9_14, 2500000)
|
184
|
+
def set_duty_cycle_ns(pin, duty)
|
185
|
+
|
186
|
+
check_pwm_enabled(pin)
|
187
|
+
|
188
|
+
fd = Beaglebone::get_pin_status(pin, :fd_duty)
|
189
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd
|
190
|
+
|
191
|
+
period = Beaglebone::get_pin_status(pin, :period)
|
192
|
+
|
193
|
+
duty = duty.to_i
|
194
|
+
|
195
|
+
if duty < 0 || duty > period
|
196
|
+
raise ArgumentError, "Duty cycle ns must be >= 0 and <= #{period} (current period), #{duty} invalid"
|
197
|
+
end
|
198
|
+
|
199
|
+
value = duty
|
200
|
+
|
201
|
+
fd.write(value.to_s)
|
202
|
+
fd.flush
|
203
|
+
|
204
|
+
raise StandardError, "Could not set duty cycle: #{pin} (#{value})" unless read_duty_value(pin) == value
|
205
|
+
|
206
|
+
value
|
207
|
+
end
|
208
|
+
|
209
|
+
# Set frequency of specified pin in cycles per second
|
210
|
+
#
|
211
|
+
# @param pin should be a symbol representing the header pin
|
212
|
+
# @param frequency should specify the frequency in cycles per second
|
213
|
+
# @example
|
214
|
+
# PWM.set_frequency(:P9_14, 100)
|
215
|
+
def set_frequency(pin, frequency)
|
216
|
+
frequency = frequency.to_i
|
217
|
+
raise ArgumentError, "Frequency must be > 0 and <= 1000000000, #{frequency} invalid" if frequency < 1 || frequency > 1000000000
|
218
|
+
check_pwm_enabled(pin)
|
219
|
+
|
220
|
+
fd = Beaglebone::get_pin_status(pin, :fd_period)
|
221
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd
|
222
|
+
|
223
|
+
duty_ns = Beaglebone::get_pin_status(pin, :duty)
|
224
|
+
duty_pct = Beaglebone::get_pin_status(pin, :duty_pct)
|
225
|
+
|
226
|
+
value = (1000000000 / frequency).to_i
|
227
|
+
|
228
|
+
#we can't set the frequency lower than the previous duty cycle
|
229
|
+
#adjust if necessary
|
230
|
+
if duty_ns > value
|
231
|
+
set_duty_cycle(pin, Beaglebone::get_pin_status(pin, :duty_pct), value)
|
232
|
+
end
|
233
|
+
|
234
|
+
fd.write(value.to_s)
|
235
|
+
fd.flush
|
236
|
+
|
237
|
+
raise StandardError, "Could not set frequency: #{pin} (#{value})" unless read_period_value(pin) == value
|
238
|
+
|
239
|
+
#adjust the duty cycle if we haven't already
|
240
|
+
if duty_ns <= value
|
241
|
+
set_duty_cycle(pin, duty_pct, value)
|
242
|
+
end
|
243
|
+
|
244
|
+
value
|
245
|
+
end
|
246
|
+
|
247
|
+
# Set frequency of specified pin based on period duration
|
248
|
+
#
|
249
|
+
# @param pin should be a symbol representing the header pin
|
250
|
+
# @param period should specify the length of a cycle in nanoseconds
|
251
|
+
#
|
252
|
+
# @example
|
253
|
+
# PWM.set_frequency_ns(:P9_14, 100000000)
|
254
|
+
def set_period_ns(pin, period)
|
255
|
+
period = period.to_i
|
256
|
+
raise ArgumentError, "period must be > 0 and <= 1000000000, #{period} invalid" if period < 1 || period > 1000000000
|
257
|
+
check_pwm_enabled(pin)
|
258
|
+
|
259
|
+
fd = Beaglebone::get_pin_status(pin, :fd_period)
|
260
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd
|
261
|
+
|
262
|
+
duty_ns = Beaglebone::get_pin_status(pin, :duty)
|
263
|
+
value = period.to_i
|
264
|
+
|
265
|
+
#we can't set the frequency lower than the previous duty cycle
|
266
|
+
#adjust if necessary
|
267
|
+
if duty_ns > value
|
268
|
+
set_duty_cycle(pin, Beaglebone::get_pin_status(pin, :duty_pct), value)
|
269
|
+
end
|
270
|
+
|
271
|
+
fd.write(value.to_s)
|
272
|
+
fd.flush
|
273
|
+
|
274
|
+
raise StandardError, "Could not set period: #{pin} (#{value})" unless read_period_value(pin) == value
|
275
|
+
|
276
|
+
#adjust the duty cycle if we haven't already
|
277
|
+
if duty_ns <= value
|
278
|
+
set_duty_cycle(pin, Beaglebone::get_pin_status(pin, :duty_pct), value)
|
279
|
+
end
|
280
|
+
|
281
|
+
value
|
282
|
+
end
|
283
|
+
|
284
|
+
#reset all PWM pins we've used to IN and unexport them
|
285
|
+
def cleanup
|
286
|
+
get_pwm_pins.each { |x| disable_pwm_pin(x) }
|
287
|
+
end
|
288
|
+
|
289
|
+
# Return an array of PWM pins in use
|
290
|
+
#
|
291
|
+
# @return [Array<Symbol>]
|
292
|
+
#
|
293
|
+
# @example
|
294
|
+
# PWM.get_pwm_pins => [:P9_13, :P9_14]
|
295
|
+
def get_pwm_pins
|
296
|
+
Beaglebone.pinstatus.clone.select { |x,y| x if y[:type] == :pwm}.keys
|
297
|
+
end
|
298
|
+
|
299
|
+
# Disable a PWM pin
|
300
|
+
#
|
301
|
+
# @param pin should be a symbol representing the header pin
|
302
|
+
def disable_pwm_pin(pin)
|
303
|
+
Beaglebone::check_valid_pin(pin, :pwm)
|
304
|
+
Beaglebone::delete_pin_status(pin) if Beaglebone::device_tree_unload("#{TREES[:PWM][:pin]}#{pin}")
|
305
|
+
end
|
306
|
+
|
307
|
+
private
|
308
|
+
|
309
|
+
#ensure pin is valid pwm pin
|
310
|
+
def valid?(pin)
|
311
|
+
#check to see if pin exists
|
312
|
+
pin = pin.to_sym.upcase
|
313
|
+
|
314
|
+
return false unless PINS[pin]
|
315
|
+
return false unless PINS[pin][:pwm]
|
316
|
+
|
317
|
+
true
|
318
|
+
end
|
319
|
+
|
320
|
+
#ensure pin is pwm enabled
|
321
|
+
def check_pwm_enabled(pin)
|
322
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless enabled?(pin)
|
323
|
+
end
|
324
|
+
|
325
|
+
#read run file
|
326
|
+
def read_run_value(pin)
|
327
|
+
check_pwm_enabled(pin)
|
328
|
+
|
329
|
+
fd = Beaglebone::get_pin_status(pin, :fd_run)
|
330
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd
|
331
|
+
|
332
|
+
fd.rewind
|
333
|
+
fd.read.strip.to_i
|
334
|
+
end
|
335
|
+
|
336
|
+
#read polarity file
|
337
|
+
def read_polarity_value(pin)
|
338
|
+
check_pwm_enabled(pin)
|
339
|
+
|
340
|
+
fd = Beaglebone::get_pin_status(pin, :fd_polarity)
|
341
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd
|
342
|
+
|
343
|
+
fd.rewind
|
344
|
+
value = fd.read.strip.to_i
|
345
|
+
|
346
|
+
Beaglebone::set_pin_status(pin, :polarity, value)
|
347
|
+
|
348
|
+
end
|
349
|
+
|
350
|
+
#read duty file
|
351
|
+
def read_duty_value(pin)
|
352
|
+
check_pwm_enabled(pin)
|
353
|
+
|
354
|
+
fd = Beaglebone::get_pin_status(pin, :fd_duty)
|
355
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd
|
356
|
+
|
357
|
+
fd.rewind
|
358
|
+
value = fd.read.strip.to_i
|
359
|
+
|
360
|
+
Beaglebone::set_pin_status(pin, :duty, value)
|
361
|
+
Beaglebone::set_pin_status(pin, :duty_pct, ((value * 100) / Beaglebone::get_pin_status(pin, :period).to_i))
|
362
|
+
|
363
|
+
value
|
364
|
+
end
|
365
|
+
|
366
|
+
#read period file
|
367
|
+
def read_period_value(pin)
|
368
|
+
check_pwm_enabled(pin)
|
369
|
+
|
370
|
+
fd = Beaglebone::get_pin_status(pin, :fd_period)
|
371
|
+
raise StandardError, "Pin is not PWM enabled: #{pin}" unless fd
|
372
|
+
|
373
|
+
fd.rewind
|
374
|
+
value = fd.read.strip.to_i
|
375
|
+
|
376
|
+
Beaglebone::set_pin_status(pin, :period, value)
|
377
|
+
Beaglebone::set_pin_status(pin, :duty_pct, ((Beaglebone::get_pin_status(pin, :duty).to_i * 100) / value).to_i)
|
378
|
+
|
379
|
+
value
|
380
|
+
end
|
381
|
+
|
382
|
+
#return sysfs directory for pwm control
|
383
|
+
def pwm_directory(pin)
|
384
|
+
raise StandardError, 'Invalid Pin' unless valid?(pin)
|
385
|
+
Dir.glob("/sys/devices/ocp.*/pwm_test_#{pin}.*").first
|
386
|
+
end
|
387
|
+
|
388
|
+
#ensure polarity is valid
|
389
|
+
def check_valid_polarity(polarity)
|
390
|
+
#check to see if mode is valid
|
391
|
+
polarity = polarity.to_sym.upcase
|
392
|
+
raise ArgumentError, "No such polarity: #{polarity.to_s}" unless POLARITIES.include?(polarity)
|
393
|
+
end
|
394
|
+
|
395
|
+
end
|
396
|
+
end
|
397
|
+
|
398
|
+
# Object Oriented PWM Implementation.
|
399
|
+
# This treats the pin as an object.
|
400
|
+
class PWMPin
|
401
|
+
|
402
|
+
# Initialize a PWM pin
|
403
|
+
#
|
404
|
+
#
|
405
|
+
# @param duty should specify the duty cycle
|
406
|
+
# @param frequency should specify cycles per second
|
407
|
+
# @param polarity optional, should specify the polarity, :NORMAL or :INVERTED
|
408
|
+
# @param run optional, if false, pin will be configured but will not run
|
409
|
+
#
|
410
|
+
# @example
|
411
|
+
# p9_14 = PWMPin.new(:P9_14, 90, 10, :NORMAL)
|
412
|
+
def initialize(pin, duty=nil, frequency=nil, polarity=nil, run=true)
|
413
|
+
@pin = pin
|
414
|
+
PWM::start(@pin, duty, frequency, polarity, run)
|
415
|
+
end
|
416
|
+
|
417
|
+
# Stop PWM output on pin
|
418
|
+
def stop
|
419
|
+
PWM::stop(@pin)
|
420
|
+
end
|
421
|
+
|
422
|
+
# Start PWM output on pin. Pin must have been previously started
|
423
|
+
def run
|
424
|
+
PWM::run(@pin)
|
425
|
+
end
|
426
|
+
|
427
|
+
# Set polarity on pin
|
428
|
+
#
|
429
|
+
# @param polarity should specify the polarity, :NORMAL or :INVERTED
|
430
|
+
# @example
|
431
|
+
# p9_14.set_polarity(:INVERTED)
|
432
|
+
def set_polarity(polarity)
|
433
|
+
PWM::set_polarity(@pin, polarity)
|
434
|
+
end
|
435
|
+
|
436
|
+
# Set duty cycle of pin in percentage
|
437
|
+
#
|
438
|
+
#
|
439
|
+
# @param duty should specify the duty cycle in percentage
|
440
|
+
# @example
|
441
|
+
# p9_14.set_duty_cycle(25)
|
442
|
+
def set_duty_cycle(duty, newperiod=nil)
|
443
|
+
PWM::set_duty_cycle(@pin, duty, newperiod)
|
444
|
+
end
|
445
|
+
|
446
|
+
# Set duty cycle of pin in nanoseconds
|
447
|
+
#
|
448
|
+
# @param duty should specify the duty cycle in nanoseconds
|
449
|
+
# @example
|
450
|
+
# p9_14.set_duty_cycle_ns(2500000)
|
451
|
+
def set_duty_cycle_ns(duty)
|
452
|
+
PWM::set_duty_cycle_ns(@pin, duty)
|
453
|
+
end
|
454
|
+
|
455
|
+
# Set frequency of pin in cycles per second
|
456
|
+
#
|
457
|
+
# @param frequency should specify the frequency in cycles per second
|
458
|
+
# @example
|
459
|
+
# p9_14.set_frequency(100)
|
460
|
+
def set_frequency(frequency)
|
461
|
+
PWM::set_frequency(@pin, frequency)
|
462
|
+
end
|
463
|
+
|
464
|
+
# Set frequency of pin based on period duration
|
465
|
+
#
|
466
|
+
# @param period should specify the length of a cycle in nanoseconds
|
467
|
+
# @example
|
468
|
+
# p9_14.set_frequency_ns(100000000)
|
469
|
+
def set_period_ns(period)
|
470
|
+
PWM::set_period_ns(@pin, period)
|
471
|
+
end
|
472
|
+
|
473
|
+
# Disable PWM pin
|
474
|
+
def disable_pwm_pin
|
475
|
+
PWM::disable_pwm_pin(@pin)
|
476
|
+
end
|
477
|
+
end
|
478
|
+
|
479
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Beaglebone
|
2
|
+
class ShiftRegister
|
3
|
+
|
4
|
+
def initialize(latch_pin, clock_pin, data_pin, lsb=nil)
|
5
|
+
|
6
|
+
@latch_pin = latch_pin
|
7
|
+
@clock_pin = clock_pin
|
8
|
+
@data_pin = data_pin
|
9
|
+
@lsb = lsb
|
10
|
+
|
11
|
+
GPIO::pin_mode(@latch_pin, :OUT)
|
12
|
+
GPIO::pin_mode(@clock_pin, :OUT)
|
13
|
+
GPIO::pin_mode(@data_pin, :OUT)
|
14
|
+
end
|
15
|
+
|
16
|
+
def shiftout(data, lsb=nil)
|
17
|
+
GPIO::shift_out(@latch_pin, @clock_pin, @data_pin, data, lsb || @lsb)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|