pi_piper 1.1.2 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
data/Manifest CHANGED
@@ -2,5 +2,7 @@ Manifest
2
2
  README.md
3
3
  Rakefile
4
4
  lib/pi_piper.rb
5
+ lib/pi_piper/bcm2835.rb
6
+ lib/pi_piper/libbcm2835.img
5
7
  lib/pi_piper/pin.rb
6
- pi_piper.gemspec
8
+ lib/pi_piper/spi.rb
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
- Sample usage:
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.1.2') do |p|
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
@@ -1,4 +1,8 @@
1
1
  Dir[File.dirname(__FILE__) + '/pi_piper/*.rb'].each {|file| require file }
2
+ at_exit do
3
+ PiPiper::Bcm2835.close
4
+ end
5
+ PiPiper::Bcm2835.init
2
6
 
3
7
  module PiPiper
4
8
 
@@ -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
@@ -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.1.2"
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-20"
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.1.2
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-20 00:00:00.000000000 Z
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: []