pi_piper 1.9.9 → 2.0.beta.1
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/Gemfile +1 -3
- data/Gemfile.lock +12 -42
- data/README.md +8 -38
- data/Rakefile +7 -8
- data/lib/pi_piper.rb +2 -41
- data/lib/pi_piper/bcm2835.rb +12 -46
- data/lib/pi_piper/i2c.rb +1 -4
- data/lib/pi_piper/libbcm2835.img +0 -0
- data/lib/pi_piper/pin.rb +43 -98
- data/lib/pi_piper/platform.rb +4 -6
- data/lib/pi_piper/spi.rb +15 -30
- data/pi_piper.gemspec +8 -19
- metadata +14 -99
- data/.gitignore +0 -4
- data/.rspec +0 -3
- data/.travis.yml +0 -8
- data/examples/2_bit_counter/2_bit_counter.rb +0 -22
- data/examples/7-segment/7-segment.rb +0 -37
- data/examples/dsl_switch/dsl_switch.rb +0 -15
- data/examples/mcp3008/circuit.png +0 -0
- data/examples/mcp3008/mcp3008.rb +0 -55
- data/examples/mcp3008_spi/mcp3008_spi.rb +0 -24
- data/examples/morse_code/circuit.png +0 -0
- data/examples/morse_code/morse_code.rb +0 -43
- data/examples/simple_switch/circuit.png +0 -0
- data/examples/simple_switch/simple_switch.rb +0 -10
- data/lib/pi_piper/libbcm2835.so +0 -0
- data/lib/pi_piper/pin_error.rb +0 -3
- data/lib/pi_piper/pin_values.rb +0 -10
- data/lib/pi_piper/stub_driver.rb +0 -107
- data/spec/i2c_spec.rb +0 -83
- data/spec/pin_spec.rb +0 -149
- data/spec/pull_mode_spec.rb +0 -70
- data/spec/spec_helper.rb +0 -7
- data/spec/spi_spec.rb +0 -44
- data/spec/stub_driver_spec.rb +0 -140
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cecbad62bc8eeedf7e061bfc03396691f584ee82
|
4
|
+
data.tar.gz: 5c22774ad6b6c737019baa7802c99934668f537a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dac9621e23d30b021ead1b74f30496fedfa93474346bb1656fb5a9f1a882e7bedfbdff87c28e6b3b4c3c84adb39427599a37c1eedd3c9fde9f318c22e7e3d5c7
|
7
|
+
data.tar.gz: 7167326e0245ee3a3272fc926298b94d7aa2b4e893c5b20f8ce5bb6a84414efca45bb5776adac1454a60f4e8f7c2eb4b3c9d792c623c5926ccbdfa006d89f008
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,10 +1,3 @@
|
|
1
|
-
PATH
|
2
|
-
remote: .
|
3
|
-
specs:
|
4
|
-
pi_piper (2.0.beta.11)
|
5
|
-
eventmachine (= 1.0.9)
|
6
|
-
ffi
|
7
|
-
|
8
1
|
GEM
|
9
2
|
remote: https://rubygems.org/
|
10
3
|
specs:
|
@@ -16,50 +9,27 @@ GEM
|
|
16
9
|
rake (>= 0.9.2)
|
17
10
|
rdoc (>= 3.6.1)
|
18
11
|
rubyforge (>= 2.0.4)
|
19
|
-
|
20
|
-
ffi (1.9.0)
|
12
|
+
ffi (1.4.0)
|
21
13
|
gemcutter (0.7.1)
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
rspec-expectations (~> 3.4.0)
|
34
|
-
rspec-mocks (~> 3.4.0)
|
35
|
-
rspec-core (3.4.1)
|
36
|
-
rspec-support (~> 3.4.0)
|
37
|
-
rspec-expectations (3.4.0)
|
38
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
39
|
-
rspec-support (~> 3.4.0)
|
40
|
-
rspec-mocks (3.4.1)
|
41
|
-
diff-lcs (>= 1.2.0, < 2.0)
|
42
|
-
rspec-support (~> 3.4.0)
|
43
|
-
rspec-support (3.4.1)
|
14
|
+
json_pure (1.7.7)
|
15
|
+
rake (10.0.3)
|
16
|
+
rdoc (4.0.0)
|
17
|
+
rspec (2.14.1)
|
18
|
+
rspec-core (~> 2.14.0)
|
19
|
+
rspec-expectations (~> 2.14.0)
|
20
|
+
rspec-mocks (~> 2.14.0)
|
21
|
+
rspec-core (2.14.5)
|
22
|
+
rspec-expectations (2.14.2)
|
23
|
+
diff-lcs (>= 1.1.3, < 2.0)
|
24
|
+
rspec-mocks (2.14.3)
|
44
25
|
rubyforge (2.0.4)
|
45
26
|
json_pure (>= 1.1.7)
|
46
|
-
simplecov (0.7.1)
|
47
|
-
multi_json (~> 1.0)
|
48
|
-
simplecov-html (~> 0.7.1)
|
49
|
-
simplecov-html (0.7.1)
|
50
27
|
|
51
28
|
PLATFORMS
|
52
29
|
ruby
|
53
30
|
|
54
31
|
DEPENDENCIES
|
55
32
|
echoe
|
56
|
-
eventmachine (~> 1.0.9)
|
57
33
|
ffi
|
58
|
-
mocha
|
59
|
-
pi_piper!
|
60
34
|
rake
|
61
35
|
rspec
|
62
|
-
simplecov
|
63
|
-
|
64
|
-
BUNDLED WITH
|
65
|
-
1.11.2
|
data/README.md
CHANGED
@@ -1,16 +1,14 @@
|
|
1
1
|
## Overview
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
Pi Piper brings event driven programming to the Raspberry Pi's GPIO pins. Pi Piper works with all revisions of the Raspberry Pi,
|
3
|
+
Pi Piper brings event driven programming to the Raspberry Pi's GPIO pins. Pi Piper works with all revisions of the Raspberry Pi,
|
6
4
|
and has been tested with Ruby 1.9.3 & 2.0 under both [Raspbian "wheezy"](http://www.raspberrypi.org/downloads) and [Occidentalis v0.2](http://learn.adafruit.com/adafruit-raspberry-pi-educational-linux-distro/occidentalis-v0-dot-2).
|
7
5
|
|
8
6
|
To get started:
|
9
7
|
|
10
8
|
If you do not already have Ruby installed, first you'll need to:
|
11
|
-
|
9
|
+
|
12
10
|
sudo apt-get install ruby ruby1.9.1-dev
|
13
|
-
|
11
|
+
|
14
12
|
Despite one of the packages being titled "ruby1.9.1-dev", the above command will install Ruby 1.9.3 (as of January 2013) and the Ruby dev tools.
|
15
13
|
|
16
14
|
To install Pi Piper:
|
@@ -40,7 +38,7 @@ PiPiper.wait
|
|
40
38
|
|
41
39
|
Your block will be called when a change to the pin's state is detected.
|
42
40
|
|
43
|
-
When using pins as input, you can use internal resistors to pull the pin
|
41
|
+
When using pins as input, you can use internal resistors to pull the pin
|
44
42
|
up or pull down. This is important if you use open-collector sensors
|
45
43
|
which have floating output in some states.
|
46
44
|
|
@@ -65,26 +63,15 @@ sleep 1
|
|
65
63
|
pin.off
|
66
64
|
```
|
67
65
|
|
68
|
-
_please note, in the above context "pin" refers to the GPIO number of the Raspberry Pi._
|
69
|
-
|
70
66
|
### SPI
|
71
|
-
Starting with version 1.2, Pi Piper offers SPI support.
|
67
|
+
Starting with version 1.2, Pi Piper offers SPI support.
|
72
68
|
|
73
69
|
```ruby
|
74
|
-
PiPiper::Spi.begin do
|
75
|
-
puts write [0x01, 0x80, 0x00]
|
70
|
+
PiPiper::Spi.begin do
|
71
|
+
puts write [0x01, 0x80, 0x00]
|
76
72
|
end
|
77
73
|
```
|
78
74
|
|
79
|
-
If you are using an operating system that supports `/dev/spidev0.0` like the [adafruit
|
80
|
-
distro][adafruit-linux] you can also write to the spi using `PiPiper::Spi.spidev_out`
|
81
|
-
|
82
|
-
```ruby
|
83
|
-
# Example writing red, green, blue to a string of WS2801 pixels
|
84
|
-
PiPiper::Spi.spidev_out([255,0,0,0,255,0,0,0,255])
|
85
|
-
```
|
86
|
-
[adafruit-linux]:http://learn.adafruit.com/adafruit-raspberry-pi-educational-linux-distro/overview
|
87
|
-
|
88
75
|
## Documentation
|
89
76
|
|
90
77
|
API documentation for Pi Piper can be found at [rdoc.info](http://rdoc.info/github/jwhitehorn/pi_piper/frames/).
|
@@ -98,26 +85,9 @@ Looking for more examples/sample code for Pi Piper? Then check out the following
|
|
98
85
|
* [Project 3: 2-bit counter](https://github.com/jwhitehorn/pi_piper/wiki/Project-3:-2-bit-counter)
|
99
86
|
* [Project 4: MCP3008](https://github.com/jwhitehorn/pi_piper/wiki/Project-4:-MCP3008)
|
100
87
|
|
101
|
-
## Under the hood
|
102
|
-
|
103
|
-
PiPiper use the libbcm2835 library from Mike McCauley at airspayce.
|
104
|
-
|
105
|
-
http://www.airspayce.com/mikem/bcm2835/index.html
|
106
|
-
|
107
|
-
if you want to upgrade or downgrade the library for compatibility reason, get it and make it a shared object library :
|
108
|
-
|
109
|
-
```script
|
110
|
-
wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.49.tar.gz
|
111
|
-
tar zxvf bcm2835-1.49.tar.gz && cd bcm2835-1.49
|
112
|
-
./configure && make
|
113
|
-
sudo make check
|
114
|
-
sudo make install
|
115
|
-
cd src && cc -shared bcm2835.o -o libbcm2835.so
|
116
|
-
cp libbcm2835.so ~/pi_piper/lib/pi_piper
|
117
|
-
|
118
88
|
## License
|
119
89
|
|
120
|
-
Copyright (c) 2013, [Jason Whitehorn](https://github.com/jwhitehorn)
|
90
|
+
Copyright (c) 2013, [Jason Whitehorn](https://github.com/jwhitehorn)
|
121
91
|
All rights reserved.
|
122
92
|
|
123
93
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
data/Rakefile
CHANGED
@@ -1,24 +1,23 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
|
-
require '
|
4
|
+
require 'rake/testtask'
|
5
5
|
|
6
6
|
#rake manifest
|
7
7
|
#rake build_gemspec
|
8
|
-
#
|
9
|
-
#gem push xxx.gem
|
8
|
+
#rake release
|
10
9
|
|
11
|
-
Echoe.new('pi_piper', '2.0.beta.
|
10
|
+
Echoe.new('pi_piper', '2.0.beta.1') do |p|
|
12
11
|
p.description = "Event driven Raspberry Pi GPIO library"
|
13
12
|
p.url = "http://github.com/jwhitehorn/pi_piper"
|
14
13
|
p.author = "Jason Whitehorn"
|
15
14
|
p.email = "jason.whitehorn@gmail.com"
|
16
15
|
p.ignore_pattern = ["examples/**/*", "spec/**/*"]
|
17
|
-
p.dependencies = ['ffi'
|
16
|
+
p.dependencies = ['ffi']
|
18
17
|
end
|
19
18
|
|
20
19
|
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
Rake::TestTask.new do |t|
|
22
|
+
t.pattern = 'spec/**/*_spec.rb'
|
23
|
+
end
|
data/lib/pi_piper.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'eventmachine'
|
2
1
|
Dir[File.dirname(__FILE__) + '/pi_piper/*.rb'].each {|file| require file unless file.end_with?('bcm2835.rb') }
|
3
2
|
|
4
3
|
module PiPiper
|
@@ -11,7 +10,7 @@ module PiPiper
|
|
11
10
|
# Options hash. Options include `:pin`, `:invert` and `:trigger`.
|
12
11
|
#
|
13
12
|
def watch(options, &block)
|
14
|
-
|
13
|
+
Thread.new do
|
15
14
|
pin = PiPiper::Pin.new(options)
|
16
15
|
loop do
|
17
16
|
pin.wait_for_change
|
@@ -21,9 +20,7 @@ module PiPiper
|
|
21
20
|
pin.instance_exec &block
|
22
21
|
end
|
23
22
|
end
|
24
|
-
end
|
25
|
-
new_thread.abort_on_exception = true
|
26
|
-
new_thread
|
23
|
+
end.abort_on_exception = true
|
27
24
|
end
|
28
25
|
|
29
26
|
#Defines an event block to be executed after a pin either goes high or low.
|
@@ -35,44 +32,8 @@ module PiPiper
|
|
35
32
|
options[:trigger] = options.delete(:goes) == :high ? :rising : :falling
|
36
33
|
watch options, &block
|
37
34
|
end
|
38
|
-
|
39
|
-
#Defines an event block to be called on a regular schedule. The block will be passed the slave output.
|
40
|
-
#
|
41
|
-
# @param [Hash] options A hash of options.
|
42
|
-
# @option options [Fixnum] :every A frequency of time (in seconds) to poll the SPI slave.
|
43
|
-
# @option options [Fixnum] :slave The slave number to poll.
|
44
|
-
# @option options [Number|Array] :write Data to poll the SPI slave with.
|
45
|
-
def poll_spi(options, &block)
|
46
|
-
EM::PeriodicTimer.new(options[:every]) do
|
47
|
-
Spi.begin options[:slave] do
|
48
|
-
output = write options[:write]
|
49
|
-
block.call output
|
50
|
-
end
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
#Defines an event block to be called when SPI slave output meets certain characteristics.
|
55
|
-
#The block will be passed the slave output.
|
56
|
-
#
|
57
|
-
# @param [Hash] options A hash of options.
|
58
|
-
# @option options [Fixnum] :every A frequency of time (in seconds) to poll the SPI slave.
|
59
|
-
# @option options [Fixnum] :slave The slave number to poll.
|
60
|
-
# @option options [Number|Array] :write Data to poll the SPI slave with.
|
61
|
-
# @option options [Fixnum] :eq Tests for SPI slave output equality.
|
62
|
-
# @option options [Fixnum] :lt Tests for SPI slave output less than supplied value.
|
63
|
-
# @option options [Fixnum] :gt Tests for SPI slave output greater than supplied value.
|
64
|
-
def when_spi(options, &block)
|
65
|
-
poll_spi options do |value|
|
66
|
-
if (options[:eq] && value == options[:eq]) ||
|
67
|
-
(options[:lt] && value < options[:lt]) ||
|
68
|
-
(options[:gt] && value > options[:gt])
|
69
|
-
block.call value
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
35
|
|
74
36
|
#Prevents the main thread from exiting. Required when using PiPiper.watch
|
75
|
-
# @deprecated Please use EventMachine.run instead
|
76
37
|
def wait
|
77
38
|
loop do sleep 1 end
|
78
39
|
end
|
data/lib/pi_piper/bcm2835.rb
CHANGED
@@ -5,8 +5,7 @@ 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.
|
9
|
-
@pins = []
|
8
|
+
ffi_lib File.dirname(__FILE__) + '/libbcm2835.img'
|
10
9
|
|
11
10
|
SPI_MODE0 = 0
|
12
11
|
SPI_MODE1 = 1
|
@@ -20,54 +19,28 @@ module PiPiper
|
|
20
19
|
|
21
20
|
attach_function :init, :bcm2835_init, [], :uint8
|
22
21
|
attach_function :close, :bcm2835_close, [], :uint8
|
23
|
-
|
22
|
+
|
24
23
|
#pin support...
|
25
|
-
attach_function :pin_set_pud,
|
24
|
+
attach_function :pin_set_pud, :bcm2835_gpio_set_pud, [:uint8, :uint8], :void
|
26
25
|
|
27
26
|
def self.pin_input(pin)
|
28
|
-
export(pin)
|
29
|
-
|
27
|
+
File.open("/sys/class/gpio/export", "w") { |f| f.write("#{pin}") }
|
28
|
+
File.open("/sys/class/gpio/gpio#{pin}/direction", "w") { |f| f.write("in") }
|
30
29
|
end
|
31
|
-
|
30
|
+
|
32
31
|
def self.pin_set(pin, value)
|
33
32
|
File.open("/sys/class/gpio/gpio#{pin}/value", 'w') {|f| f.write("#{value}") }
|
34
33
|
end
|
35
|
-
|
34
|
+
|
36
35
|
def self.pin_output(pin)
|
37
|
-
export(pin)
|
38
|
-
|
36
|
+
File.open("/sys/class/gpio/export", "w") { |f| f.write("#{pin}") }
|
37
|
+
File.open(direction_file, "w") { |f| f.write("out") }
|
39
38
|
end
|
40
|
-
|
39
|
+
|
41
40
|
def self.pin_read(pin)
|
42
41
|
File.read("/sys/class/gpio/gpio#{pin}/value").to_i
|
43
42
|
end
|
44
43
|
|
45
|
-
def self.pin_direction(pin, direction)
|
46
|
-
File.open("/sys/class/gpio/gpio#{pin}/direction", 'w') do |f|
|
47
|
-
f.write(direction)
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Exports pin and subsequently locks it from outside access
|
52
|
-
def self.export(pin)
|
53
|
-
File.open('/sys/class/gpio/export', 'w') { |f| f.write("#{pin}") }
|
54
|
-
@pins << pin unless @pins.include?(pin)
|
55
|
-
end
|
56
|
-
|
57
|
-
def self.release_pin(pin)
|
58
|
-
File.open('/sys/class/gpio/unexport', 'w') { |f| f.write("#{pin}") }
|
59
|
-
@pins.delete(pin)
|
60
|
-
end
|
61
|
-
|
62
|
-
def self.release_pins
|
63
|
-
@pins.dup.each { |pin| release_pin(pin) }
|
64
|
-
end
|
65
|
-
|
66
|
-
#NOTE to use: chmod 666 /dev/spidev0.0
|
67
|
-
def self.spidev_out(array)
|
68
|
-
File.open('/dev/spidev0.0', 'wb'){|f| f.write(array.pack('C*')) }
|
69
|
-
end
|
70
|
-
|
71
44
|
#SPI support...
|
72
45
|
attach_function :spi_begin, :bcm2835_spi_begin, [], :uint8
|
73
46
|
attach_function :spi_end, :bcm2835_spi_end, [], :uint8
|
@@ -86,17 +59,16 @@ module PiPiper
|
|
86
59
|
attach_function :i2c_write, :bcm2835_i2c_write, [:pointer, :uint], :uint8
|
87
60
|
attach_function :i2c_set_address,:bcm2835_i2c_setSlaveAddress, [:uint8], :void
|
88
61
|
attach_function :i2c_set_clock_divider, :bcm2835_i2c_setClockDivider, [:uint16], :void
|
89
|
-
attach_function :i2c_read, :bcm2835_i2c_read, [:pointer, :uint], :uint8
|
90
62
|
|
91
63
|
def self.i2c_allowed_clocks
|
92
64
|
[100.kilohertz,
|
93
65
|
399.3610.kilohertz,
|
94
66
|
1.666.megahertz,
|
95
|
-
1.689.megahertz]
|
67
|
+
1.689.megahertz]
|
96
68
|
end
|
97
69
|
|
98
70
|
def self.spi_transfer_bytes(data)
|
99
|
-
data_out = FFI::MemoryPointer.new(data.count)
|
71
|
+
data_out = FFI::MemoryPointer.new(data.count)
|
100
72
|
data_in = FFI::MemoryPointer.new(data.count)
|
101
73
|
(0..data.count-1).each { |i| data_out.put_uint8(i, data[i]) }
|
102
74
|
|
@@ -112,11 +84,5 @@ module PiPiper
|
|
112
84
|
i2c_write data_out, data.count
|
113
85
|
end
|
114
86
|
|
115
|
-
def self.i2c_read_bytes(bytes)
|
116
|
-
data_in = FFI::MemoryPointer.new(bytes)
|
117
|
-
i2c_read(data_in, bytes) #TODO reason codes
|
118
|
-
|
119
|
-
(0..bytes-1).map { |i| data_in.get_uint8(i) }
|
120
|
-
end
|
121
87
|
end
|
122
88
|
end
|
data/lib/pi_piper/i2c.rb
CHANGED
@@ -28,6 +28,7 @@ module PiPiper
|
|
28
28
|
|
29
29
|
def self.clock=(clock)
|
30
30
|
valid_clocks = Platform.driver.i2c_allowed_clocks
|
31
|
+
|
31
32
|
raise "Invalid clock rate. Valid clocks are 100 kHz, 399.3610 kHz, 1.666 MHz and 1.689 MHz" unless valid_clocks.include? clock
|
32
33
|
|
33
34
|
Platform.driver.i2c_set_clock clock
|
@@ -42,10 +43,6 @@ module PiPiper
|
|
42
43
|
Platform.driver.i2c_transfer_bytes data
|
43
44
|
end
|
44
45
|
|
45
|
-
def read(bytes)
|
46
|
-
Platform.driver.i2c_read_bytes(bytes)
|
47
|
-
end
|
48
|
-
|
49
46
|
end
|
50
47
|
|
51
48
|
end
|
Binary file
|
data/lib/pi_piper/pin.rb
CHANGED
@@ -1,112 +1,72 @@
|
|
1
|
-
require_relative 'pin_values'
|
2
|
-
|
3
1
|
module PiPiper
|
4
2
|
# Represents a GPIO pin on the Raspberry Pi
|
5
3
|
class Pin
|
6
|
-
|
4
|
+
GPIO_PUD_OFF = 0
|
5
|
+
GPIO_PUD_DOWN = 1
|
6
|
+
GPIO_PUD_UP = 2
|
7
7
|
|
8
|
-
attr_reader :pin, :last_value, :direction, :invert
|
8
|
+
attr_reader :pin, :last_value, :value, :direction, :invert
|
9
9
|
|
10
10
|
#Initializes a new GPIO pin.
|
11
11
|
#
|
12
12
|
# @param [Hash] options A hash of options
|
13
13
|
# @option options [Fixnum] :pin The pin number to initialize. Required.
|
14
|
-
#
|
15
|
-
# @option options [
|
16
|
-
# either :
|
17
|
-
#
|
18
|
-
# @option options [Boolean] :invert Indicates if the value read from the
|
19
|
-
# physical pin should be inverted. Defaults to false.
|
20
|
-
#
|
21
|
-
# @option options [Symbol] :trigger Indicates when the wait_for_change
|
22
|
-
# method will detect a change, either :rising, :falling, or :both edge
|
23
|
-
# triggers. Defaults to :both.
|
24
|
-
#
|
25
|
-
# @option options [Symbol] :pull Indicates if and how pull mode must be
|
26
|
-
# set when pin direction is set to :in. Either :up, :down or :offing.
|
27
|
-
# Defaults to :off.
|
28
|
-
#
|
14
|
+
# @option options [Symbol] :direction The direction of communication, either :in or :out. Defaults to :in.
|
15
|
+
# @option options [Boolean] :invert Indicates if the value read from the physical pin should be inverted. Defaults to false.
|
16
|
+
# @option options [Symbol] :trigger Indicates when the wait_for_change method will detect a change, either :rising, :falling, or :both edge triggers. Defaults to :both.
|
17
|
+
# @option options [Symbol] :pull Indicates if and how pull mode must be set when pin direction is set to :in. Either :up, :down or :offing. Defaults to :off.
|
29
18
|
def initialize(options)
|
30
|
-
options = {
|
31
|
-
|
32
|
-
:trigger => :both,
|
33
|
-
:pull => :off}.merge(options)
|
34
|
-
|
35
|
-
@pin = options[:pin]
|
19
|
+
options = {:direction => :in, :invert => false, :trigger => :both, :pull => :off}.merge options
|
20
|
+
@pin = options[:pin]
|
36
21
|
@direction = options[:direction]
|
37
|
-
@invert
|
38
|
-
@trigger
|
39
|
-
@pull
|
40
|
-
@released = false
|
22
|
+
@invert = options[:invert]
|
23
|
+
@trigger = options[:trigger]
|
24
|
+
@pull = options[:pull]
|
41
25
|
|
42
|
-
raise "Invalid pull mode. Options are :up, :down or :float (default)" unless
|
43
|
-
|
44
|
-
raise "
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
raise "Invalid trigger. Options are :rising, :falling, or :both" unless
|
49
|
-
[:rising, :falling, :both].include? @trigger
|
26
|
+
raise "Invalid pull mode. Options are :up, :down or :float (default)" unless [:up, :down, :float, :off].include? @pull
|
27
|
+
raise "Unable to use pull-ups : pin direction must be ':in' for this" if @direction != :in && [:up, :down].include?(@pull)
|
28
|
+
raise "Invalid direction. Options are :in or :out" unless [:in, :out].include? @direction
|
29
|
+
raise "Invalid trigger. Options are :rising, :falling, or :both" unless [:rising, :falling, :both].include? @trigger
|
30
|
+
|
31
|
+
@direction == :out ? Platform.driver.pin_output(@pin) : Platform.driver.pin_input(@pin)
|
50
32
|
|
51
|
-
if @direction == :out
|
52
|
-
Platform.driver.pin_output(@pin)
|
53
|
-
else
|
54
|
-
Platform.driver.pin_input(@pin)
|
55
|
-
end
|
56
33
|
pull!(@pull)
|
57
34
|
|
58
35
|
read
|
59
36
|
end
|
60
|
-
|
61
|
-
# If the pin has been initialized for output this method will set the
|
62
|
-
# logic level high.
|
37
|
+
|
38
|
+
# If the pin has been initialized for output this method will set the logic level high.
|
63
39
|
def on
|
64
|
-
|
65
|
-
Platform.driver.pin_set(pin, GPIO_HIGH) if direction == :out
|
40
|
+
Platform.driver.pin_set(pin, 1) if direction == :out
|
66
41
|
end
|
67
|
-
|
42
|
+
|
68
43
|
# Tests if the logic level is high.
|
69
44
|
def on?
|
70
45
|
not off?
|
71
46
|
end
|
72
|
-
|
73
|
-
# If the pin has been initialized for output this method will set
|
74
|
-
# the logic level low.
|
47
|
+
|
48
|
+
# If the pin has been initialized for output this method will set the logic level low.
|
75
49
|
def off
|
76
|
-
|
77
|
-
Platform.driver.pin_set(pin, GPIO_LOW) if direction == :out
|
50
|
+
Platform.driver.pin_set(pin, 0) if direction == :out
|
78
51
|
end
|
79
|
-
|
52
|
+
|
80
53
|
# Tests if the logic level is low.
|
81
54
|
def off?
|
82
|
-
value ==
|
55
|
+
value == 0
|
83
56
|
end
|
84
57
|
|
85
|
-
|
86
|
-
@value ||= read
|
87
|
-
end
|
88
|
-
|
89
|
-
# If the pin has been initialized for output this method will either raise
|
90
|
-
# or lower the logic level depending on `new_value`.
|
58
|
+
# If the pin has been initialized for output this method will either raise or lower the logic level depending on `new_value`.
|
91
59
|
# @param [Object] new_value If false or 0 the pin will be set to off, otherwise on.
|
92
60
|
def update_value(new_value)
|
93
|
-
!new_value || new_value ==
|
61
|
+
!new_value || new_value == 0 ? off : on
|
94
62
|
end
|
95
|
-
alias_method :value=, :update_value
|
96
63
|
|
97
|
-
# When the pin has been initialized in input mode, internal resistors can
|
98
|
-
#
|
99
|
-
#
|
100
|
-
#
|
101
|
-
# is floating.
|
102
|
-
#
|
103
|
-
# For instance when nothing is plugged in, pulling the pin-up will make
|
104
|
-
# subsequent value readings to return 'on' (or high, or 1...).
|
105
|
-
# @param [Symbol] state Indicates if and how pull mode must be set when
|
106
|
-
# pin direction is set to :in. Either :up, :down or :offing. Defaults to :off.
|
64
|
+
# When the pin has been initialized in input mode, internal resistors can be pulled up or down (respectively with :up and :down).
|
65
|
+
# Pulling an input pin wil prevent noise from triggering it when the input is floating.
|
66
|
+
# For instance when nothing is plugged in, pulling the pin-up will make subsequent value readings to return 'on' (or high, or 1...).
|
67
|
+
# @param [Symbol] state Indicates if and how pull mode must be set when pin direction is set to :in. Either :up, :down or :offing. Defaults to :off.
|
107
68
|
def pull!(state)
|
108
|
-
return nil
|
109
|
-
fail PiPiper::PinError, "Pin #{@pin} already released" if released?
|
69
|
+
return nil unless @direction == :in
|
110
70
|
@pull = case state
|
111
71
|
when :up then GPIO_PUD_UP
|
112
72
|
when :down then GPIO_PUD_DOWN
|
@@ -119,8 +79,7 @@ module PiPiper
|
|
119
79
|
@pull
|
120
80
|
end
|
121
81
|
|
122
|
-
# If the pin direction is input, it will return the current state of
|
123
|
-
# pull-up/pull-down resistor, either :up, :down or :off.
|
82
|
+
# If the pin direction is input, it will return the current state of pull-up/pull-down resistor, either :up, :down or :off.
|
124
83
|
def pull?
|
125
84
|
case @pull
|
126
85
|
when GPIO_PUD_UP then :up
|
@@ -134,15 +93,14 @@ module PiPiper
|
|
134
93
|
last_value != value
|
135
94
|
end
|
136
95
|
|
137
|
-
#
|
138
|
-
# `:trigger` modifies what edge this method will release on.
|
96
|
+
# blocks until a logic level change occurs. The initializer option `:trigger` modifies what edge this method will release on.
|
139
97
|
def wait_for_change
|
140
98
|
fd = File.open(value_file, "r")
|
141
99
|
File.open(edge_file, "w") { |f| f.write("both") }
|
142
100
|
loop do
|
143
101
|
fd.read
|
144
102
|
IO.select(nil, nil, [fd], nil)
|
145
|
-
read
|
103
|
+
read
|
146
104
|
if changed?
|
147
105
|
next if @trigger == :rising and value == 0
|
148
106
|
next if @trigger == :falling and value == 1
|
@@ -151,29 +109,15 @@ module PiPiper
|
|
151
109
|
end
|
152
110
|
end
|
153
111
|
|
154
|
-
# Reads the current value from the pin. Without calling this method
|
155
|
-
#
|
156
|
-
|
157
|
-
# In short, you must call this method if you are curious about the
|
158
|
-
# current state of the pin.
|
159
|
-
def read
|
160
|
-
fail PiPiper::PinError, "Pin #{@pin} already released" if released?
|
112
|
+
# Reads the current value from the pin. Without calling this method first, `value`, `last_value` and `changed?` will not be updated.
|
113
|
+
# In short, you must call this method if you are curious about the current state of the pin.
|
114
|
+
def read
|
161
115
|
@last_value = @value
|
162
116
|
val = Platform.driver.pin_read(@pin)
|
163
117
|
@value = invert ? (val ^ 1) : val
|
164
118
|
end
|
165
|
-
|
166
|
-
def release
|
167
|
-
Platform.driver.release_pin(@pin)
|
168
|
-
@released = true
|
169
|
-
end
|
170
|
-
|
171
|
-
def released?
|
172
|
-
@released == true
|
173
|
-
end
|
174
|
-
|
119
|
+
|
175
120
|
private
|
176
|
-
|
177
121
|
def value_file
|
178
122
|
"/sys/class/gpio/gpio#{pin}/value"
|
179
123
|
end
|
@@ -185,5 +129,6 @@ module PiPiper
|
|
185
129
|
def direction_file
|
186
130
|
"/sys/class/gpio/gpio#{pin}/direction"
|
187
131
|
end
|
132
|
+
|
188
133
|
end
|
189
134
|
end
|