beaglebone 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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