-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathi2c_bitbang.rb
More file actions
executable file
·107 lines (92 loc) · 2.25 KB
/
i2c_bitbang.rb
File metadata and controls
executable file
·107 lines (92 loc) · 2.25 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
module LGPIO
class I2CBitBang
attr_reader :handle, :scl, :sda
def initialize(handle, scl, sda)
@handle = handle
@scl = scl
@sda = sda
initialize_pins
end
def initialize_pins
LGPIO.gpio_claim_output(handle, LGPIO::SET_PULL_NONE, scl, LGPIO::HIGH)
LGPIO.gpio_claim_output(handle, LGPIO::SET_OPEN_DRAIN | LGPIO::SET_PULL_UP, sda, LGPIO::HIGH)
end
def write_form(address)
(address << 1)
end
def read_form(address)
(address << 1) | 0b00000001
end
def start
LGPIO.gpio_write(handle, sda, 0)
LGPIO.gpio_write(handle, scl, 0)
end
def stop
LGPIO.gpio_write(handle, sda, 0)
LGPIO.gpio_write(handle, scl, 1)
LGPIO.gpio_write(handle, sda, 1)
end
def read_bit
LGPIO.gpio_write(handle, sda, 1)
LGPIO.gpio_write(handle, scl, 1)
bit = LGPIO.gpio_read(handle, sda)
LGPIO.gpio_write(handle, scl, 0)
bit
end
def write_bit(bit)
LGPIO.gpio_write(handle, sda, bit)
LGPIO.gpio_write(handle, scl, 1)
LGPIO.gpio_write(handle, scl, 0)
end
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
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
def read(address, count)
start
ack = write_byte(read_form(address))
return nil unless ack
# Read number of bytes, and ACK for all but the last one.
bytes = []
i = 0
while (i < count-1) do
bytes << read_byte(true)
i = i + 1
end
bytes << read_byte(false)
stop
bytes
end
def write(address, bytes)
start
write_byte(write_form(address))
bytes.each { |byte| write_byte(byte) }
stop
end
def search
found = []
(0x08..0x77).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
end
end