Class: LGPIO::I2CBitBang
- Inherits:
-
Object
- Object
- LGPIO::I2CBitBang
- Defined in:
- lib/lgpio/i2c_bitbang.rb
Constant Summary collapse
- VALID_ADDRESSES =
(0x08..0x77).to_a
Instance Attribute Summary collapse
-
#scl_handle ⇒ Object
readonly
Returns the value of attribute scl_handle.
-
#scl_line ⇒ Object
readonly
Returns the value of attribute scl_line.
-
#sda_handle ⇒ Object
readonly
Returns the value of attribute sda_handle.
-
#sda_line ⇒ Object
readonly
Returns the value of attribute sda_line.
Instance Method Summary collapse
- #config ⇒ Object
-
#initialize(options = {}) ⇒ I2CBitBang
constructor
A new instance of I2CBitBang.
- #initialize_pins ⇒ Object
- #read(address, length) ⇒ Object
- #read_bit ⇒ Object
- #read_byte(ack) ⇒ Object
- #read_byte_c(ack) ⇒ Object
- #read_form(address) ⇒ Object
- #search ⇒ Object
- #set_sda(value) ⇒ Object
- #start ⇒ Object
- #stop ⇒ Object
- #write(address, bytes) ⇒ Object
- #write_bit(bit) ⇒ Object
- #write_byte(byte) ⇒ Object
- #write_byte_c(byte) ⇒ Object
- #write_form(address) ⇒ Object
Constructor Details
#initialize(options = {}) ⇒ I2CBitBang
Returns a new instance of I2CBitBang.
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
# File 'lib/lgpio/i2c_bitbang.rb', line 7 def initialize(={}) scl = [:scl] sda = [:sda] @scl_handle = scl[:handle] if scl @scl_line = scl[:line] if scl raise ArgumentError, ":scl pin required as Hash, with :handle and :line required" unless (@scl_handle && @scl_line) @sda_handle = sda[:handle] if sda @sda_line = sda[:line] if sda raise ArgumentError, ":sda pin required as Hash, with :handle and :line required" unless (@sda_handle && @sda_line) @sda_state = nil initialize_pins end |
Instance Attribute Details
#scl_handle ⇒ Object (readonly)
Returns the value of attribute scl_handle.
5 6 7 |
# File 'lib/lgpio/i2c_bitbang.rb', line 5 def scl_handle @scl_handle end |
#scl_line ⇒ Object (readonly)
Returns the value of attribute scl_line.
5 6 7 |
# File 'lib/lgpio/i2c_bitbang.rb', line 5 def scl_line @scl_line end |
#sda_handle ⇒ Object (readonly)
Returns the value of attribute sda_handle.
5 6 7 |
# File 'lib/lgpio/i2c_bitbang.rb', line 5 def sda_handle @sda_handle end |
#sda_line ⇒ Object (readonly)
Returns the value of attribute sda_line.
5 6 7 |
# File 'lib/lgpio/i2c_bitbang.rb', line 5 def sda_line @sda_line end |
Instance Method Details
#config ⇒ Object
23 24 25 |
# File 'lib/lgpio/i2c_bitbang.rb', line 23 def config @config ||= [scl_handle, scl_line, sda_handle, scl_line] end |
#initialize_pins ⇒ Object
27 28 29 30 |
# File 'lib/lgpio/i2c_bitbang.rb', line 27 def initialize_pins LGPIO.gpio_claim_output(scl_handle, scl_line, LGPIO::SET_PULL_NONE, LGPIO::HIGH) LGPIO.gpio_claim_output(sda_handle, sda_line, LGPIO::SET_OPEN_DRAIN | LGPIO::SET_PULL_UP, LGPIO::HIGH) end |
#read(address, length) ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/lgpio/i2c_bitbang.rb', line 99 def read(address, length) raise ArgumentError, "invalid I2C address: #{address}. Range is 0x08..0x77" unless VALID_ADDRESSES.include?(address) raise ArgumentError, "invalid Integer for read length: #{length}" unless length.kind_of?(Integer) start ack = write_byte(read_form(address)) return nil unless ack # Read length bytes, and ACK for all but the last one. bytes = [] # Bit-bang per-byte in Ruby. # (length-1).times { bytes << read_byte(true) } # bytes << read_byte(false) # Bit-bang per-byte in C. (length-1).times { bytes << read_byte_c(true) } bytes << read_byte_c(false) stop bytes end |
#read_bit ⇒ Object
56 57 58 59 60 61 62 |
# File 'lib/lgpio/i2c_bitbang.rb', line 56 def read_bit set_sda(1) LGPIO.gpio_write(scl_handle, scl_line, 1) bit = LGPIO.gpio_read(sda_handle, sda_line) LGPIO.gpio_write(scl_handle, scl_line, 0) bit end |
#read_byte(ack) ⇒ Object
70 71 72 73 74 75 76 77 78 79 |
# File 'lib/lgpio/i2c_bitbang.rb', line 70 def read_byte(ack) byte = 0 i = 0 while i < 8 byte = (byte << 1) | read_bit i = i + 1 end write_bit(ack ? 0 : 1) byte end |
#read_byte_c(ack) ⇒ Object
91 92 93 |
# File 'lib/lgpio/i2c_bitbang.rb', line 91 def read_byte_c(ack) LGPIO.i2c_bb_read_byte(@scl_handle, @scl_line, @sda_handle, @sda_line, ack) end |
#read_form(address) ⇒ Object
41 42 43 |
# File 'lib/lgpio/i2c_bitbang.rb', line 41 def read_form(address) (address << 1) | 0b00000001 end |
#search ⇒ Object
138 139 140 141 142 143 144 145 146 147 |
# File 'lib/lgpio/i2c_bitbang.rb', line 138 def search found = [] VALID_ADDRESSES.each do |address| start # Device present if ACK received when we write its address to the bus. found << address if write_byte(write_form(address)) stop end found end |
#set_sda(value) ⇒ Object
32 33 34 35 |
# File 'lib/lgpio/i2c_bitbang.rb', line 32 def set_sda(value) return if (@sda_state == value) LGPIO.gpio_write(sda_handle, sda_line, @sda_state = value) end |
#start ⇒ Object
45 46 47 48 |
# File 'lib/lgpio/i2c_bitbang.rb', line 45 def start LGPIO.gpio_write(sda_handle, sda_line, 0) LGPIO.gpio_write(scl_handle, scl_line, 0) end |
#stop ⇒ Object
50 51 52 53 54 |
# File 'lib/lgpio/i2c_bitbang.rb', line 50 def stop LGPIO.gpio_write(sda_handle, sda_line, 0) LGPIO.gpio_write(scl_handle, scl_line, 1) LGPIO.gpio_write(sda_handle, sda_line, 1) end |
#write(address, bytes) ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/lgpio/i2c_bitbang.rb', line 122 def write(address, bytes) raise ArgumentError, "invalid I2C address: #{address}. Range is 0x08..0x77" unless VALID_ADDRESSES.include?(address) raise ArgumentError, "invalid byte Array to write: #{bytes}" unless bytes.kind_of?(Array) start write_byte(write_form(address)) # Bit-bang per-byte in Ruby. # bytes.each { |byte| write_byte(byte) } # Bit-bang per-byte in C. bytes.each { |byte| write_byte_c(byte) } stop end |
#write_bit(bit) ⇒ Object
64 65 66 67 68 |
# File 'lib/lgpio/i2c_bitbang.rb', line 64 def write_bit(bit) set_sda(bit) LGPIO.gpio_write(scl_handle, scl_line, 1) LGPIO.gpio_write(scl_handle, scl_line, 0) end |
#write_byte(byte) ⇒ Object
81 82 83 84 85 86 87 88 89 |
# File 'lib/lgpio/i2c_bitbang.rb', line 81 def write_byte(byte) i = 7 while i >= 0 write_bit (byte >> i) & 0b1 i = i - 1 end # Return ACK (SDA pulled low) or NACK (SDA stayed high). (read_bit == 0) end |
#write_byte_c(byte) ⇒ Object
95 96 97 |
# File 'lib/lgpio/i2c_bitbang.rb', line 95 def write_byte_c(byte) LGPIO.i2c_bb_write_byte(@scl_handle, @scl_line, @sda_handle, @sda_line, byte) end |
#write_form(address) ⇒ Object
37 38 39 |
# File 'lib/lgpio/i2c_bitbang.rb', line 37 def write_form(address) (address << 1) end |