lgpio 0.1.9 → 0.1.10
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 +4 -4
- data/examples/i2c_bb_aht10.rb +14 -4
- data/examples/i2c_bb_search.rb +13 -3
- data/examples/i2c_bb_ssd1306_bench.rb +11 -4
- data/examples/spi_bb_loopback.rb +6 -1
- data/examples/spi_bb_sim_bench.rb +6 -1
- data/examples/spi_bb_ssd1306_bench.rb +39 -25
- data/lib/lgpio/i2c_bitbang.rb +27 -19
- data/lib/lgpio/spi_bitbang.rb +36 -28
- data/lib/lgpio/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4da526bc3f239adf23035ca2c8923463667f979038b01fe0f8b63f0ad017a0e1
|
4
|
+
data.tar.gz: 6beafa4839875a6aac25f78a0b4b3e4fa25a28569269254ec4dcea27bfc06572
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: af9365d7c43fc0f7d5bab7c360e5a2e9325f2c3f7b7015ffff39d98ee3c4c2041123dfb81354d5d0113a06daab31910d18ed3fcee91dd75ded80c13b87543cba
|
7
|
+
data.tar.gz: aef0e2f50840a3b601627283f15df63f1f6ab5d065288f05275c07d04e0ad32def28d055acedfbba807c16f16b041d2df3bd5444f093bbb55c604aac2026c4ac
|
data/examples/i2c_bb_aht10.rb
CHANGED
@@ -9,13 +9,19 @@ SOFT_RESET = [0xBA]
|
|
9
9
|
INIT_AND_CALIBRATE = [0xE1, 0x08, 0x00]
|
10
10
|
START_MEASUREMENT = [0xAC, 0x33, 0x00]
|
11
11
|
|
12
|
-
|
12
|
+
SCL_CHIP = 0
|
13
13
|
SCL_PIN = 228
|
14
|
+
SDA_CHIP = 0
|
14
15
|
SDA_PIN = 270
|
15
16
|
ADDRESS = 0x38
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
scl_handle = LGPIO.chip_open(SCL_CHIP)
|
19
|
+
sda_handle = (SCL_CHIP == SDA_CHIP) ? scl_handle : LGPIO.chip_open(SDA_CHIP)
|
20
|
+
pin_hash = {
|
21
|
+
scl: { handle: scl_handle, line: SCL_PIN },
|
22
|
+
sda: { handle: sda_handle, line: SDA_PIN },
|
23
|
+
}
|
24
|
+
i2c_bb = LGPIO::I2CBitBang.new(pin_hash)
|
19
25
|
|
20
26
|
# Startup sequence
|
21
27
|
sleep(POWER_ON_DELAY)
|
@@ -24,11 +30,15 @@ sleep(RESET_DELAY)
|
|
24
30
|
i2c_bb.write(ADDRESS, INIT_AND_CALIBRATE)
|
25
31
|
sleep(COMMAND_DELAY)
|
26
32
|
|
27
|
-
# Read
|
33
|
+
# Read
|
28
34
|
i2c_bb.write(ADDRESS, START_MEASUREMENT)
|
29
35
|
sleep(MEASURE_DELAY)
|
30
36
|
bytes = i2c_bb.read(ADDRESS, DATA_LENGTH)
|
31
37
|
|
38
|
+
# Close
|
39
|
+
LGPIO.chip_close(scl_handle)
|
40
|
+
LGPIO.chip_close(sda_handle) unless (scl_handle == sda_handle)
|
41
|
+
|
32
42
|
# Humidity uses the upper 4 bits of the shared byte as its lowest 4 bits.
|
33
43
|
h_raw = ((bytes[1] << 16) | (bytes[2] << 8) | (bytes[3])) >> 4
|
34
44
|
humidity = (h_raw.to_f / 2**20) * 100
|
data/examples/i2c_bb_search.rb
CHANGED
@@ -1,13 +1,23 @@
|
|
1
1
|
require 'lgpio'
|
2
2
|
|
3
|
-
|
3
|
+
SCL_CHIP = 0
|
4
4
|
SCL_PIN = 228
|
5
|
+
SDA_CHIP = 0
|
5
6
|
SDA_PIN = 270
|
6
7
|
|
7
|
-
|
8
|
-
|
8
|
+
scl_handle = LGPIO.chip_open(SCL_CHIP)
|
9
|
+
sda_handle = (SCL_CHIP == SDA_CHIP) ? scl_handle : LGPIO.chip_open(SDA_CHIP)
|
10
|
+
pin_hash = {
|
11
|
+
scl: { handle: scl_handle, line: SCL_PIN },
|
12
|
+
sda: { handle: sda_handle, line: SDA_PIN },
|
13
|
+
}
|
14
|
+
i2c_bb = LGPIO::I2CBitBang.new(pin_hash)
|
15
|
+
|
9
16
|
devices = i2c_bb.search
|
10
17
|
|
18
|
+
LGPIO.chip_close(scl_handle)
|
19
|
+
LGPIO.chip_close(sda_handle) unless (scl_handle == sda_handle)
|
20
|
+
|
11
21
|
if devices.empty?
|
12
22
|
puts "No devices found on I2C bus"
|
13
23
|
else
|
@@ -5,13 +5,19 @@ START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
|
|
5
5
|
PATTERN_1 = [64] + Array.new(1024) { 0b00110011 }
|
6
6
|
PATTERN_2 = [64] + Array.new(1024) { 0b11001100 }
|
7
7
|
|
8
|
-
|
8
|
+
SCL_CHIP = 0
|
9
9
|
SCL_PIN = 228
|
10
|
+
SDA_CHIP = 0
|
10
11
|
SDA_PIN = 270
|
11
12
|
ADDRESS = 0x3C
|
12
13
|
|
13
|
-
|
14
|
-
|
14
|
+
scl_handle = LGPIO.chip_open(SCL_CHIP)
|
15
|
+
sda_handle = (SCL_CHIP == SDA_CHIP) ? scl_handle : LGPIO.chip_open(SDA_CHIP)
|
16
|
+
pin_hash = {
|
17
|
+
scl: { handle: scl_handle, line: SCL_PIN },
|
18
|
+
sda: { handle: sda_handle, line: SDA_PIN },
|
19
|
+
}
|
20
|
+
i2c_bb = LGPIO::I2CBitBang.new(pin_hash)
|
15
21
|
|
16
22
|
i2c_bb.write(ADDRESS, INIT_ARRAY)
|
17
23
|
FRAME_COUNT = 400
|
@@ -25,7 +31,8 @@ start = Time.now
|
|
25
31
|
end
|
26
32
|
finish = Time.now
|
27
33
|
|
28
|
-
LGPIO.chip_close(
|
34
|
+
LGPIO.chip_close(scl_handle)
|
35
|
+
LGPIO.chip_close(sda_handle) unless (scl_handle == sda_handle)
|
29
36
|
|
30
37
|
fps = FRAME_COUNT / (finish - start)
|
31
38
|
# Also calculate C calls per second, using roughly 23 calls per byte written.
|
data/examples/spi_bb_loopback.rb
CHANGED
@@ -10,7 +10,12 @@ ORDERS = [:msbfirst, :lsbfirst]
|
|
10
10
|
TX_BYTES = [0, 1, 2, 3, 4, 5, 6, 7]
|
11
11
|
|
12
12
|
chip_handle = LGPIO.chip_open(GPIO_CHIP)
|
13
|
-
|
13
|
+
pin_hash = {
|
14
|
+
clock: { handle: chip_handle, line: CLOCK_PIN },
|
15
|
+
input: { handle: chip_handle, line: INPUT_PIN },
|
16
|
+
output: { handle: chip_handle, line: OUTPUT_PIN },
|
17
|
+
}
|
18
|
+
spi_bb = LGPIO::SPIBitBang.new(pin_hash)
|
14
19
|
|
15
20
|
puts "TX bytes => #{TX_BYTES.inspect}"
|
16
21
|
|
@@ -12,7 +12,12 @@ PATTERN_2 = [0x3C << 1] + [64] + Array.new(1179) { 0b11001100 }
|
|
12
12
|
FRAME_COUNT = 400
|
13
13
|
|
14
14
|
chip_handle = LGPIO.chip_open(GPIO_CHIP)
|
15
|
-
|
15
|
+
pin_hash = {
|
16
|
+
clock: { handle: chip_handle, line: CLOCK_PIN },
|
17
|
+
input: { handle: chip_handle, line: INPUT_PIN },
|
18
|
+
output: { handle: chip_handle, line: OUTPUT_PIN },
|
19
|
+
}
|
20
|
+
spi_bb = LGPIO::SPIBitBang.new(pin_hash)
|
16
21
|
|
17
22
|
start = Time.now
|
18
23
|
(FRAME_COUNT / 2).times do
|
@@ -5,41 +5,55 @@ START_ARRAY = [0, 33, 0, 127, 34, 0, 7]
|
|
5
5
|
PATTERN_1 = Array.new(1024) { 0b00110011 }
|
6
6
|
PATTERN_2 = Array.new(1024) { 0b11001100 }
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
8
|
+
# Pins for Radxa Zero 3W
|
9
|
+
# Demonstration of how to use GPIOs across multiple /dev/gpiochip devices.
|
10
|
+
pins = {
|
11
|
+
clock: { chip: 1, line: 4 },
|
12
|
+
output: { chip: 3, line: 4 },
|
13
|
+
reset: { chip: 3, line: 5 },
|
14
|
+
dc: { chip: 3, line: 6 },
|
15
|
+
cs: { chip: 3, line: 7 },
|
16
|
+
}
|
17
|
+
|
18
|
+
# Open chip handles without duplicating.
|
19
|
+
open_handles = []
|
20
|
+
pins.each_value do |hash|
|
21
|
+
if hash[:handle] = open_handles[hash[:chip]]
|
22
|
+
else
|
23
|
+
hash[:handle] = LGPIO.chip_open(hash[:chip])
|
24
|
+
open_handles[hash[:chip]] = hash[:handle]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
puts pins.inspect
|
29
|
+
|
30
|
+
spi_bb = LGPIO::SPIBitBang.new(clock: pins[:clock], output: pins[:output])
|
31
|
+
LGPIO.gpio_claim_output(pins[:reset][:handle], pins[:reset][:line], LGPIO::SET_PULL_NONE, LGPIO::LOW)
|
32
|
+
LGPIO.gpio_claim_output(pins[:dc][:handle], pins[:dc][:line], LGPIO::SET_PULL_NONE, LGPIO::LOW)
|
33
|
+
LGPIO.gpio_claim_output(pins[:cs][:handle], pins[:cs][:line], LGPIO::SET_PULL_NONE, LGPIO::HIGH)
|
21
34
|
|
22
35
|
# OLED STARTUP
|
23
|
-
LGPIO.gpio_write(
|
24
|
-
LGPIO.gpio_write(
|
25
|
-
spi_bb.transfer(write: INIT_ARRAY, select:
|
36
|
+
LGPIO.gpio_write(pins[:reset][:handle], pins[:reset][:line], 1)
|
37
|
+
LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 0)
|
38
|
+
spi_bb.transfer(write: INIT_ARRAY, select: pins[:cs])
|
26
39
|
|
27
40
|
FRAME_COUNT = 400
|
28
41
|
|
29
42
|
start = Time.now
|
30
43
|
(FRAME_COUNT / 2).times do
|
31
|
-
LGPIO.gpio_write(
|
32
|
-
spi_bb.transfer(write: START_ARRAY, select:
|
33
|
-
LGPIO.gpio_write(
|
34
|
-
spi_bb.transfer(write: PATTERN_1, select:
|
35
|
-
LGPIO.gpio_write(
|
36
|
-
spi_bb.transfer(write: START_ARRAY, select:
|
37
|
-
LGPIO.gpio_write(
|
38
|
-
spi_bb.transfer(write: PATTERN_2, select:
|
44
|
+
LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 0)
|
45
|
+
spi_bb.transfer(write: START_ARRAY, select: pins[:cs])
|
46
|
+
LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 1)
|
47
|
+
spi_bb.transfer(write: PATTERN_1, select: pins[:cs])
|
48
|
+
LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 0)
|
49
|
+
spi_bb.transfer(write: START_ARRAY, select: pins[:cs])
|
50
|
+
LGPIO.gpio_write(pins[:dc][:handle], pins[:dc][:line], 1)
|
51
|
+
spi_bb.transfer(write: PATTERN_2, select: pins[:cs])
|
39
52
|
end
|
40
53
|
finish = Time.now
|
41
54
|
|
42
|
-
|
55
|
+
# Close all handles.
|
56
|
+
open_handles.compact.each { |h| LGPIO.chip_close(h) }
|
43
57
|
|
44
58
|
fps = FRAME_COUNT / (finish - start)
|
45
59
|
# Also calculate C calls per second, using roughly 20 calls per byte written.
|
data/lib/lgpio/i2c_bitbang.rb
CHANGED
@@ -2,24 +2,32 @@ module LGPIO
|
|
2
2
|
class I2CBitBang
|
3
3
|
VALID_ADDRESSES = (0x08..0x77).to_a
|
4
4
|
|
5
|
-
attr_reader :
|
5
|
+
attr_reader :scl_handle, :scl_line, :sda_handle, :sda_line
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
@
|
7
|
+
def initialize(options={})
|
8
|
+
scl = options[:scl]
|
9
|
+
sda = options[:sda]
|
10
|
+
|
11
|
+
@scl_handle = scl[:handle] if scl
|
12
|
+
@scl_line = scl[:line] if scl
|
13
|
+
raise ArgumentError, ":scl pin required as Hash, with :handle and :line required" unless (@scl_handle && @scl_line)
|
14
|
+
|
15
|
+
@sda_handle = sda[:handle] if sda
|
16
|
+
@sda_line = sda[:line] if sda
|
17
|
+
raise ArgumentError, ":sda pin required as Hash, with :handle and :line required" unless (@sda_handle && @sda_line)
|
18
|
+
|
19
|
+
@sda_state = nil
|
12
20
|
initialize_pins
|
13
21
|
end
|
14
22
|
|
15
23
|
def initialize_pins
|
16
|
-
LGPIO.gpio_claim_output(
|
17
|
-
LGPIO.gpio_claim_output(
|
24
|
+
LGPIO.gpio_claim_output(scl_handle, scl_line, LGPIO::SET_PULL_NONE, LGPIO::HIGH)
|
25
|
+
LGPIO.gpio_claim_output(sda_handle, sda_line, LGPIO::SET_OPEN_DRAIN | LGPIO::SET_PULL_UP, LGPIO::HIGH)
|
18
26
|
end
|
19
27
|
|
20
28
|
def set_sda(value)
|
21
29
|
return if (@sda_state == value)
|
22
|
-
LGPIO.gpio_write(
|
30
|
+
LGPIO.gpio_write(sda_handle, sda_line, @sda_state = value)
|
23
31
|
end
|
24
32
|
|
25
33
|
def write_form(address)
|
@@ -31,28 +39,28 @@ module LGPIO
|
|
31
39
|
end
|
32
40
|
|
33
41
|
def start
|
34
|
-
LGPIO.gpio_write(
|
35
|
-
LGPIO.gpio_write(
|
42
|
+
LGPIO.gpio_write(sda_handle, sda_line, 0)
|
43
|
+
LGPIO.gpio_write(scl_handle, scl_line, 0)
|
36
44
|
end
|
37
45
|
|
38
46
|
def stop
|
39
|
-
LGPIO.gpio_write(
|
40
|
-
LGPIO.gpio_write(
|
41
|
-
LGPIO.gpio_write(
|
47
|
+
LGPIO.gpio_write(sda_handle, sda_line, 0)
|
48
|
+
LGPIO.gpio_write(scl_handle, scl_line, 1)
|
49
|
+
LGPIO.gpio_write(sda_handle, sda_line, 1)
|
42
50
|
end
|
43
51
|
|
44
52
|
def read_bit
|
45
53
|
set_sda(1)
|
46
|
-
LGPIO.gpio_write(
|
47
|
-
bit = LGPIO.gpio_read(
|
48
|
-
LGPIO.gpio_write(
|
54
|
+
LGPIO.gpio_write(scl_handle, scl_line, 1)
|
55
|
+
bit = LGPIO.gpio_read(sda_handle, sda_line)
|
56
|
+
LGPIO.gpio_write(scl_handle, scl_line, 0)
|
49
57
|
bit
|
50
58
|
end
|
51
59
|
|
52
60
|
def write_bit(bit)
|
53
61
|
set_sda(bit)
|
54
|
-
LGPIO.gpio_write(
|
55
|
-
LGPIO.gpio_write(
|
62
|
+
LGPIO.gpio_write(scl_handle, scl_line, 1)
|
63
|
+
LGPIO.gpio_write(scl_handle, scl_line, 0)
|
56
64
|
end
|
57
65
|
|
58
66
|
def read_byte(ack)
|
data/lib/lgpio/spi_bitbang.rb
CHANGED
@@ -1,16 +1,24 @@
|
|
1
1
|
module LGPIO
|
2
2
|
class SPIBitBang
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :clock_handle, :input_handle, :output_handle
|
4
|
+
attr_reader :clock_line, :input_line, :output_line
|
4
5
|
|
5
6
|
def initialize(options={})
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@output = options[:output] || options[:pico] || options[:mosi]
|
7
|
+
clock = options[:clock]
|
8
|
+
input = options[:input]
|
9
|
+
output = options[:output]
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
raise ArgumentError, ":clock
|
11
|
+
@clock_handle = clock[:handle] if clock
|
12
|
+
@clock_line = clock[:line] if clock
|
13
|
+
raise ArgumentError, ":clock pin required as Hash, with :handle and :line required" unless (@clock_handle && @clock_line)
|
14
|
+
|
15
|
+
@input_handle = input[:handle] if input
|
16
|
+
@input_line = input[:line] if input
|
17
|
+
@output_handle = output[:handle] if output
|
18
|
+
@output_line = output[:line] if output
|
19
|
+
unless ((@input_handle && @input_line) || (@output_handle && @output_line))
|
20
|
+
raise ArgumentError, "either :input or :output pin required as Hash, with :handle and :line required"
|
21
|
+
end
|
14
22
|
|
15
23
|
@output_state = nil
|
16
24
|
initialize_pins
|
@@ -21,38 +29,38 @@ module LGPIO
|
|
21
29
|
end
|
22
30
|
|
23
31
|
def initialize_pins
|
24
|
-
LGPIO.gpio_claim_output(
|
25
|
-
LGPIO.gpio_claim_input(
|
26
|
-
LGPIO.gpio_claim_output(
|
32
|
+
LGPIO.gpio_claim_output(clock_handle, clock_line, LGPIO::SET_PULL_NONE, LGPIO::LOW)
|
33
|
+
LGPIO.gpio_claim_input(input_handle, input_line, LGPIO::SET_PULL_NONE) if input_line
|
34
|
+
LGPIO.gpio_claim_output(output_handle, output_line, LGPIO::SET_PULL_NONE, LGPIO::LOW) if output_line
|
27
35
|
end
|
28
36
|
|
29
37
|
def set_output(level)
|
30
38
|
return if (level == @output_state)
|
31
|
-
LGPIO.gpio_write(
|
39
|
+
LGPIO.gpio_write(output_handle, output_line, @output_state = level)
|
32
40
|
end
|
33
41
|
|
34
42
|
def transfer_bit(write_bit, reading: false, mode: 0)
|
35
43
|
case mode
|
36
44
|
when 0
|
37
45
|
set_output(write_bit) if write_bit
|
38
|
-
LGPIO.gpio_write(
|
39
|
-
read_bit = LGPIO.gpio_read(
|
40
|
-
LGPIO.gpio_write(
|
46
|
+
LGPIO.gpio_write(clock_handle, clock_line, 1)
|
47
|
+
read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
|
48
|
+
LGPIO.gpio_write(clock_handle, clock_line, 0)
|
41
49
|
when 1
|
42
|
-
LGPIO.gpio_write(
|
50
|
+
LGPIO.gpio_write(clock_handle, clock_line, 1)
|
43
51
|
set_output(write_bit) if write_bit
|
44
|
-
LGPIO.gpio_write(
|
45
|
-
read_bit = LGPIO.gpio_read(
|
52
|
+
LGPIO.gpio_write(clock_handle, clock_line, 0)
|
53
|
+
read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
|
46
54
|
when 2
|
47
55
|
set_output(write_bit) if write_bit
|
48
|
-
LGPIO.gpio_write(
|
49
|
-
read_bit = LGPIO.gpio_read(
|
50
|
-
LGPIO.gpio_write(
|
56
|
+
LGPIO.gpio_write(clock_handle, clock_line, 0)
|
57
|
+
read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
|
58
|
+
LGPIO.gpio_write(clock_handle, clock_line, 1)
|
51
59
|
when 3
|
52
|
-
LGPIO.gpio_write(
|
60
|
+
LGPIO.gpio_write(clock_handle, clock_line, 0)
|
53
61
|
set_output(write_bit) if write_bit
|
54
|
-
LGPIO.gpio_write(
|
55
|
-
read_bit = LGPIO.gpio_read(
|
62
|
+
LGPIO.gpio_write(clock_handle, clock_line, 1)
|
63
|
+
read_bit = LGPIO.gpio_read(input_handle, input_line) if reading
|
56
64
|
else
|
57
65
|
raise ArgumentError, "invalid SPI mode: #{mode} given"
|
58
66
|
end
|
@@ -87,9 +95,9 @@ module LGPIO
|
|
87
95
|
# Idle clock state depends on SPI mode.
|
88
96
|
case mode
|
89
97
|
when 0..1
|
90
|
-
LGPIO.gpio_write(
|
98
|
+
LGPIO.gpio_write(clock_handle, clock_line, 0)
|
91
99
|
when 2..3
|
92
|
-
LGPIO.gpio_write(
|
100
|
+
LGPIO.gpio_write(clock_handle, clock_line, 1)
|
93
101
|
else
|
94
102
|
raise ArgumentError, "invalid SPI mode: #{mode} given"
|
95
103
|
end
|
@@ -97,7 +105,7 @@ module LGPIO
|
|
97
105
|
raise ArgumentError, "invalid Integer for read: #{read}" unless read.kind_of?(Integer)
|
98
106
|
|
99
107
|
read_bytes = (read > 0) ? [] : nil
|
100
|
-
LGPIO.gpio_write(handle, select, 0) if select
|
108
|
+
LGPIO.gpio_write(select[:handle], select[:line], 0) if select
|
101
109
|
|
102
110
|
i = 0
|
103
111
|
while (i < read) || (i < write.length)
|
@@ -106,7 +114,7 @@ module LGPIO
|
|
106
114
|
i = i + 1
|
107
115
|
end
|
108
116
|
|
109
|
-
LGPIO.gpio_write(handle, select, 1) if select
|
117
|
+
LGPIO.gpio_write(select[:handle], select[:line], 1) if select
|
110
118
|
read_bytes
|
111
119
|
end
|
112
120
|
end
|
data/lib/lgpio/version.rb
CHANGED