i2c 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -41,19 +41,26 @@ first I2c bus on the system.
41
41
 
42
42
  === MCP23017
43
43
 
44
- 16bit IO-Expander MCP23017 from Microchip. Provides a wiringpi-ruby compatible
44
+ 16 bit IO-Expander MCP23017 from Microchip. Provides a wiringpi-ruby compatible
45
45
  API and may therefore be used as a drop-in replacement for IO tasks on a
46
- Raspberry Pi. Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf
46
+ Raspberry Pi.
47
+ Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21952b.pdf
48
+
49
+ === MCP23008
50
+
51
+ 8 bit IO-Expander MCP23008 from Microchip. Basically a small version of the
52
+ MCP23017.
53
+ Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21919e.pdf
47
54
 
48
55
  == Acknowledgements
49
56
 
50
57
  The low-level IO (mainly in i2c-dev.rb) was extracted from Ruby-I2C
51
58
  (http://rubyforge.org/projects/i2c/) by Jonas Bähr <jonas.baehr@fs.ei.tum.de>
52
59
 
53
- == Legal stuff
60
+ == Copyright / Licence
54
61
 
55
62
  This code may be used under the terms of the GNU General Public Licence, Version 2.
56
63
 
57
64
  Copyright (c) 2012 Christoph Anderegg <christoph@christoph-anderegg.ch>
58
- Copyright (c) 2008 Jonas Bähr, jonas.baehr@fs.ei.tum.de
65
+ Copyright (c) 2008 Jonas Bähr <jonas.baehr@fs.ei.tum.de>
59
66
 
data/lib/i2c.rb CHANGED
@@ -8,6 +8,7 @@
8
8
 
9
9
  require 'i2c/i2c.rb'
10
10
  require 'i2c/backends/i2c-dev.rb'
11
+ require 'i2c/drivers/mcp23008.rb'
11
12
  require 'i2c/drivers/mcp23017.rb'
12
13
 
13
14
 
@@ -0,0 +1,98 @@
1
+ # -*- coding: utf-8 -*-
2
+ # I2C IO-Expander driver
3
+ # for the MCP23008 8-bit IO-Expander.
4
+ #
5
+ # The interface is compatible to the interface
6
+ # of the WiringPi gem. PWM is not supported though.
7
+ #
8
+ # Copyright (c) 2012 Christoph Anderegg <christoph@christoph-anderegg.ch>
9
+ # This file may be distributed under the terms of the GNU General Public
10
+ # License Version 2.
11
+ #
12
+
13
+ require 'i2c/i2c.rb'
14
+
15
+ # Constants for mode()
16
+ INPUT = 1
17
+ OUTPUT = 0
18
+
19
+ # Constants for write()
20
+ HIGH = 1
21
+ LOW = 0
22
+
23
+ module I2C
24
+ module Drivers
25
+ class MCP23008
26
+ # Registers
27
+ IODIR = 0x00
28
+ GPIO = 0x09
29
+
30
+ # Creates an instance representing exactly one
31
+ # MCP23008 on one I2C-bus.
32
+ #
33
+ # device: I2C-device file (usually /dev/i2c-0).
34
+ # Or an intantiated io class that supports
35
+ # the necessary operations (#read, #write
36
+ # and #ioctl).
37
+ # address: Device address on the bus.
38
+ def initialize(device, address)
39
+ if device.kind_of?(String)
40
+ @device = ::I2C.create(device)
41
+ else
42
+ [ :read, :write ].each do |m|
43
+ raise IncompatibleDeviceException,
44
+ "Missing #{m} method in device object." unless device.respond_to?(m)
45
+ end
46
+ @device = device
47
+ end
48
+ @address = address
49
+
50
+ @dir = 0xFF # Direction is input initially
51
+ @device.write(@address, IODIR, @dir)
52
+ @data = @device.read(@address, 1, GPIO).unpack("C")[0]
53
+ end
54
+
55
+ def mode?(pin)
56
+ @dir = @device.read(@address, 1, IODIR).unpack("C")[0]
57
+ return (@dir >> pin) & 0x01
58
+ end
59
+
60
+ def mode(pin, pin_mode)
61
+ raise ArgumentError, "Pin not 0-7" unless (0..7).include?(pin)
62
+ raise ArgumentError, 'invalid value' unless [0,1].include?(pin_mode)
63
+ @dir = set_bit_value(@dir, pin, pin_mode)
64
+ @device.write(@address, IODIR, @dir)
65
+ end
66
+
67
+ def []=(pin, value)
68
+ raise ArgumentError, "Pin not 0-7" unless (0..7).include?(pin)
69
+ raise ArgumentError, 'invalid value' unless [0,1].include?(value)
70
+ @data = set_bit_value(@data, pin, value)
71
+ @device.write(@address, GPIO, @data)
72
+ end
73
+ alias :write :[]=
74
+
75
+ def [](pin)
76
+ raise ArgumentError, "Pin not 0-7." unless (0..7).include?(pin)
77
+ @data = @device.read(@address, 1, GPIO).unpack("C")[0]
78
+ return (@data >> pin) & 0x01
79
+ end
80
+ alias :read :[]
81
+
82
+ private
83
+ def set_bit_value(byte, bit, value)
84
+ mask = 0x00
85
+ mask = (0x01 << bit)
86
+ case value
87
+ when 0
88
+ byte = (byte & ((~mask) & 0xFF)) & 0xFF
89
+ when 1
90
+ byte = (byte | mask) & 0xFF
91
+ else
92
+ raise ArgumentError, "Bit not 0-7."
93
+ end
94
+ byte
95
+ end
96
+ end
97
+ end
98
+ end
@@ -69,7 +69,7 @@ module I2C
69
69
  end
70
70
 
71
71
  def mode(pin, pin_mode)
72
- raise ArgumentError, "Pin not 0-15" unless (0..16).include?(pin)
72
+ raise ArgumentError, "Pin not 0-15" unless (0..15).include?(pin)
73
73
  raise ArgumentError, 'invalid value' unless [0,1].include?(pin_mode)
74
74
  if 8 <= pin
75
75
  @dir_b = set_bit_value(@dir_b, (pin-8), pin_mode)
@@ -0,0 +1,86 @@
1
+ require 'i2c'
2
+
3
+ class MockI2CIO
4
+ attr_reader :registers
5
+ attr_reader :last_address
6
+
7
+ def initialize
8
+ @registers = Hash.new
9
+ # Initialize according to data sheet
10
+ @registers[0x00] = 0xFF
11
+ (0x01..0x0A).each do |reg|
12
+ @registers[reg] = 0x00
13
+ end
14
+ end
15
+
16
+ def write(address, *params)
17
+ @last_address = address
18
+ if params.count >= 1
19
+ reg_addr = params.shift
20
+ index = 0
21
+ params.each do |p|
22
+ @registers[reg_addr+index] = p
23
+ index += 1
24
+ end
25
+ end
26
+ end
27
+
28
+ def read(address, size, *params)
29
+ @last_address = address
30
+ answer = String.new
31
+ answer.force_encoding("US-ASCII")
32
+ if (size > 0) && (params.count >= 1)
33
+ reg_addr = params.shift
34
+ (0...size).each do |index|
35
+ answer << (@registers[reg_addr+index] & 0xFF)
36
+ end
37
+ end
38
+ answer
39
+ end
40
+ end
41
+
42
+ describe I2C::Drivers::MCP23008, "#mode?" do
43
+ it "initially returns 1 for all pin modes" do
44
+ io = MockI2CIO.new
45
+ mcp23008 = I2C::Drivers::MCP23008.new(io, 0x20)
46
+ (0..7).each do |pin|
47
+ mcp23008.mode?(pin).should eq(1)
48
+ end
49
+ end
50
+ end
51
+
52
+ describe I2C::Drivers::MCP23008, "#mode?" do
53
+ it "returns what has been set through #mode" do
54
+ io = MockI2CIO.new
55
+ mcp23008 = I2C::Drivers::MCP23008.new(io, 0x20)
56
+ (0..500).each do |pin|
57
+ pin = rand(8)
58
+ mode = rand(2)
59
+ mcp23008.mode(pin, mode)
60
+ mcp23008.mode?(pin).should eq(mode)
61
+ end
62
+ end
63
+ end
64
+
65
+ describe I2C::Drivers::MCP23008, "#[]" do
66
+ it "initially returns 0 for all I/O pins" do
67
+ io = MockI2CIO.new
68
+ mcp23008 = I2C::Drivers::MCP23008.new(io, 0x20)
69
+ (0..7).each do |pin|
70
+ mcp23008[pin].should eq(0)
71
+ end
72
+ end
73
+ end
74
+
75
+ describe I2C::Drivers::MCP23008, "#[]" do
76
+ it "returns what has been set through #[]=" do
77
+ io = MockI2CIO.new
78
+ mcp23008 = I2C::Drivers::MCP23008.new(io, 0x20)
79
+ (0..500).each do |pin|
80
+ pin = rand(8)
81
+ value = rand(2)
82
+ mcp23008[pin] = value
83
+ mcp23008[pin].should eq(value)
84
+ end
85
+ end
86
+ end
@@ -44,9 +44,9 @@ end
44
44
  describe I2C::Drivers::MCP23017, "#mode?" do
45
45
  it "initially returns 1 for all pin modes" do
46
46
  io = MockI2CIO.new
47
- mcp17026 = I2C::Drivers::MCP23017.new(io, 0x20)
47
+ mcp23017 = I2C::Drivers::MCP23017.new(io, 0x20)
48
48
  (0..15).each do |pin|
49
- mcp17026.mode?(pin).should eq(1)
49
+ mcp23017.mode?(pin).should eq(1)
50
50
  end
51
51
  end
52
52
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: i2c
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-08-03 00:00:00.000000000 Z
12
+ date: 2012-08-26 00:00:00.000000000 Z
13
13
  dependencies: []
14
14
  description: Interface to I2C (aka TWI) implementations. Also provides abstractions
15
15
  for some I2c-devices. Created with the Raspberry Pi in mind.
@@ -23,7 +23,9 @@ files:
23
23
  - lib/i2c/i2c.rb
24
24
  - lib/i2c/backends/i2c-dev.rb
25
25
  - lib/i2c/drivers/mcp23017.rb
26
+ - lib/i2c/drivers/mcp23008.rb
26
27
  - test//mcp23017_spec.rb
28
+ - test//mcp23008_spec.rb
27
29
  - rules/88-i2c.rules
28
30
  - README.rdoc
29
31
  homepage: https://github.com/andec/i2c