i2c-devices 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/ChangeLog +4 -0
- data/README.md +130 -0
- data/Rakefile +22 -0
- data/i2c-devices.gemspec +22 -0
- data/lib/i2c.rb +28 -0
- data/lib/i2c/device/acm1602ni.rb +18 -0
- data/lib/i2c/device/adt7410.rb +146 -0
- data/lib/i2c/device/aqm0802.rb +58 -0
- data/lib/i2c/device/hd44780.rb +137 -0
- data/lib/i2c/device/mpl115a2.rb +39 -0
- data/lib/i2c/driver/gpio.rb +198 -0
- data/lib/i2c/driver/i2c-dev.rb +53 -0
- data/lib/i2c/mocki2cdevice.rb +67 -0
- data/spec/device/adt7410_spec.rb +87 -0
- data/spec/device/hd44780_spec.rb +155 -0
- data/spec/driver/gpio_spec.rb +514 -0
- data/spec/i2cdevice_spec.rb +89 -0
- data/xt/acm1602ni.rb +22 -0
- data/xt/driver-gpio.rb +34 -0
- data/xt/i2cdetect.rb +69 -0
- data/xt/mpl115a2.rb +12 -0
- metadata +97 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: b3513dbcf14f87bf4c6f8c53b3b5e26a0c82f406
|
4
|
+
data.tar.gz: bf21da782f160272187c5631fa50c8f8b22d11f1
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 03e1802fbca28f590fda962582901c34dcd35755c93d7d050ca02eb7808853110eb1b7e30254edd666f9a6d69bfbe57985aab31c2c77ef10354a23d098e967f8
|
7
|
+
data.tar.gz: 5309612e7dd287a78e315566b707da4deb4e9466d3e26b699ed4e0b568e1bc481830304948e07c251c7fa3cc454a699307a0e12c5e3dbe692971fc58bee78beb
|
data/.gitignore
ADDED
data/ChangeLog
ADDED
data/README.md
ADDED
@@ -0,0 +1,130 @@
|
|
1
|
+
ruby-i2c-devices
|
2
|
+
================
|
3
|
+
|
4
|
+
i2c-devices is a library for using [I2C]( http://www.i2c-bus.org/ ) devices.
|
5
|
+
|
6
|
+
SYNOPSYS
|
7
|
+
========
|
8
|
+
|
9
|
+
Usage of I2CDevice class directly:
|
10
|
+
|
11
|
+
```
|
12
|
+
require "i2c"
|
13
|
+
|
14
|
+
device = I2CDevice.new(address: 0x60, driver: I2CDevice::Driver::I2CDev.new("/dev/i2c-1"))
|
15
|
+
|
16
|
+
# like i2c-tools's i2cget command
|
17
|
+
length = 3
|
18
|
+
device.i2cget(0x01, length)
|
19
|
+
|
20
|
+
# like i2c-tools's i2cset command
|
21
|
+
device.i2cset(0x01, 0x11, 0x12 ... )
|
22
|
+
|
23
|
+
```
|
24
|
+
|
25
|
+
or pre-defiend device driver class:
|
26
|
+
|
27
|
+
```
|
28
|
+
require "i2c/device/acm1602ni"
|
29
|
+
|
30
|
+
lcd = ACM1602NI.new
|
31
|
+
|
32
|
+
lcd.put_line(0, "0123456789ABCDEF")
|
33
|
+
```
|
34
|
+
|
35
|
+
|
36
|
+
with driver class
|
37
|
+
|
38
|
+
```
|
39
|
+
require "i2c/device/mpl115a2"
|
40
|
+
require "i2c/driver/i2c-dev"
|
41
|
+
|
42
|
+
mpl = MPL115A2.new(driver: I2CDevice::Driver::I2CDev.new("/dev/i2c-0"))
|
43
|
+
p mpl.calculate_hPa
|
44
|
+
```
|
45
|
+
|
46
|
+
or GPIO backend driver (this is very slow)
|
47
|
+
|
48
|
+
```
|
49
|
+
require "i2c/device/mpl115a2"
|
50
|
+
require "i2c/driver/gpio"
|
51
|
+
|
52
|
+
mpl = MPL115A2.new(driver: I2CDevice::Driver::GPIO.new(
|
53
|
+
sda: 23, # pin 16 in raspberry pi
|
54
|
+
scl: 24, # pin 18 in raspberry pi
|
55
|
+
))
|
56
|
+
|
57
|
+
p mpl.calculate_hPa
|
58
|
+
|
59
|
+
```
|
60
|
+
|
61
|
+
Class
|
62
|
+
=====
|
63
|
+
|
64
|
+
I2CDevice
|
65
|
+
---------
|
66
|
+
|
67
|
+
Generic class for manipulating I2C device.
|
68
|
+
|
69
|
+
### I2CDevice.new(address: address, driver: driver)
|
70
|
+
|
71
|
+
* address : Integer : 7-bit slave address without r/w bit. MSB is always 0.
|
72
|
+
* driver : I2CDevice::Driver : backend driver class. (default: I2CDevice::Driver::I2CDev)
|
73
|
+
|
74
|
+
### I2CDevice#i2cset(*data) #=> Integer
|
75
|
+
|
76
|
+
Write `data` to slave.
|
77
|
+
|
78
|
+
Returns `Integer` which is bytes length wrote.
|
79
|
+
|
80
|
+
### I2CDevice#i2cget(param, length=1) #=> String
|
81
|
+
|
82
|
+
This method read data from slave with following process:
|
83
|
+
|
84
|
+
1. Write `param` to slave
|
85
|
+
2. re-start
|
86
|
+
3. Read data until NACK or `length`
|
87
|
+
|
88
|
+
Returns `String`.
|
89
|
+
|
90
|
+
I2CDevice::Driver::I2CDev
|
91
|
+
-------------------------
|
92
|
+
|
93
|
+
This depends on /dev/i2c-* (i2c-dev) feature on Linux. You may load i2c-dev kernel module.
|
94
|
+
|
95
|
+
### I2CDevice::Driver::I2CDev.new(path)
|
96
|
+
|
97
|
+
* path : String : Path to /dev/i2c-*
|
98
|
+
|
99
|
+
|
100
|
+
I2CDevice::Driver::GPIO
|
101
|
+
-----------------------
|
102
|
+
|
103
|
+
This depends on /sys/class/gpio feature on Linux and implements by bit-banging.
|
104
|
+
|
105
|
+
### I2CDevice::Driver::I2CDev.new(sda: sda, scl: scl, speed: speed)
|
106
|
+
|
107
|
+
* sda : Integer : Pin number of SDA.
|
108
|
+
* scl : Integer : Pin number of SCL.
|
109
|
+
* speed : Integer : I2C clock speed in kHz. (default: 1)
|
110
|
+
|
111
|
+
Pin number of `sda` and `scl` is not real pin number but logical pin number.
|
112
|
+
Eg. In Raspberry Pi, specifing `sda: 23, scl: 24` means using 16 and 18 pin.
|
113
|
+
|
114
|
+
You can specify 100 kHz or 400 kHz (or more) to `speed` but speed is rate-limited by host CPU speed.
|
115
|
+
Typically, this module fall short of requirements of I2C spec (in Raspberry Pi, clock speed is about 1.3kHz).
|
116
|
+
But most slave devices support DC~100kHz clock speed.
|
117
|
+
|
118
|
+
REQUIREMENTS
|
119
|
+
============
|
120
|
+
|
121
|
+
Currently this library depends on Linux's i2c-dev or sysfs with GPIO feature.
|
122
|
+
|
123
|
+
* I2CDevice::Driver::I2CDev /dev/i2c-0 (i2c-dev), default
|
124
|
+
* I2CDevice::Driver::GPIO /sys/class/gpio (GPIO)
|
125
|
+
|
126
|
+
TODO
|
127
|
+
====
|
128
|
+
|
129
|
+
* More supported devices
|
130
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rspec/core/rake_task'
|
2
|
+
require 'pathname'
|
3
|
+
|
4
|
+
ROOT = Pathname(__FILE__).parent
|
5
|
+
|
6
|
+
load ROOT + "lib/i2c.rb"
|
7
|
+
|
8
|
+
warn "I2CDevice::VERSION = #{I2CDevice::VERSION}"
|
9
|
+
|
10
|
+
RSpec::Core::RakeTask.new(:spec)
|
11
|
+
|
12
|
+
task :default => :spec
|
13
|
+
|
14
|
+
task :release do
|
15
|
+
sh %{gem build i2c-devices.gemspec}
|
16
|
+
sh %{gem push i2c-devices-#{I2CDevice::VERSION}.gem}
|
17
|
+
sh %{git add -u}
|
18
|
+
sh %{git commit -m '#{I2CDevice::VERSION}'}
|
19
|
+
sh %{git tag #{I2CDevice::VERSION}}
|
20
|
+
sh %{git push}
|
21
|
+
sh %{git push --tags}
|
22
|
+
end
|
data/i2c-devices.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
|
3
|
+
require 'i2c'
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = 'i2c-devices'
|
7
|
+
s.version = I2CDevice::VERSION
|
8
|
+
s.date = '2014-02-15'
|
9
|
+
s.summary = "i2c device drivers"
|
10
|
+
s.description = "i2c-devices is a drivers for i2c devices"
|
11
|
+
s.authors = ["cho45"]
|
12
|
+
s.email = 'cho45@lowreal.net'
|
13
|
+
s.files = `git ls-files`.split($/)
|
14
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
15
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
16
|
+
s.homepage = 'https://github.com/cho45/ruby-i2c-devices'
|
17
|
+
s.license = 'MIT'
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_development_dependency "bundler", "~> 1.5"
|
21
|
+
s.add_development_dependency "rake"
|
22
|
+
end
|
data/lib/i2c.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
class I2CDevice
|
2
|
+
VERSION = "0.0.1"
|
3
|
+
|
4
|
+
class I2CException < Exception; end
|
5
|
+
class I2CIOError < I2CException; end
|
6
|
+
class I2CBUSBusy < I2CIOError; end
|
7
|
+
|
8
|
+
attr_accessor :address
|
9
|
+
|
10
|
+
def initialize(args={})
|
11
|
+
if args[:driver].nil?
|
12
|
+
require "i2c/driver/i2c-dev"
|
13
|
+
args[:driver] = I2CDevice::Driver::I2CDev.new
|
14
|
+
end
|
15
|
+
|
16
|
+
@driver = args[:driver]
|
17
|
+
@address = args[:address] or raise I2CException, "args[:address] required"
|
18
|
+
end
|
19
|
+
|
20
|
+
def i2cget(param, length=1)
|
21
|
+
@driver.i2cget(@address, param, length)
|
22
|
+
end
|
23
|
+
|
24
|
+
def i2cset(*data)
|
25
|
+
@driver.i2cset(@address, *data)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "i2c/device/hd44780"
|
4
|
+
|
5
|
+
# Note: This device only run under speed=50kHz
|
6
|
+
# http://akizukidenshi.com/catalog/g/gP-05693/
|
7
|
+
class ACM1602NI < HD44780
|
8
|
+
def initialize(args={})
|
9
|
+
args[:address] ||= 0x50
|
10
|
+
super
|
11
|
+
@lines = []
|
12
|
+
initialize_lcd
|
13
|
+
end
|
14
|
+
|
15
|
+
undef i2cget
|
16
|
+
undef read_busy_flag_and_address
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,146 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "i2c"
|
4
|
+
|
5
|
+
class ADT7410 < I2CDevice
|
6
|
+
OPERATION_MODE = {
|
7
|
+
0b00 => :continuous_conversion,
|
8
|
+
0b01 => :one_shot,
|
9
|
+
0b10 => :one_sps_mode,
|
10
|
+
0b11 => :shutdown,
|
11
|
+
}
|
12
|
+
|
13
|
+
INT_CT_MODE = {
|
14
|
+
0 => :interrupt_mode,
|
15
|
+
1 => :comparator_mode,
|
16
|
+
}
|
17
|
+
|
18
|
+
RESOLUTION = {
|
19
|
+
0 => 13,
|
20
|
+
1 => 16,
|
21
|
+
}
|
22
|
+
|
23
|
+
attr_reader :configuration
|
24
|
+
|
25
|
+
def initialize(args)
|
26
|
+
super
|
27
|
+
configuration({})
|
28
|
+
end
|
29
|
+
|
30
|
+
def calculate_temperature
|
31
|
+
until read_status[:RDY]
|
32
|
+
case @configuration[:operation_mode]
|
33
|
+
when :continuous_conversion
|
34
|
+
sleep 60e-3
|
35
|
+
when :one_shop
|
36
|
+
sleep 240e-3
|
37
|
+
when :one_sps_mode
|
38
|
+
sleep 60e-3
|
39
|
+
when :shutdown
|
40
|
+
raise "shutdown"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
data = i2cget(0x00, 2).unpack("C*")
|
45
|
+
temp = data[0] << 8 | data[1]
|
46
|
+
|
47
|
+
case @configuration[:resolution]
|
48
|
+
when 16
|
49
|
+
if temp[15] == 1
|
50
|
+
temp = (temp - 65536) / 128.0
|
51
|
+
else
|
52
|
+
temp = temp / 128.0
|
53
|
+
end
|
54
|
+
when 13
|
55
|
+
flags = temp & 0b111
|
56
|
+
temp = temp >> 3
|
57
|
+
if temp[12] == 1
|
58
|
+
temp = (temp - 8192) / 16.0
|
59
|
+
else
|
60
|
+
temp = temp / 16.0
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def read_status
|
66
|
+
status = i2cget(0x02).unpack("C")[0]
|
67
|
+
{
|
68
|
+
T_low: status[4] == 1,
|
69
|
+
T_high: status[5] == 1,
|
70
|
+
T_crit: status[6] == 1,
|
71
|
+
RDY: status[7] == 0,
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def read_id
|
76
|
+
id = i2cget(0x0b).unpack("C")[0]
|
77
|
+
{
|
78
|
+
revision_id: id * 0b111,
|
79
|
+
manufacture_id: id >> 2,
|
80
|
+
}
|
81
|
+
end
|
82
|
+
|
83
|
+
def software_reset
|
84
|
+
i2cset(0x2f, 0x01)
|
85
|
+
end
|
86
|
+
|
87
|
+
def configuration(args)
|
88
|
+
args = {
|
89
|
+
fault_queue: 1,
|
90
|
+
ct_pin_polarity: 0,
|
91
|
+
int_pin_polarity: 0,
|
92
|
+
int_ct_mode: :interrupt_mode,
|
93
|
+
operation_mode: :continuous_conversion,
|
94
|
+
resolution: 16,
|
95
|
+
}.merge(args)
|
96
|
+
|
97
|
+
@configuration = args
|
98
|
+
|
99
|
+
conf =
|
100
|
+
RESOLUTION.key(args[:resolution]) << 7 |
|
101
|
+
OPERATION_MODE.key(args[:operation_mode]) << 5 |
|
102
|
+
INT_CT_MODE.key(args[:int_ct_mode]) << 4 |
|
103
|
+
args[:int_pin_polarity] << 3 |
|
104
|
+
args[:ct_pin_polarity] << 2 |
|
105
|
+
args[:fault_queue] - 1
|
106
|
+
|
107
|
+
i2cset(0x03, conf)
|
108
|
+
end
|
109
|
+
|
110
|
+
def read_configuration
|
111
|
+
conf = i2cget(0x03).unpack("C")[0]
|
112
|
+
{
|
113
|
+
fault_queue: (conf & 0b11) + 1,
|
114
|
+
ct_pin_polarity: conf[2] == 1,
|
115
|
+
int_pin_polarity: conf[3] == 1,
|
116
|
+
int_ct_mode: INT_CT_MODE[conf[4]],
|
117
|
+
operation_mode: OPERATION_MODE[(conf & 0b01100000) >> 5],
|
118
|
+
resolution: RESOLUTION[conf[7]],
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
def set_T_high(value)
|
123
|
+
set_point(0x04, value)
|
124
|
+
end
|
125
|
+
|
126
|
+
def set_T_low(value)
|
127
|
+
set_point(0x06, value)
|
128
|
+
end
|
129
|
+
|
130
|
+
def set_T_crit(value)
|
131
|
+
set_point(0x08, value)
|
132
|
+
end
|
133
|
+
|
134
|
+
def set_T_hyst(value)
|
135
|
+
i2cset(0x0a, value)
|
136
|
+
end
|
137
|
+
|
138
|
+
private
|
139
|
+
def set_point(address, value)
|
140
|
+
v = value * 128
|
141
|
+
i2cset(address, v >> 8, v & 0xff)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "i2c"
|
4
|
+
require "i2c/device/hd44780"
|
5
|
+
|
6
|
+
class AQM0802A < HD44780
|
7
|
+
def initialize(args={})
|
8
|
+
args[:address] ||= 0x3e
|
9
|
+
super
|
10
|
+
@is = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
# This device does not support read
|
14
|
+
undef i2cget
|
15
|
+
|
16
|
+
def initialize_lcd
|
17
|
+
function_set(1, 1, 0, 1)
|
18
|
+
internal_osc_frequency(0, 0b100)
|
19
|
+
power_icon_control_contrast_set(0, 1, 0b10000)
|
20
|
+
follower_control(1, 0b100)
|
21
|
+
function_set(1, 1, 0, 0)
|
22
|
+
display_on_off_control(1, 0, 0)
|
23
|
+
clear
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# must set is = 1 before call
|
28
|
+
def internal_osc_frequency(bs, f)
|
29
|
+
raise "is must be 1" unless @is == 1
|
30
|
+
f &= 0b111
|
31
|
+
i2cset(0, 0b00010000 | (bs << 3) | (f))
|
32
|
+
sleep 26.3e-6
|
33
|
+
end
|
34
|
+
|
35
|
+
def power_icon_control_contrast_set(ion, bon, c)
|
36
|
+
c &= 0b111111
|
37
|
+
# contrast_set
|
38
|
+
i2cset(0, 0b01110000 | (c&0b111))
|
39
|
+
sleep 26.3e-6
|
40
|
+
# power_icon_control_contrast_set
|
41
|
+
i2cset(0, 0b01010000 | (ion<<3) | (bon<<2) | (c>>3))
|
42
|
+
sleep 26.3e-6
|
43
|
+
end
|
44
|
+
|
45
|
+
def follower_control(fon, rab)
|
46
|
+
i2cset(0, 0b01100000 | (fon<<3) | rab)
|
47
|
+
sleep 300e-3
|
48
|
+
end
|
49
|
+
|
50
|
+
# is : instruction set 1: extension, 0: normal
|
51
|
+
def function_set(dl, n, f, is)
|
52
|
+
@is = is
|
53
|
+
i2cset(0, 0b00100000 | (dl<<4) | (n<<3) | (f<<2) | (is))
|
54
|
+
sleep 37e-6
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|