pi_piper 1.1.2 → 1.2
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.
- data/Manifest +3 -1
- data/README.md +27 -1
- data/Rakefile +2 -2
- data/lib/pi_piper.rb +4 -0
- data/lib/pi_piper/bcm2835.rb +38 -0
- data/lib/pi_piper/libbcm2835.img +0 -0
- data/lib/pi_piper/spi.rb +229 -0
- data/pi_piper.gemspec +7 -4
- metadata +25 -3
data/Manifest
CHANGED
data/README.md
CHANGED
@@ -4,7 +4,7 @@ Pi Piper brings event driven programming to the Raspberry Pi's GPIO pins. To get
|
|
4
4
|
|
5
5
|
sudo gem install pi_piper
|
6
6
|
|
7
|
-
|
7
|
+
### GPIO
|
8
8
|
```ruby
|
9
9
|
require 'pi_piper'
|
10
10
|
|
@@ -26,6 +26,31 @@ sleep 1
|
|
26
26
|
pin.off
|
27
27
|
```
|
28
28
|
|
29
|
+
### SPI
|
30
|
+
Starting with version 1.2, PiPiper offers SPI support. Before utilizing SPI, ensure that you have Mike McCauley's [bcm2835 library](http://www.open.com.au/mikem/bcm2835/index.html) installed:
|
31
|
+
|
32
|
+
ls /usr/local/lib/libbcm2835.so
|
33
|
+
|
34
|
+
If that file is not present, and you try to utilize the PiPiper::Spi class, you will receive an error similar to:
|
35
|
+
|
36
|
+
LoadError: Could not open library '/usr/local/lib/libbcm2835.so': /usr/local/lib/libbcm2835.so: cannot open shared object file: No such file or directory
|
37
|
+
from /var/lib/gems/1.9.1/gems/ffi-1.3.1/lib/ffi/library.rb:123:in `block in ffi_lib'
|
38
|
+
from /var/lib/gems/1.9.1/gems/ffi-1.3.1/lib/ffi/library.rb:90:in `map'
|
39
|
+
from /var/lib/gems/1.9.1/gems/ffi-1.3.1/lib/ffi/library.rb:90:in `ffi_lib'
|
40
|
+
from /var/lib/gems/1.9.1/gems/pi_piper-1.2/lib/pi_piper/bcm2835.rb:6:in `<module:Bcm2835>'
|
41
|
+
from /var/lib/gems/1.9.1/gems/pi_piper-1.2/lib/pi_piper/bcm2835.rb:4:in `<module:PiPiper>'
|
42
|
+
from /var/lib/gems/1.9.1/gems/pi_piper-1.2/lib/pi_piper/bcm2835.rb:3:in `<top (required)>'
|
43
|
+
from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
|
44
|
+
from /usr/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require'
|
45
|
+
from /var/lib/gems/1.9.1/gems/pi_piper-1.2/lib/pi_piper/spi.rb:261:in `initialize'
|
46
|
+
from (irb):2:in `new'
|
47
|
+
from (irb):2
|
48
|
+
from /usr/bin/irb:12:in `<main>'
|
49
|
+
|
50
|
+
For those uninterested in SPI support, the bcm2835 is a "soft" requirement and is lazy loaded. If you never intended to use PiPiper::Spi, you shouldn't have to worry about this requirement.
|
51
|
+
|
52
|
+
|
53
|
+
|
29
54
|
## Example projects
|
30
55
|
|
31
56
|
Looking for more examples/sample code for Pi Piper? Then check out the following example projects, complete with circuit diagrams:
|
@@ -33,6 +58,7 @@ Looking for more examples/sample code for Pi Piper? Then check out the following
|
|
33
58
|
* [Project 1: Morse Code](https://github.com/jwhitehorn/pi_piper/wiki/Project-1:-Morse-Code)
|
34
59
|
* [Project 2: Simple Switch](https://github.com/jwhitehorn/pi_piper/wiki/Project-2:-Simple-Switch)
|
35
60
|
* [Project 3: 2-bit counter](https://github.com/jwhitehorn/pi_piper/wiki/Project-3:-2-bit-counter)
|
61
|
+
* [Project 4: MCP3008](https://github.com/jwhitehorn/pi_piper/wiki/Project-4:-MCP3008)
|
36
62
|
|
37
63
|
## License
|
38
64
|
|
data/Rakefile
CHANGED
@@ -2,13 +2,13 @@ require 'rubygems'
|
|
2
2
|
require 'rake'
|
3
3
|
require 'echoe'
|
4
4
|
|
5
|
-
Echoe.new('pi_piper', '1.
|
5
|
+
Echoe.new('pi_piper', '1.2') do |p|
|
6
6
|
p.description = "Event driven Raspberry Pi GPIO library"
|
7
7
|
p.url = "http://github.com/jwhitehorn/pi_piper"
|
8
8
|
p.author = "Jason Whitehorn"
|
9
9
|
p.email = "jason.whitehorn@gmail.com"
|
10
10
|
p.ignore_pattern = ["examples/**/*"]
|
11
|
-
p.development_dependencies = []
|
11
|
+
p.development_dependencies = ['ffi']
|
12
12
|
end
|
13
13
|
|
14
14
|
Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
|
data/lib/pi_piper.rb
CHANGED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
|
3
|
+
module PiPiper
|
4
|
+
module Bcm2835
|
5
|
+
extend FFI::Library
|
6
|
+
ffi_lib File.dirname(__FILE__) + '/libbcm2835.img'
|
7
|
+
|
8
|
+
SPI_MODE0 = 0
|
9
|
+
SPI_MODE1 = 1
|
10
|
+
SPI_MODE2 = 2
|
11
|
+
SPI_MODE3 = 3
|
12
|
+
|
13
|
+
attach_function :init, :bcm2835_init, [], :uint8
|
14
|
+
attach_function :close, :bcm2835_close, [], :uint8
|
15
|
+
|
16
|
+
attach_function :spi_begin, :bcm2835_spi_begin, [], :uint8
|
17
|
+
attach_function :spi_end, :bcm2835_spi_end, [], :uint8
|
18
|
+
attach_function :spi_transfer, :bcm2835_spi_transfer, [:uint8], :uint8
|
19
|
+
attach_function :spi_transfernb, :bcm2835_spi_transfernb, [:pointer, :pointer, :uint], :void
|
20
|
+
attach_function :spi_clock, :bcm2835_spi_setClockDivider, [:uint8], :void
|
21
|
+
attach_function :spi_bit_order, :bcm2835_spi_setBitOrder, [:uint8], :void
|
22
|
+
attach_function :spi_chip_select, :bcm2835_spi_chipSelect, [:uint8], :void
|
23
|
+
attach_function :spi_set_data_mode, :bcm2835_spi_setDataMode, [:uint8], :void
|
24
|
+
attach_function :spi_chip_select_polarity,
|
25
|
+
:bcm2835_spi_setChipSelectPolarity, [:uint8, :uint8], :void
|
26
|
+
|
27
|
+
def self.spi_transfer_bytes(data)
|
28
|
+
data_out = FFI::MemoryPointer.new(data.count)
|
29
|
+
data_in = FFI::MemoryPointer.new(data.count)
|
30
|
+
(0..data.count-1).each { |i| data_out.put_uint8(i, data[i]) }
|
31
|
+
|
32
|
+
spi_transfernb(data_out, data_in, data.count)
|
33
|
+
|
34
|
+
(0..data.count-1).map { |i| data_in.get_uint8(i) }
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
Binary file
|
data/lib/pi_piper/spi.rb
ADDED
@@ -0,0 +1,229 @@
|
|
1
|
+
=begin
|
2
|
+
Modifications Copyright 2013, Jason Whitehorn and released under the terms
|
3
|
+
of the license included in README.md
|
4
|
+
|
5
|
+
Based on works, Copyright (c) 2012 Joshua Nussbaum
|
6
|
+
|
7
|
+
MIT License
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
10
|
+
a copy of this software and associated documentation files (the
|
11
|
+
"Software"), to deal in the Software without restriction, including
|
12
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
13
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
14
|
+
permit persons to whom the Software is furnished to do so, subject to
|
15
|
+
the following conditions:
|
16
|
+
|
17
|
+
The above copyright notice and this permission notice shall be
|
18
|
+
included in all copies or substantial portions of the Software.
|
19
|
+
|
20
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
21
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
22
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
23
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
24
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
25
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
26
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
27
|
+
=end
|
28
|
+
|
29
|
+
module PiPiper
|
30
|
+
class Spi
|
31
|
+
# 65536 = 256us = 4kHz
|
32
|
+
CLOCK_DIVIDER_65536 = 0
|
33
|
+
# 32768 = 126us = 8kHz
|
34
|
+
CLOCK_DIVIDER_32768 = 32768
|
35
|
+
# 16384 = 64us = 15.625kHz
|
36
|
+
CLOCK_DIVIDER_16384 = 16384
|
37
|
+
# 8192 = 32us = 31.25kHz
|
38
|
+
CLOCK_DIVIDER_8192 = 8192
|
39
|
+
# 4096 = 16us = 62.5kHz
|
40
|
+
CLOCK_DIVIDER_4096 = 4096
|
41
|
+
# 2048 = 8us = 125kHz
|
42
|
+
CLOCK_DIVIDER_2048 = 2048
|
43
|
+
# 1024 = 4us = 250kHz
|
44
|
+
CLOCK_DIVIDER_1024 = 1024
|
45
|
+
# 512 = 2us = 500kHz
|
46
|
+
CLOCK_DIVIDER_512 = 512
|
47
|
+
# 256 = 1us = 1MHz
|
48
|
+
CLOCK_DIVIDER_256 = 256
|
49
|
+
# 128 = 500ns = = 2MHz
|
50
|
+
CLOCK_DIVIDER_128 = 128
|
51
|
+
# 64 = 250ns = 4MHz
|
52
|
+
CLOCK_DIVIDER_64 = 64
|
53
|
+
# 32 = 125ns = 8MHz
|
54
|
+
CLOCK_DIVIDER_32 = 32
|
55
|
+
# 16 = 50ns = 20MHz
|
56
|
+
CLOCK_DIVIDER_16 = 16
|
57
|
+
|
58
|
+
# Least signifigant bit first, e.g. 4 = 0b001
|
59
|
+
LSBFIRST = 0
|
60
|
+
# Most signifigant bit first, e.g. 4 = 0b100
|
61
|
+
MSBFIRST = 1
|
62
|
+
|
63
|
+
# Select Chip 0
|
64
|
+
CHIP_SELECT_0 = 0
|
65
|
+
# Select Chip 1
|
66
|
+
CHIP_SELECT_1 = 1
|
67
|
+
# Select both chips (ie pins CS1 and CS2 are asserted)
|
68
|
+
CHIP_SELECT_BOTH = 2
|
69
|
+
# No CS, control it yourself
|
70
|
+
CHIP_SELECT_NONE = 3
|
71
|
+
|
72
|
+
def self.set_mode(cpol, cpha)
|
73
|
+
mode = SPI_MODE0 #default
|
74
|
+
mode = SPI_MODE1 if cpol == 0 and cpha == 1
|
75
|
+
mode = SPI_MODE2 if cpol == 1 and cpha == 0
|
76
|
+
mode = SPI_MODE3 if cpol == 1 and cpha == 1
|
77
|
+
Bcma2835.spi_set_data_mode mode
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.begin(chip=nil)
|
81
|
+
Bcm2835.spi_begin
|
82
|
+
chip = CHIP_SELECT_0 if !chip && block_given?
|
83
|
+
spi = new(chip)
|
84
|
+
|
85
|
+
if block_given?
|
86
|
+
begin
|
87
|
+
yield(spi)
|
88
|
+
ensure
|
89
|
+
self.end
|
90
|
+
end
|
91
|
+
else
|
92
|
+
spi
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Not needed when #begin is called with a block
|
97
|
+
def self.end
|
98
|
+
Bcm2835.spi_end
|
99
|
+
end
|
100
|
+
|
101
|
+
def clock(divider)
|
102
|
+
Bcm2835.spi_clock(divider)
|
103
|
+
end
|
104
|
+
|
105
|
+
def bit_order(order=MSBFIRST)
|
106
|
+
if order.is_a?(Range)
|
107
|
+
if order.begin < order.end
|
108
|
+
order = LSBFIRST
|
109
|
+
else
|
110
|
+
order = MSBFIRST
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
Bcm2835.spi_bit_order(order)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Activate a specific chip so that communication can begin
|
118
|
+
#
|
119
|
+
# When a block is provided, the chip is automatically deactivated after the block completes.
|
120
|
+
# When a block is not provided, the user is responsible for calling chip_select(CHIP_SELECT_NONE)
|
121
|
+
#
|
122
|
+
# @example With block (preferred)
|
123
|
+
# spi.chip_select do
|
124
|
+
# spi.write(0xFF)
|
125
|
+
# end
|
126
|
+
#
|
127
|
+
# @example Without block
|
128
|
+
# spi.chip_select(CHIP_SELECT_0)
|
129
|
+
# spi.write(0xFF)
|
130
|
+
# spi.write(0x22)
|
131
|
+
# spi.chip_select(CHIP_SELECT_NONE)
|
132
|
+
#
|
133
|
+
# @yield
|
134
|
+
# @param [optional, CHIP_SELECT_*] chip the chip select line options
|
135
|
+
def chip_select(chip=CHIP_SELECT_0)
|
136
|
+
chip = @chip if @chip
|
137
|
+
Bcm2835.spi_chip_select(chip)
|
138
|
+
if block_given?
|
139
|
+
begin
|
140
|
+
yield
|
141
|
+
ensure
|
142
|
+
Bcm2835.spi_chip_select(CHIP_SELECT_NONE)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Configure the active state of the chip select line
|
148
|
+
#
|
149
|
+
# The default state for most chips is active low.
|
150
|
+
#
|
151
|
+
# "active low" means the clock line is kept high during idle, and goes low when communicating.
|
152
|
+
#
|
153
|
+
# "active high" means the clock line is kept low during idle, and goes high when communicating.
|
154
|
+
#
|
155
|
+
# @param [Boolean] active_low true for active low, false for active high
|
156
|
+
# @param [optional, CHIP_SELECT_*] chip one of CHIP_SELECT_*
|
157
|
+
def chip_select_active_low(active_low, chip=nil)
|
158
|
+
chip = @chip if @chip
|
159
|
+
chip = CHIP_SELECT_0 unless chip
|
160
|
+
|
161
|
+
Bcm2835.spi_chip_select_polarity(chip, active_low ? 0 : 1)
|
162
|
+
end
|
163
|
+
|
164
|
+
# Read from the bus
|
165
|
+
#
|
166
|
+
# @example Read a single byte
|
167
|
+
# byte = spi.read
|
168
|
+
#
|
169
|
+
# @example Read array of bytes
|
170
|
+
# array = spi.read(3)
|
171
|
+
#
|
172
|
+
#
|
173
|
+
# @param [optional, Number] count the number of bytes to read.
|
174
|
+
# When count is provided, an array is returned.
|
175
|
+
# When count is nil, a single byte is returned.
|
176
|
+
# @return [Number|Array] data that was read from the bus
|
177
|
+
def read(count=nil)
|
178
|
+
if count
|
179
|
+
write([0xFF] * count)
|
180
|
+
else
|
181
|
+
enable { Bcm2835.spi_transfer(0) }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Write to the bus
|
186
|
+
#
|
187
|
+
# @example Write a single byte
|
188
|
+
# spi.write(0x22)
|
189
|
+
#
|
190
|
+
# @example Write multiple bytes
|
191
|
+
# spi.write(0x22, 0x33, 0x44)
|
192
|
+
#
|
193
|
+
# @return [Number|Array|String] data that came out of MISO during write
|
194
|
+
def write(*args)
|
195
|
+
case args.count
|
196
|
+
when 0
|
197
|
+
raise ArgumentError.new("missing arguments")
|
198
|
+
when 1
|
199
|
+
data = args.first
|
200
|
+
else
|
201
|
+
data = args
|
202
|
+
end
|
203
|
+
|
204
|
+
enable do
|
205
|
+
case data
|
206
|
+
when Numeric
|
207
|
+
Bcm2835.spi_transfer(data)
|
208
|
+
when Enumerable
|
209
|
+
Bcm2835.spi_transfer_bytes(data)
|
210
|
+
else
|
211
|
+
raise ArgumentError.new("#{data.class} is not valid data. Use Numeric or an Enumerable of numbers")
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
private
|
217
|
+
def initialize(chip)
|
218
|
+
@chip = chip
|
219
|
+
end
|
220
|
+
|
221
|
+
def enable(&block)
|
222
|
+
if @chip
|
223
|
+
chip_select(&block)
|
224
|
+
else
|
225
|
+
yield
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
data/pi_piper.gemspec
CHANGED
@@ -2,15 +2,15 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "pi_piper"
|
5
|
-
s.version = "1.
|
5
|
+
s.version = "1.2"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Jason Whitehorn"]
|
9
|
-
s.date = "2013-01-
|
9
|
+
s.date = "2013-01-21"
|
10
10
|
s.description = "Event driven Raspberry Pi GPIO library"
|
11
11
|
s.email = "jason.whitehorn@gmail.com"
|
12
|
-
s.extra_rdoc_files = ["README.md", "lib/pi_piper.rb", "lib/pi_piper/pin.rb"]
|
13
|
-
s.files = ["Manifest", "README.md", "Rakefile", "lib/pi_piper.rb", "lib/pi_piper/pin.rb", "pi_piper.gemspec"]
|
12
|
+
s.extra_rdoc_files = ["README.md", "lib/pi_piper.rb", "lib/pi_piper/bcm2835.rb", "lib/pi_piper/libbcm2835.img", "lib/pi_piper/pin.rb", "lib/pi_piper/spi.rb"]
|
13
|
+
s.files = ["Manifest", "README.md", "Rakefile", "lib/pi_piper.rb", "lib/pi_piper/bcm2835.rb", "lib/pi_piper/libbcm2835.img", "lib/pi_piper/pin.rb", "lib/pi_piper/spi.rb", "pi_piper.gemspec"]
|
14
14
|
s.homepage = "http://github.com/jwhitehorn/pi_piper"
|
15
15
|
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Pi_piper", "--main", "README.md"]
|
16
16
|
s.require_paths = ["lib"]
|
@@ -22,8 +22,11 @@ Gem::Specification.new do |s|
|
|
22
22
|
s.specification_version = 3
|
23
23
|
|
24
24
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
25
|
+
s.add_development_dependency(%q<ffi>, [">= 0"])
|
25
26
|
else
|
27
|
+
s.add_dependency(%q<ffi>, [">= 0"])
|
26
28
|
end
|
27
29
|
else
|
30
|
+
s.add_dependency(%q<ffi>, [">= 0"])
|
28
31
|
end
|
29
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pi_piper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.2'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,8 +9,24 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-01-
|
13
|
-
dependencies:
|
12
|
+
date: 2013-01-21 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: ffi
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
14
30
|
description: Event driven Raspberry Pi GPIO library
|
15
31
|
email: jason.whitehorn@gmail.com
|
16
32
|
executables: []
|
@@ -18,13 +34,19 @@ extensions: []
|
|
18
34
|
extra_rdoc_files:
|
19
35
|
- README.md
|
20
36
|
- lib/pi_piper.rb
|
37
|
+
- lib/pi_piper/bcm2835.rb
|
38
|
+
- lib/pi_piper/libbcm2835.img
|
21
39
|
- lib/pi_piper/pin.rb
|
40
|
+
- lib/pi_piper/spi.rb
|
22
41
|
files:
|
23
42
|
- Manifest
|
24
43
|
- README.md
|
25
44
|
- Rakefile
|
26
45
|
- lib/pi_piper.rb
|
46
|
+
- lib/pi_piper/bcm2835.rb
|
47
|
+
- lib/pi_piper/libbcm2835.img
|
27
48
|
- lib/pi_piper/pin.rb
|
49
|
+
- lib/pi_piper/spi.rb
|
28
50
|
- pi_piper.gemspec
|
29
51
|
homepage: http://github.com/jwhitehorn/pi_piper
|
30
52
|
licenses: []
|