class I2CDevice::Driver::GPIO
Generic software I2C Driver based on /sys/class/gpio. THIS MODULE WORKS WITH VERY SLOW SPEED ABOUT JUST 1kHz (normaly 100kHz).
Attributes
scl[R]
Pin-number of SCL
sda[R]
Pin-number of SDA
speed[R]
Clock speed in kHz
Public Class Methods
new(opts={})
click to toggle source
opts[:sda]
- Integer
-
Pin-number of SDA
opts[:scl]
- Integer
-
Pin-number of SCL
[ opts[:speed] = 1 ]
- Integer
-
Clock speed in kHz
# File lib/templates/grove_pi/i2c/driver/gpio.rb, line 90 def initialize(opts={}) @sda = opts[:sda] or raise "opts[:sda] = [gpio pin number] is required" @scl = opts[:scl] or raise "opts[:scl] = [gpio pin number] is required" @speed = opts[:speed] || 1 # kHz but insane @clock = 1.0 / (@speed * 1000) begin GPIO.export(@sda) GPIO.export(@scl) rescue Errno::EBUSY => e end ObjectSpace.define_finalizer(self, self.class.finalizer([@scl, @sda])) begin GPIO.direction(@sda, :high) GPIO.direction(@scl, :high) GPIO.direction(@sda, :in) GPIO.direction(@scl, :in) rescue Errno::EACCES => e # writing to gpio after export is failed in a while retry end end
Public Instance Methods
i2cget(address, param, length=1)
click to toggle source
Interface of I2CDevice::Driver
# File lib/templates/grove_pi/i2c/driver/gpio.rb, line 113 def i2cget(address, param, length=1) ret = "" start_condition unless write( (address << 1) + 0) raise I2CDevice::I2CIOError, "Unknown slave device (address:#{address})" end write(param) stop_condition # AVR stucked with SCL low without this (Does not AVR support Sr condition?) start_condition unless write( (address << 1) + 1) raise I2CDevice::I2CIOError, "Unknown slave device (address:#{address})" end length.times do |n| ret << read(n != length - 1).chr end ret ensure stop_condition end
i2cset(address, *data)
click to toggle source
Interface of I2CDevice::Driver
# File lib/templates/grove_pi/i2c/driver/gpio.rb, line 134 def i2cset(address, *data) sent = 0 start_condition unless write( (address << 1) + 0) raise I2CDevice::I2CIOError, "Unknown slave device (address:#{address})" end data.each do |c| unless write(c) break end sent += 1 end sent ensure stop_condition end
Private Instance Methods
read(ack=true)
click to toggle source
Read one byte from BUS.
ack
- true|flase
-
Send ack for this read.
- Returns
- Integer
-
Byte
# File lib/templates/grove_pi/i2c/driver/gpio.rb, line 218 def read(ack=true) p [:read, ack] if @@DEBUG ret = 0 GPIO.direction(@scl, :low) sleep @clock GPIO.direction(@sda, :in) 8.times do GPIO.direction(@scl, :in) sleep @clock / 2 ret = (ret << 1) | GPIO.read(@sda) sleep @clock / 2 GPIO.direction(@scl, :low) sleep @clock end GPIO.direction(@sda, ack ? :low : :high) GPIO.write(@scl, true) sleep @clock GPIO.write(@scl, false) sleep @clock ret end
start_condition()
click to toggle source
Send start condition (or repeated start condition) raise I2CDevice::I2CBUSBusy
if SCL line is low
# File lib/templates/grove_pi/i2c/driver/gpio.rb, line 155 def start_condition p :start_condition if @@DEBUG sleep @clock GPIO.direction(@sda, :in) GPIO.direction(@scl, :in) if GPIO.read(@scl) == 0 raise I2CDevice::I2CBUSBusy, "BUS is busy" end sleep @clock / 2 GPIO.direction(@scl, :high) sleep @clock / 2 GPIO.direction(@sda, :low) sleep @clock end
stop_condition()
click to toggle source
Send stop condition.
# File lib/templates/grove_pi/i2c/driver/gpio.rb, line 172 def stop_condition p :stop_condition if @@DEBUG GPIO.direction(@scl, :low) sleep @clock / 2 GPIO.direction(@sda, :low) sleep @clock / 2 GPIO.direction(@scl, :in) sleep @clock / 2 GPIO.direction(@sda, :in) sleep @clock / 2 end
write(byte)
click to toggle source
Write one byte to BUS.
# File lib/templates/grove_pi/i2c/driver/gpio.rb, line 185 def write(byte) p [:write, byte] if @@DEBUG GPIO.direction(@scl, :low) sleep @clock 7.downto(0) do |n| GPIO.direction(@sda, byte[n] == 1 ? :high : :low) GPIO.direction(@scl, :in) until GPIO.read(@scl) == 1 # clock streching sleep @clock end sleep @clock GPIO.direction(@scl, :low) GPIO.write(@sda, false) sleep @clock end GPIO.direction(@sda, :in) GPIO.direction(@scl, :in) sleep @clock / 2 ack = GPIO.read(@sda) == 0 sleep @clock / 2 while GPIO.read(@scl) == 0 sleep @clock end GPIO.direction(@scl, :low) ack end