pi_piper 2.0.beta.4 → 2.0.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.
- checksums.yaml +4 -4
- data/.gitignore +4 -0
- data/.rspec +3 -0
- data/.travis.yml +10 -0
- data/Gemfile +3 -3
- data/Gemfile.lock +39 -26
- data/LICENCE.md +23 -0
- data/README.md +53 -16
- data/Rakefile +4 -22
- data/examples/2_bit_counter/2_bit_counter.rb +21 -0
- data/examples/7-segment/7-segment.rb +37 -0
- data/examples/dsl_switch/dsl_switch.rb +15 -0
- data/examples/elro/README.md +75 -0
- data/examples/elro/docs/elro-dips.jpg +0 -0
- data/examples/elro/docs/elro-switch.jpg +0 -0
- data/examples/elro/docs/setup.jpg +0 -0
- data/examples/elro/docs/wireplan.jpg +0 -0
- data/examples/elro/docs/wrl10534.jpg +0 -0
- data/examples/elro/elro.rb +15 -0
- data/examples/elro/lib/elro_switch.rb +51 -0
- data/examples/elro/lib/elro_util.rb +64 -0
- data/examples/elro/spec/elro_spec.rb +35 -0
- data/examples/elro/spec/elro_util_spec.rb +51 -0
- data/examples/elro/spec/spec_helper.rb +6 -0
- data/examples/mcp3008/circuit.png +0 -0
- data/examples/mcp3008/mcp3008.rb +55 -0
- data/examples/mcp3008_spi/mcp3008_spi.rb +24 -0
- data/examples/morse_code/circuit.png +0 -0
- data/examples/morse_code/morse_code.rb +49 -0
- data/examples/simple_switch/circuit.png +0 -0
- data/examples/simple_switch/simple_switch.rb +10 -0
- data/lib/pi_piper.rb +5 -3
- data/lib/pi_piper/bcm2835.rb +84 -14
- data/lib/pi_piper/i2c.rb +0 -1
- data/lib/pi_piper/libbcm2835.so +0 -0
- data/lib/pi_piper/pin.rb +102 -63
- data/lib/pi_piper/pin_error.rb +3 -0
- data/lib/pi_piper/pin_values.rb +35 -0
- data/lib/pi_piper/platform.rb +5 -5
- data/lib/pi_piper/pwm.rb +95 -0
- data/lib/pi_piper/spi.rb +30 -45
- data/lib/pi_piper/stub_driver.rb +124 -0
- data/lib/pi_piper/version.rb +3 -0
- data/pi_piper.gemspec +24 -29
- data/spec/bcm2835_spec.rb +132 -0
- data/spec/i2c_spec.rb +62 -0
- data/spec/pin_spec.rb +140 -0
- data/spec/pwm_spec.rb +83 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/spi_spec.rb +38 -0
- data/spec/stub_driver_spec.rb +140 -0
- metadata +100 -26
- data/Manifest +0 -14
- data/lib/pi_piper/libbcm2835.img +0 -0
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
$LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
|
3
|
+
|
4
|
+
require 'pi_piper'
|
5
|
+
require 'elro_switch'
|
6
|
+
|
7
|
+
exit(0) unless ARGV[0]
|
8
|
+
|
9
|
+
device = ARGV[0].to_i
|
10
|
+
switch_on = ARGV[1]
|
11
|
+
key = [0,0,0,0,1]
|
12
|
+
|
13
|
+
pin = PiPiper::Pin.new(:pin => 17, :direction => :out)
|
14
|
+
elro = ElroSwitch.new(device, key, pin)
|
15
|
+
elro.switch(switch_on == "1")
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'elro_util'
|
2
|
+
|
3
|
+
# ElroSwitch is a little tool written to send trigger-events from a RaspberryPi
|
4
|
+
# to an Elro remote controlled switch.
|
5
|
+
#
|
6
|
+
# It works perfectly with PiPiper: https://github.com/jwhitehorn/pi_piper
|
7
|
+
#
|
8
|
+
# See README.md for more information.
|
9
|
+
#
|
10
|
+
# == CREDITS
|
11
|
+
# Written by Torsten Mangner (https://github.com/alphaone).
|
12
|
+
# This library is mostly a (heavily refactored) port from this python script
|
13
|
+
# http://pastebin.com/aRipYrZ6
|
14
|
+
# by Heiko H.,
|
15
|
+
# which is a port from a C++ snippet
|
16
|
+
# http://www.jer00n.nl/433send.cpp
|
17
|
+
# written by J. Lukas,
|
18
|
+
# and influenced by this Arduino source code
|
19
|
+
# http://gathering.tweakers.net/forum/view_message/34919677
|
20
|
+
# written by Piepersnijder.
|
21
|
+
class ElroSwitch
|
22
|
+
include ElroUtil
|
23
|
+
|
24
|
+
# devices: according to dipswitches on your Elro receivers
|
25
|
+
# or
|
26
|
+
# a numeric A = 1, B = 2, C = 4, D = 8, E = 16
|
27
|
+
# key: according to dipswitches on your Elro receivers
|
28
|
+
# pin: an object that responses to #update_value(bool) (like PiPiper::Pin)
|
29
|
+
def initialize(device, key, pin)
|
30
|
+
raise ArgumentError.new("key has to be of size 5") unless key.size == 5
|
31
|
+
raise ArgumentError.new("device has to be Numeric or Array") unless (device.is_a?(Numeric) or device.is_a?(Array))
|
32
|
+
raise ArgumentError.new("device has to be of size 5") if (device.is_a?(Array) and device.size != 5)
|
33
|
+
raise ArgumentError.new("device has to be between 0 and 31") if (device.is_a?(Numeric) and !((0..31) === device))
|
34
|
+
raise ArgumentError.new("pin has no method :update_value") unless pin.respond_to?(:update_value)
|
35
|
+
@key = key
|
36
|
+
@device = device
|
37
|
+
@pin = pin
|
38
|
+
end
|
39
|
+
|
40
|
+
def switch(switch)
|
41
|
+
sequence = []
|
42
|
+
sequence << ElroUtil.sequence_for_key(@key)
|
43
|
+
sequence << ElroUtil.sequence_for_device(@device)
|
44
|
+
sequence << ElroUtil.sequence_for_onoff(switch)
|
45
|
+
sequence << ElroUtil.sequence_for_static_part
|
46
|
+
|
47
|
+
pulses = ElroUtil.pulses_from_sequence(sequence.flatten)
|
48
|
+
ElroUtil.send_pulses(@pin, pulses)
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# ElroUtil will do the hard work for ElroSwitch
|
2
|
+
#
|
3
|
+
# == WARNING
|
4
|
+
# The Raspberry is not build to be the fastest hardware in the world.
|
5
|
+
# Ruby (MRI) is not fastest programming language (but still the best).
|
6
|
+
# The Elro Switch expects the 1280 signals for each switch-event to be
|
7
|
+
# transmitted with a frequency of 300 microseconds (but as I have observed
|
8
|
+
# will still operate while using frequencies from ≈100 to ≈600 microseconds
|
9
|
+
# per signal).
|
10
|
+
#
|
11
|
+
# This implementation (using PiPiper) reaches a frequency of around
|
12
|
+
# 500 microseconds on an RaspberryPi without any wait or sleep.
|
13
|
+
#
|
14
|
+
# Other implementation (in python or C) need to time their signals to
|
15
|
+
# not be too fast.
|
16
|
+
#
|
17
|
+
# Keep that in mind, if this code will run on faster hardware or faster Rubies.
|
18
|
+
module ElroUtil
|
19
|
+
|
20
|
+
DIP_OFF = 142
|
21
|
+
DIP_ON = 136
|
22
|
+
REPEAT = 10 # Number of transmissions
|
23
|
+
|
24
|
+
def ElroUtil.sequence_for_key(key)
|
25
|
+
key.map { |dip| (dip == 1) ? DIP_ON : DIP_OFF }
|
26
|
+
end
|
27
|
+
|
28
|
+
def ElroUtil.sequence_for_device(device)
|
29
|
+
if device.is_a?(Array)
|
30
|
+
device.map { |dip| dip == 1 ? DIP_ON : DIP_OFF }
|
31
|
+
elsif device.is_a?(Numeric)
|
32
|
+
ElroUtil.convert_to_bits(device, 5).reverse.map { |b| b ? DIP_ON : DIP_OFF }
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def ElroUtil.sequence_for_onoff(switch_on)
|
37
|
+
switch_on ? [DIP_ON, DIP_OFF] : [DIP_OFF, DIP_ON]
|
38
|
+
end
|
39
|
+
|
40
|
+
def ElroUtil.sequence_for_static_part
|
41
|
+
[128, 0, 0, 0]
|
42
|
+
end
|
43
|
+
|
44
|
+
def ElroUtil.pulses_from_sequence(sequence)
|
45
|
+
sequence.map { |part| ElroUtil.convert_to_bits(part, 8) }.flatten
|
46
|
+
end
|
47
|
+
|
48
|
+
def ElroUtil.send_pulses(pin, pulses, verbose=false)
|
49
|
+
pin.update_value(false)
|
50
|
+
start_time = Time.now
|
51
|
+
REPEAT.times do
|
52
|
+
pulses.each { |b| pin.update_value(b) }
|
53
|
+
end
|
54
|
+
end_time = Time.now
|
55
|
+
if verbose
|
56
|
+
puts "avg %.0f microsecs per pulse" % ((end_time - start_time) / (10 * 16 * 8) * 1_000_000)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def ElroUtil.convert_to_bits(num, length)
|
61
|
+
sprintf("%0#{length}d", num.to_s(2)).split("").map {|b| b.to_i & 1 == 1}
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ElroSwitch do
|
4
|
+
|
5
|
+
let(:pin) {double("pi_piper_pin", :update_value => nil)}
|
6
|
+
|
7
|
+
it "does not allow wrong key length" do
|
8
|
+
expect {ElroSwitch.new(1, [0,0,1,0,1,0], pin)}.to raise_error ArgumentError
|
9
|
+
end
|
10
|
+
|
11
|
+
it "does expect a Numeric or a List as device" do
|
12
|
+
expect {ElroSwitch.new([0,0,0,0,0], [0,1,0,1,0], pin)}.not_to raise_error ArgumentError
|
13
|
+
expect {ElroSwitch.new(15, [0,1,0,1,0], pin)}.not_to raise_error ArgumentError
|
14
|
+
expect {ElroSwitch.new("x", [0,1,0,1,0], pin)}.to raise_error ArgumentError
|
15
|
+
end
|
16
|
+
|
17
|
+
it "does expect a numeric device to be between 0 and 31" do
|
18
|
+
expect {ElroSwitch.new(-1, [0,1,0,1,0], pin)}.to raise_error ArgumentError
|
19
|
+
expect {ElroSwitch.new( 0, [0,1,0,1,0], pin)}.not_to raise_error ArgumentError
|
20
|
+
expect {ElroSwitch.new(31, [0,1,0,1,0], pin)}.not_to raise_error ArgumentError
|
21
|
+
expect {ElroSwitch.new(32, [0,1,0,1,0], pin)}.to raise_error ArgumentError
|
22
|
+
end
|
23
|
+
|
24
|
+
it "does not allow wrong device length" do
|
25
|
+
expect {ElroSwitch.new([0,0,0,0], [0,1,0,1,0], pin)}.to raise_error ArgumentError
|
26
|
+
end
|
27
|
+
|
28
|
+
it "sends pulses on switch" do
|
29
|
+
pin.should_receive(:update_value).exactly(16 * 8 * 10 + 1).times
|
30
|
+
|
31
|
+
elro = ElroSwitch.new(1, [0,0,1,0,1], pin)
|
32
|
+
elro.switch(true)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ElroUtil do
|
4
|
+
|
5
|
+
it "generates correct sequence for key" do
|
6
|
+
ElroUtil.sequence_for_key([0,0,1,0,1]).should ==
|
7
|
+
[142, 142, 136, 142, 136]
|
8
|
+
end
|
9
|
+
|
10
|
+
it "generates correct sequence for device" do
|
11
|
+
ElroUtil.sequence_for_device(7).should ==
|
12
|
+
[136, 136, 136, 142, 142]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "generates correct sequence for device as array" do
|
16
|
+
ElroUtil.sequence_for_device([1,1,1,0,0]).should ==
|
17
|
+
[136, 136, 136, 142, 142]
|
18
|
+
end
|
19
|
+
|
20
|
+
it "generates correct sequence for on/off" do
|
21
|
+
ElroUtil.sequence_for_onoff(true).should ==
|
22
|
+
[136, 142]
|
23
|
+
ElroUtil.sequence_for_onoff(false).should ==
|
24
|
+
[142, 136]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "generates correct sequence for static part" do
|
28
|
+
ElroUtil.sequence_for_static_part.should ==
|
29
|
+
[128, 0, 0, 0]
|
30
|
+
end
|
31
|
+
|
32
|
+
it "converts numbers to bits" do
|
33
|
+
ElroUtil.convert_to_bits(7, 8).should == [false, false, false, false, false, true, true, true]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "converts sequence to bit pulses" do
|
37
|
+
ElroUtil.pulses_from_sequence([136, 142]).should ==
|
38
|
+
[
|
39
|
+
true, false, false, false, true, false, false, false,
|
40
|
+
true, false, false, false, true, true, true, false
|
41
|
+
]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "sends pulses" do
|
45
|
+
pin = double("pi_piper_pin")
|
46
|
+
pin.should_receive(:update_value).exactly(40 + 1).times
|
47
|
+
|
48
|
+
ElroUtil.send_pulses(pin, [true, false, false, true])
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
Binary file
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'pi_piper'
|
2
|
+
#port of the Adafruit MCP3008 interface code found @ http://learn.adafruit.com/send-raspberry-pi-data-to-cosm/python-script
|
3
|
+
|
4
|
+
def read_adc(adc_pin, clockpin, adc_in, adc_out, cspin)
|
5
|
+
cspin.on
|
6
|
+
clockpin.off
|
7
|
+
cspin.off
|
8
|
+
|
9
|
+
command_out = adc_pin
|
10
|
+
command_out |= 0x18
|
11
|
+
command_out <<= 3
|
12
|
+
|
13
|
+
(0..4).each do
|
14
|
+
adc_in.update_value((command_out & 0x80) > 0)
|
15
|
+
command_out <<= 1
|
16
|
+
clockpin.on
|
17
|
+
clockpin.off
|
18
|
+
end
|
19
|
+
result = 0
|
20
|
+
|
21
|
+
(0..11).each do
|
22
|
+
clockpin.on
|
23
|
+
clockpin.off
|
24
|
+
result <<= 1
|
25
|
+
adc_out.read
|
26
|
+
if adc_out.on?
|
27
|
+
result |= 0x1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
cspin.on
|
32
|
+
|
33
|
+
result >> 1
|
34
|
+
end
|
35
|
+
|
36
|
+
clock = PiPiper::Pin.new :pin => 18, :direction => :out
|
37
|
+
adc_out = PiPiper::Pin.new :pin => 23
|
38
|
+
adc_in = PiPiper::Pin.new :pin => 24, :direction => :out
|
39
|
+
cs = PiPiper::Pin.new :pin => 25, :direction => :out
|
40
|
+
|
41
|
+
adc_pin = 0
|
42
|
+
|
43
|
+
loop do
|
44
|
+
value = read_adc(adc_pin, clock, adc_in, adc_out, cs)
|
45
|
+
invert = 1023 - value
|
46
|
+
mvolts = invert * (3300.0 / 1023.0)
|
47
|
+
if mvolts < 2700
|
48
|
+
temp = (mvolts - 380.0) / (2320.0 / 84.0)
|
49
|
+
else
|
50
|
+
temp = (mvolts - 2700.0) / (390.0 / 92.0) + 84.0
|
51
|
+
end
|
52
|
+
temp_f = (temp * 9.0 / 5.0) + 32
|
53
|
+
puts "Value = #{value}, invert = #{invert}, mvolts = #{mvolts}, temp = #{temp} C | #{temp_f} F"
|
54
|
+
sleep 1
|
55
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'pi_piper'
|
2
|
+
#special thanks to Jeremy Blythe, and his article @ http://jeremyblythe.blogspot.com/2012/09/raspberry-pi-hardware-spi-analog-inputs.html
|
3
|
+
#it greatly helped in getting the MCP3008 setup with SPI
|
4
|
+
|
5
|
+
adc_num = 0
|
6
|
+
|
7
|
+
loop do
|
8
|
+
value = 0
|
9
|
+
PiPiper::Spi.begin do |spi|
|
10
|
+
raw = spi.write [1, (8+adc_num)<<4, 0]
|
11
|
+
value = ((raw[1]&3) << 8) + raw[2]
|
12
|
+
end
|
13
|
+
|
14
|
+
invert = 1023 - value
|
15
|
+
mvolts = invert * (3300.0 / 1023.0)
|
16
|
+
if mvolts < 2700
|
17
|
+
temp = (mvolts - 380.0) / (2320.0 / 84.0)
|
18
|
+
else
|
19
|
+
temp = (mvolts - 2700.0) / (390.0 / 92.0) + 84.0
|
20
|
+
end
|
21
|
+
temp_f = (temp * 9.0 / 5.0) + 32
|
22
|
+
puts "Value = #{value}, invert = #{invert}, mvolts = #{mvolts}, temp = #{temp} C | #{temp_f} F"
|
23
|
+
sleep 1
|
24
|
+
end
|
Binary file
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'pi_piper'
|
2
|
+
|
3
|
+
unit = 0.1
|
4
|
+
dot = unit
|
5
|
+
dash = unit * 3
|
6
|
+
inter_element_gap = unit
|
7
|
+
short_gap = unit * 3
|
8
|
+
medium_gap = unit * 7
|
9
|
+
|
10
|
+
#http://en.wikipedia.org/wiki/Morse_code
|
11
|
+
character_timing = { "a" => [dot, dash], "b" => [dash, dot, dot, dot], "c" => [dash, dot, dash, dot],
|
12
|
+
"d" => [dash, dot, dot], "e" => [dot], "f" => [dot, dot, dash, dot],
|
13
|
+
"g" => [dash, dash, dot], "h" => [dot, dot, dot, dot], "i" => [dot, dot],
|
14
|
+
"j" => [dot, dash, dash, dash], "k" => [dash, dot, dash], "l" => [dot, dash, dot, dot],
|
15
|
+
"m" => [dash, dash], "n" => [dash, dot], "o" => [dash, dash, dash],
|
16
|
+
"p" => [dot, dash, dash, dot], "q" => [dash, dash, dot, dash], "r" => [dot, dash, dot],
|
17
|
+
"s" => [dot, dot, dot], "t" => [dash], "u" => [dot, dot, dash],
|
18
|
+
"v" => [dot, dot, dot, dash], "w" => [dot, dash, dash], "x" => [dash, dot, dot, dash],
|
19
|
+
"y" => [dash, dot, dash, dash], "z" => [dash, dash, dot, dot],
|
20
|
+
"0" => [dash, dash, dash, dash, dash], "1" => [dot, dash, dash, dash, dash],
|
21
|
+
"2" => [dot, dot, dash, dash, dash], "3" => [dot, dot, dot, dash, dash],
|
22
|
+
"4" => [dot, dot, dot, dot, dash], "5" => [dot, dot, dot, dot, dot],
|
23
|
+
"6" => [dash, dot, dot, dot, dot], "7" => [dash, dash, dot, dot, dot],
|
24
|
+
"8" => [dash, dash, dash, dot, dot], "9" => [dash, dash, dash, dash, dot]
|
25
|
+
}
|
26
|
+
|
27
|
+
pin = PiPiper::Pin.new(:pin => 17, :direction => :out)
|
28
|
+
pin.off
|
29
|
+
|
30
|
+
loop do
|
31
|
+
puts "Please type something"
|
32
|
+
something = gets.chomp.downcase
|
33
|
+
|
34
|
+
something.each_char do |letter|
|
35
|
+
if letter == " "
|
36
|
+
pin.off
|
37
|
+
sleep medium_gap
|
38
|
+
else
|
39
|
+
character_timing[letter].each do |timing|
|
40
|
+
pin.on
|
41
|
+
sleep timing
|
42
|
+
pin.off
|
43
|
+
sleep inter_element_gap
|
44
|
+
end
|
45
|
+
sleep short_gap - inter_element_gap
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
Binary file
|
data/lib/pi_piper.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'eventmachine'
|
2
|
-
Dir[File.dirname(__FILE__) + '/pi_piper/*.rb'].each {|file| require file
|
2
|
+
Dir[File.dirname(__FILE__) + '/pi_piper/*.rb'].each {|file| require file unless file.end_with?('bcm2835.rb') }
|
3
3
|
|
4
4
|
module PiPiper
|
5
5
|
extend self
|
@@ -11,7 +11,7 @@ module PiPiper
|
|
11
11
|
# Options hash. Options include `:pin`, `:invert` and `:trigger`.
|
12
12
|
#
|
13
13
|
def watch(options, &block)
|
14
|
-
Thread.new do
|
14
|
+
new_thread = Thread.new do
|
15
15
|
pin = PiPiper::Pin.new(options)
|
16
16
|
loop do
|
17
17
|
pin.wait_for_change
|
@@ -21,7 +21,9 @@ module PiPiper
|
|
21
21
|
pin.instance_exec &block
|
22
22
|
end
|
23
23
|
end
|
24
|
-
end
|
24
|
+
end
|
25
|
+
new_thread.abort_on_exception = true
|
26
|
+
new_thread
|
25
27
|
end
|
26
28
|
|
27
29
|
#Defines an event block to be executed after a pin either goes high or low.
|
data/lib/pi_piper/bcm2835.rb
CHANGED
@@ -5,7 +5,8 @@ module PiPiper
|
|
5
5
|
# It serves as an FFI library for PiPiper::SPI & PiPiper::I2C.
|
6
6
|
module Bcm2835
|
7
7
|
extend FFI::Library
|
8
|
-
ffi_lib File.dirname(__FILE__) + '/libbcm2835.
|
8
|
+
ffi_lib File.dirname(__FILE__) + '/libbcm2835.so'
|
9
|
+
@pins = []
|
9
10
|
|
10
11
|
SPI_MODE0 = 0
|
11
12
|
SPI_MODE1 = 1
|
@@ -20,27 +21,97 @@ module PiPiper
|
|
20
21
|
attach_function :init, :bcm2835_init, [], :uint8
|
21
22
|
attach_function :close, :bcm2835_close, [], :uint8
|
22
23
|
|
24
|
+
# Sets the Function Select register for the given pin, which configures the pin as Input, Output or one of the 6 alternate functions.
|
25
|
+
attach_function :gpio_select_function, :bcm2835_gpio_fsel, [:uint8, :uint8], :void
|
26
|
+
# attach_function :gpio_set, :bcm2835_gpio_set, [:uint8], :void
|
27
|
+
# attach_function :gpio_clear, :bcm2835_gpio_clr, [:uint8], :void
|
28
|
+
# attach_function :gpio_level, :bcm2835_gpio_lev, [:uint8], :uint8
|
29
|
+
|
23
30
|
#pin support...
|
24
|
-
attach_function :pin_set_pud,
|
31
|
+
attach_function :pin_set_pud, :bcm2835_gpio_set_pud, [:uint8, :uint8], :void
|
25
32
|
|
26
33
|
def self.pin_input(pin)
|
27
|
-
|
28
|
-
|
34
|
+
export(pin)
|
35
|
+
pin_direction(pin, 'in')
|
29
36
|
end
|
30
|
-
|
37
|
+
|
31
38
|
def self.pin_set(pin, value)
|
32
|
-
|
39
|
+
raise PiPiper::PinError, "Pin #{pin} not exported" unless exported?(pin)
|
40
|
+
File.write("/sys/class/gpio/gpio#{pin}/value", value)
|
33
41
|
end
|
34
|
-
|
35
|
-
def
|
36
|
-
|
37
|
-
|
42
|
+
|
43
|
+
def self.pin_output(pin)
|
44
|
+
export(pin)
|
45
|
+
pin_direction(pin, 'out')
|
38
46
|
end
|
39
|
-
|
47
|
+
|
40
48
|
def self.pin_read(pin)
|
49
|
+
raise PiPiper::PinError, "Pin #{pin} not exported" unless exported?(pin)
|
41
50
|
File.read("/sys/class/gpio/gpio#{pin}/value").to_i
|
42
51
|
end
|
43
52
|
|
53
|
+
#PWM support...
|
54
|
+
attach_function :pwm_clock, :bcm2835_pwm_set_clock, [:uint32], :void
|
55
|
+
attach_function :pwm_mode, :bcm2835_pwm_set_mode, [:uint8, :uint8, :uint8], :void
|
56
|
+
attach_function :pwm_range, :bcm2835_pwm_set_range, [:uint8, :uint32], :void
|
57
|
+
attach_function :pwm_data, :bcm2835_pwm_set_data, [:uint8, :uint32], :void
|
58
|
+
|
59
|
+
def self.pin_direction(pin, direction)
|
60
|
+
raise PiPiper::PinError, "Pin #{pin} not exported" unless exported?(pin)
|
61
|
+
File.write("/sys/class/gpio/gpio#{pin}/direction", direction)
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.export(pin)
|
65
|
+
File.write('/sys/class/gpio/export', pin)
|
66
|
+
@pins << pin unless @pins.include?(pin)
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.unexport_pin(pin)
|
70
|
+
File.write('/sys/class/gpio/unexport', pin)
|
71
|
+
@pins.delete(pin)
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.unexport_all
|
75
|
+
@pins.dup.each { |pin| unexport_pin(pin) }
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.exported_pins
|
79
|
+
@pins
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.exported?(pin)
|
83
|
+
@pins.include?(pin)
|
84
|
+
end
|
85
|
+
|
86
|
+
# Support "none", "rising", "falling", or "both"
|
87
|
+
def self.pin_set_edge(pin, trigger)
|
88
|
+
raise PiPiper::PinError, "Pin #{pin} not exported" unless exported?(pin)
|
89
|
+
File.write("/sys/class/gpio/gpio#{pin}/edge", trigger)
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.pin_wait_for(pin, trigger)
|
93
|
+
pin_set_edge(pin, trigger)
|
94
|
+
|
95
|
+
fd = File.open("/sys/class/gpio/gpio#{pin}/value", "r")
|
96
|
+
value = nil
|
97
|
+
loop do
|
98
|
+
fd.read
|
99
|
+
IO.select(nil, nil, [fd], nil)
|
100
|
+
last_value = value
|
101
|
+
value = self.pin_read(pin)
|
102
|
+
if last_value != value
|
103
|
+
next if trigger == :rising and value == 0
|
104
|
+
next if trigger == :falling and value == 1
|
105
|
+
break
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
#NOTE to use: chmod 666 /dev/spidev0.0
|
111
|
+
def self.spidev_out(array)
|
112
|
+
File.open('/dev/spidev0.0', 'wb'){|f| f.write(array.pack('C*')) }
|
113
|
+
end
|
114
|
+
|
44
115
|
#SPI support...
|
45
116
|
attach_function :spi_begin, :bcm2835_spi_begin, [], :uint8
|
46
117
|
attach_function :spi_end, :bcm2835_spi_end, [], :uint8
|
@@ -65,11 +136,11 @@ module PiPiper
|
|
65
136
|
[100.kilohertz,
|
66
137
|
399.3610.kilohertz,
|
67
138
|
1.666.megahertz,
|
68
|
-
1.689.megahertz]
|
139
|
+
1.689.megahertz]
|
69
140
|
end
|
70
141
|
|
71
142
|
def self.spi_transfer_bytes(data)
|
72
|
-
data_out = FFI::MemoryPointer.new(data.count)
|
143
|
+
data_out = FFI::MemoryPointer.new(data.count)
|
73
144
|
data_in = FFI::MemoryPointer.new(data.count)
|
74
145
|
(0..data.count-1).each { |i| data_out.put_uint8(i, data[i]) }
|
75
146
|
|
@@ -91,6 +162,5 @@ module PiPiper
|
|
91
162
|
|
92
163
|
(0..bytes-1).map { |i| data_in.get_uint8(i) }
|
93
164
|
end
|
94
|
-
|
95
165
|
end
|
96
166
|
end
|