i2c-devices 0.0.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 +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
|
+
|