lgpio 0.1.5 → 0.1.6
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/README.md +42 -28
- data/examples/bench_in.rb +1 -1
- data/examples/bench_out.rb +1 -1
- data/examples/blink.rb +1 -1
- data/examples/dht.rb +47 -0
- data/examples/group_in.rb +2 -2
- data/examples/group_out.rb +1 -1
- data/examples/hcsr04.rb +32 -0
- data/examples/i2c_aht10.rb +2 -1
- data/examples/i2c_aht10_zip.rb +2 -1
- data/examples/i2c_bitbang-rb_aht10.rb +40 -0
- data/examples/i2c_bitbang-rb_ssd1306_bench.rb +35 -0
- data/examples/i2c_bitbang_aht10.rb +40 -0
- data/examples/i2c_bitbang_search.rb +20 -0
- data/examples/i2c_bitbang_ssd1306_bench.rb +35 -0
- data/examples/i2c_ssd1306_bench.rb +6 -5
- data/examples/infrared.rb +22 -0
- data/examples/momentary.rb +2 -2
- data/examples/one_wire_ds18b20.rb +30 -0
- data/examples/one_wire_search.rb +15 -0
- data/examples/pwm.rb +1 -1
- data/examples/reports.rb +1 -1
- data/examples/rotary_encoder.rb +3 -3
- data/examples/rotary_encoder_led.rb +4 -4
- data/examples/spi_bitbang_loopback.rb +25 -0
- data/examples/spi_bitbang_ssd1306_bench.rb +51 -0
- data/examples/spi_bitbang_ssd1306_sim_bench.rb +48 -0
- data/examples/wave.rb +1 -1
- data/ext/lgpio/lgpio.c +454 -9
- data/lib/lgpio/hardware_pwm.rb +18 -5
- data/lib/lgpio/i2c_bitbang.rb +117 -0
- data/lib/lgpio/infrared.rb +8 -0
- data/lib/lgpio/one_wire.rb +171 -0
- data/lib/lgpio/spi_bitbang.rb +109 -0
- data/lib/lgpio/version.rb +1 -1
- data/lib/lgpio.rb +6 -0
- metadata +19 -3
- data/examples/spi_read.rb +0 -14
@@ -0,0 +1,117 @@
|
|
1
|
+
module LGPIO
|
2
|
+
class I2CBitBang
|
3
|
+
VALID_ADDRESSES = (0x08..0x77).to_a
|
4
|
+
|
5
|
+
attr_reader :handle, :scl, :sda
|
6
|
+
|
7
|
+
def initialize(handle, scl, sda)
|
8
|
+
@handle = handle
|
9
|
+
@scl = scl
|
10
|
+
@sda = sda
|
11
|
+
@sda_state = nil
|
12
|
+
initialize_pins
|
13
|
+
end
|
14
|
+
|
15
|
+
def initialize_pins
|
16
|
+
LGPIO.gpio_claim_output(handle, LGPIO::SET_PULL_NONE, scl, LGPIO::HIGH)
|
17
|
+
LGPIO.gpio_claim_output(handle, LGPIO::SET_OPEN_DRAIN | LGPIO::SET_PULL_UP, sda, LGPIO::HIGH)
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_sda(value)
|
21
|
+
return if (@sda_state == value)
|
22
|
+
LGPIO.gpio_write(handle, sda, @sda_state = value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def write_form(address)
|
26
|
+
(address << 1)
|
27
|
+
end
|
28
|
+
|
29
|
+
def read_form(address)
|
30
|
+
(address << 1) | 0b00000001
|
31
|
+
end
|
32
|
+
|
33
|
+
def start
|
34
|
+
LGPIO.gpio_write(handle, sda, 0)
|
35
|
+
LGPIO.gpio_write(handle, scl, 0)
|
36
|
+
end
|
37
|
+
|
38
|
+
def stop
|
39
|
+
LGPIO.gpio_write(handle, sda, 0)
|
40
|
+
LGPIO.gpio_write(handle, scl, 1)
|
41
|
+
LGPIO.gpio_write(handle, sda, 1)
|
42
|
+
end
|
43
|
+
|
44
|
+
def read_bit
|
45
|
+
set_sda(1)
|
46
|
+
LGPIO.gpio_write(handle, scl, 1)
|
47
|
+
bit = LGPIO.gpio_read(handle, sda)
|
48
|
+
LGPIO.gpio_write(handle, scl, 0)
|
49
|
+
bit
|
50
|
+
end
|
51
|
+
|
52
|
+
def write_bit(bit)
|
53
|
+
set_sda(bit)
|
54
|
+
LGPIO.gpio_write(handle, scl, 1)
|
55
|
+
LGPIO.gpio_write(handle, scl, 0)
|
56
|
+
end
|
57
|
+
|
58
|
+
def read_byte(ack)
|
59
|
+
byte = 0
|
60
|
+
i = 0
|
61
|
+
while i < 8
|
62
|
+
byte = (byte << 1) | read_bit
|
63
|
+
i = i + 1
|
64
|
+
end
|
65
|
+
write_bit(ack ? 0 : 1)
|
66
|
+
byte
|
67
|
+
end
|
68
|
+
|
69
|
+
def write_byte(byte)
|
70
|
+
i = 7
|
71
|
+
while i >= 0
|
72
|
+
write_bit (byte >> i) & 0b1
|
73
|
+
i = i - 1
|
74
|
+
end
|
75
|
+
# Return ACK (SDA pulled low) or NACK (SDA stayed high).
|
76
|
+
(read_bit == 0)
|
77
|
+
end
|
78
|
+
|
79
|
+
def read(address, length)
|
80
|
+
raise ArgumentError, "invalid I2C address: #{address}. Range is 0x08..0x77" unless VALID_ADDRESSES.include?(address)
|
81
|
+
raise ArgumentError, "invalid Integer for read length: #{length}" unless length.kind_of?(Integer)
|
82
|
+
|
83
|
+
start
|
84
|
+
ack = write_byte(read_form(address))
|
85
|
+
return nil unless ack
|
86
|
+
|
87
|
+
# Read length bytes, and ACK for all but the last one.
|
88
|
+
bytes = []
|
89
|
+
(length-1).times { bytes << read_byte(true) }
|
90
|
+
bytes << read_byte(false)
|
91
|
+
stop
|
92
|
+
|
93
|
+
bytes
|
94
|
+
end
|
95
|
+
|
96
|
+
def write(address, bytes)
|
97
|
+
raise ArgumentError, "invalid I2C address: #{address}. Range is 0x08..0x77" unless VALID_ADDRESSES.include?(address)
|
98
|
+
raise ArgumentError, "invalid byte Array to write: #{bytes}" unless bytes.kind_of?(Array)
|
99
|
+
|
100
|
+
start
|
101
|
+
write_byte(write_form(address))
|
102
|
+
bytes.each { |byte| write_byte(byte) }
|
103
|
+
stop
|
104
|
+
end
|
105
|
+
|
106
|
+
def search
|
107
|
+
found = []
|
108
|
+
VALID_ADDRESSES.each do |address|
|
109
|
+
start
|
110
|
+
# Device present if ACK received when we write its address to the bus.
|
111
|
+
found << address if write_byte(write_form(address))
|
112
|
+
stop
|
113
|
+
end
|
114
|
+
found
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,171 @@
|
|
1
|
+
module LGPIO
|
2
|
+
class OneWire
|
3
|
+
# Constants
|
4
|
+
READ_POWER_SUPPLY = 0xB4
|
5
|
+
CONVERT_T = 0x44
|
6
|
+
SEARCH_ROM = 0xF0
|
7
|
+
READ_ROM = 0x33
|
8
|
+
SKIP_ROM = 0xCC
|
9
|
+
MATCH_ROM = 0x55
|
10
|
+
ALARM_SEARCH = 0xEC
|
11
|
+
READ_SCRATCH = 0xBE
|
12
|
+
WRITE_SCRATCH = 0x4E
|
13
|
+
COPY_SCRATCH = 0x48
|
14
|
+
RECALL_EEPROM = 0xB8
|
15
|
+
|
16
|
+
attr_reader :handle, :gpio, :found_addresses
|
17
|
+
|
18
|
+
def initialize(handle, gpio)
|
19
|
+
@handle = handle
|
20
|
+
@gpio = gpio
|
21
|
+
@found_addresses = []
|
22
|
+
LGPIO.gpio_claim_output(handle, LGPIO::SET_OPEN_DRAIN | LGPIO::SET_PULL_UP, gpio, LGPIO::HIGH)
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset
|
26
|
+
# LGPIO.one_wire_reset returns 0 if device present on bus.
|
27
|
+
return (LGPIO.one_wire_reset(handle, gpio) == 0)
|
28
|
+
end
|
29
|
+
|
30
|
+
def read(byte_count)
|
31
|
+
read_bytes = []
|
32
|
+
byte_count.times do
|
33
|
+
byte = 0b00000000
|
34
|
+
8.times { |i| byte |= LGPIO.one_wire_bit_read(handle, gpio) << i }
|
35
|
+
read_bytes << byte
|
36
|
+
end
|
37
|
+
read_bytes
|
38
|
+
end
|
39
|
+
|
40
|
+
def write(byte_array, parasite: nil)
|
41
|
+
byte_array.each do |byte|
|
42
|
+
8.times { |i| LGPIO.one_wire_bit_write(handle, gpio, (byte >> i) & 0b1) }
|
43
|
+
end
|
44
|
+
# Drive bus high to feed parasite capacitor after write.
|
45
|
+
LGPIO.gpio_write(handle, gpio, LGPIO::HIGH) if parasite
|
46
|
+
end
|
47
|
+
|
48
|
+
def search
|
49
|
+
branch_mask = 0
|
50
|
+
high_discrepancy = 0
|
51
|
+
|
52
|
+
loop do
|
53
|
+
reset
|
54
|
+
write [SEARCH_ROM]
|
55
|
+
result = search_pass(branch_mask)
|
56
|
+
|
57
|
+
address, high_discrepancy = parse_search_result(result)
|
58
|
+
@found_addresses << address
|
59
|
+
|
60
|
+
# No unsearched discrepancies left.
|
61
|
+
break if high_discrepancy == -1
|
62
|
+
|
63
|
+
# Force highest new discrepancy to be a 1 on the next search.
|
64
|
+
# i.e. Go as deep as possible into each branch found then back out.
|
65
|
+
#
|
66
|
+
branch_mask = branch_mask | (2 ** high_discrepancy)
|
67
|
+
|
68
|
+
# Clear bits above high_discrepancy so we don't repeat branches.
|
69
|
+
# When high_discrepancy < MSB of branch_mask, this moves us
|
70
|
+
# one node out, closer to the root, and finishing the search.
|
71
|
+
#
|
72
|
+
unset_mask = 0xFFFFFFFFFFFFFFFF >> (63 - high_discrepancy)
|
73
|
+
branch_mask = branch_mask & unset_mask
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Read a single 64-bit address and complement from the bus.
|
78
|
+
def search_pass(mask)
|
79
|
+
bytes = []
|
80
|
+
|
81
|
+
8.times do |i|
|
82
|
+
addr = 0
|
83
|
+
comp = 0
|
84
|
+
8.times do |j|
|
85
|
+
addr |= LGPIO.one_wire_bit_read(handle, gpio) << j
|
86
|
+
comp |= LGPIO.one_wire_bit_read(handle, gpio) << j
|
87
|
+
|
88
|
+
# A set (1) mask bit means we're searching a branch with that bit set.
|
89
|
+
# Force it to be 1 on this pass. Write 1 to both the bus and address bit.
|
90
|
+
#
|
91
|
+
# Don't change the complement bit from 0, Even if the bus said 0/0,
|
92
|
+
# send back 1/0, hiding known discrepancies, only sending new ones.
|
93
|
+
#
|
94
|
+
# Mask is a 64-bit number, not byte array.
|
95
|
+
if ((mask >> (i*8 + j)) & 0b1) == 1
|
96
|
+
LGPIO.one_wire_bit_write(handle, gpio, 1)
|
97
|
+
addr |= 1 << j
|
98
|
+
|
99
|
+
# Whether there was no "1-branch" marked for this bit, or there is no
|
100
|
+
# discrepancy at all, just echo address bit to the bus. We will
|
101
|
+
# compare addr/comp to find discrepancies for future passes.
|
102
|
+
else
|
103
|
+
LGPIO.one_wire_bit_write(handle, gpio, (addr >> j) & 0b1)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
bytes << addr
|
107
|
+
bytes << comp
|
108
|
+
end
|
109
|
+
|
110
|
+
# 16 bytes, address and complement bytes interleaved LSByteFIRST.
|
111
|
+
# DON'T CHANGE! #split_search_result deals with it. denko uses #search_pass
|
112
|
+
# directly on Linux, but MCUs send it this format to save RAM. Always match it.
|
113
|
+
return bytes
|
114
|
+
end
|
115
|
+
|
116
|
+
def parse_search_result(result)
|
117
|
+
address, complement = split_search_result(result)
|
118
|
+
|
119
|
+
raise "OneWire device not connected, or disconnected during search" if (address & complement) > 0
|
120
|
+
raise "CRC error during OneWire search" unless OneWire.crc(address)
|
121
|
+
|
122
|
+
# Gives 0 at every discrepancy we didn't write 1 for on this pass.
|
123
|
+
new_discrepancies = address ^ complement
|
124
|
+
|
125
|
+
high_discrepancy = -1
|
126
|
+
(0..63).each { |i| high_discrepancy = i if new_discrepancies[i] == 0 }
|
127
|
+
|
128
|
+
[address, high_discrepancy]
|
129
|
+
end
|
130
|
+
|
131
|
+
# Convert interleaved address/complement bytes to 64-bit numbers.
|
132
|
+
def split_search_result(data)
|
133
|
+
address = 0
|
134
|
+
complement = 0
|
135
|
+
data.reverse.each_slice(2) do |comp_byte, addr_byte|
|
136
|
+
address = (address << 8) | addr_byte
|
137
|
+
complement = (complement << 8) | comp_byte
|
138
|
+
end
|
139
|
+
[address, complement]
|
140
|
+
end
|
141
|
+
|
142
|
+
# CRC Class Methods
|
143
|
+
def self.crc(data)
|
144
|
+
calculated, received = self.calculate_crc(data)
|
145
|
+
calculated == received
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.calculate_crc(data)
|
149
|
+
if data.class == Integer
|
150
|
+
bytes = address_to_bytes(data)
|
151
|
+
else
|
152
|
+
bytes = data
|
153
|
+
end
|
154
|
+
|
155
|
+
crc = 0b00000000
|
156
|
+
bytes.take(bytes.length - 1).each do |byte|
|
157
|
+
for bit in (0..7)
|
158
|
+
xor = byte[bit] ^ crc[0]
|
159
|
+
crc = crc ^ ((xor * (2 ** 3)) | (xor * (2 ** 4)))
|
160
|
+
crc = crc >> 1
|
161
|
+
crc = crc | (xor * (2 ** 7))
|
162
|
+
end
|
163
|
+
end
|
164
|
+
[crc, bytes.last]
|
165
|
+
end
|
166
|
+
|
167
|
+
def self.address_to_bytes(address)
|
168
|
+
[address].pack('Q<').split("").map(&:ord)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module LGPIO
|
2
|
+
class SPIBitBang
|
3
|
+
attr_reader :handle, :clock, :input, :output
|
4
|
+
|
5
|
+
def initialize(options={})
|
6
|
+
@handle = options[:handle]
|
7
|
+
@clock = options[:clock] || options[:sck] || options[:clk]
|
8
|
+
@input = options[:input] || options[:poci] || options[:miso]
|
9
|
+
@output = options[:output] || options[:pico] || options[:mosi]
|
10
|
+
|
11
|
+
raise ArgumentError, "a gpiochip :handle is required" unless @handle
|
12
|
+
raise ArgumentError, "either input/:poci/:miso OR :output/:pico/:mosi pin required" unless (@input || @output)
|
13
|
+
raise ArgumentError, ":clock/:sck/:clk pin required" unless @clock
|
14
|
+
|
15
|
+
@output_state = nil
|
16
|
+
initialize_pins
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize_pins
|
20
|
+
LGPIO.gpio_claim_output(handle, LGPIO::SET_PULL_NONE, clock, LGPIO::LOW)
|
21
|
+
LGPIO.gpio_claim_input(handle, LGPIO::SET_PULL_NONE, input) if input
|
22
|
+
LGPIO.gpio_claim_output(handle, LGPIO::SET_PULL_NONE, output, LGPIO::LOW) if output
|
23
|
+
end
|
24
|
+
|
25
|
+
def set_output(level)
|
26
|
+
return if (level == @output_state)
|
27
|
+
LGPIO.gpio_write(handle, output, @output_state = level)
|
28
|
+
end
|
29
|
+
|
30
|
+
def transfer_bit(write_bit, reading: false, mode: 0)
|
31
|
+
case mode
|
32
|
+
when 0
|
33
|
+
set_output(write_bit) if write_bit
|
34
|
+
LGPIO.gpio_write(handle, clock, 1)
|
35
|
+
read_bit = LGPIO.gpio_read(handle, input) if reading
|
36
|
+
LGPIO.gpio_write(handle, clock, 0)
|
37
|
+
when 1
|
38
|
+
LGPIO.gpio_write(handle, clock, 1)
|
39
|
+
set_output(write_bit) if write_bit
|
40
|
+
LGPIO.gpio_write(handle, clock, 0)
|
41
|
+
read_bit = LGPIO.gpio_read(handle, input) if reading
|
42
|
+
when 2
|
43
|
+
set_output(write_bit) if write_bit
|
44
|
+
LGPIO.gpio_write(handle, clock, 0)
|
45
|
+
read_bit = LGPIO.gpio_read(handle, input) if reading
|
46
|
+
LGPIO.gpio_write(handle, clock, 1)
|
47
|
+
when 3
|
48
|
+
LGPIO.gpio_write(handle, clock, 0)
|
49
|
+
set_output(write_bit) if write_bit
|
50
|
+
LGPIO.gpio_write(handle, clock, 1)
|
51
|
+
read_bit = LGPIO.gpio_read(handle, input) if reading
|
52
|
+
else
|
53
|
+
raise ArgumentError, "invalid SPI mode: #{mode} given"
|
54
|
+
end
|
55
|
+
return reading ? read_bit : nil
|
56
|
+
end
|
57
|
+
|
58
|
+
def transfer_byte(byte, reading: false, order: :msbfirst, mode: 0)
|
59
|
+
read_byte = reading ? 0 : nil
|
60
|
+
|
61
|
+
if (order == :msbfirst)
|
62
|
+
i = 7
|
63
|
+
while i >= 0
|
64
|
+
write_bit = byte ? (byte >> i) & 0b1 : nil
|
65
|
+
read_bit = transfer_bit(write_bit, mode: mode, reading: reading)
|
66
|
+
read_byte = (read_byte << 1) | read_bit if reading
|
67
|
+
i = i - 1
|
68
|
+
end
|
69
|
+
else
|
70
|
+
i = 0
|
71
|
+
while i < 8
|
72
|
+
write_bit = byte ? (byte >> i) : nil
|
73
|
+
read_bit = transfer_bit(write_bit, mode: mode, reading: reading)
|
74
|
+
read_byte = read_byte | (read_bit << i) if reading
|
75
|
+
i = i + 1
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
read_byte
|
80
|
+
end
|
81
|
+
|
82
|
+
def transfer(write: [], read: 0, select: nil, order: :msbfirst, mode: 0)
|
83
|
+
# Idle clock state depends on SPI mode.
|
84
|
+
case mode
|
85
|
+
when 0..1
|
86
|
+
LGPIO.gpio_write(handle, clock, 0)
|
87
|
+
when 2..3
|
88
|
+
LGPIO.gpio_write(handle, clock, 1)
|
89
|
+
else
|
90
|
+
raise ArgumentError, "invalid SPI mode: #{mode} given"
|
91
|
+
end
|
92
|
+
raise ArgumentError, "invalid Array for write: #{write}" unless write.kind_of?(Array)
|
93
|
+
raise ArgumentError, "invalid Integer for read: #{read}" unless read.kind_of?(Integer)
|
94
|
+
|
95
|
+
read_bytes = (read > 0) ? [] : nil
|
96
|
+
LGPIO.gpio_write(handle, select, 0) if select
|
97
|
+
|
98
|
+
i = 0
|
99
|
+
while (i < read) || (i < write.length)
|
100
|
+
read_byte = transfer_byte(write[i], reading: (i < read), order: order, mode: mode)
|
101
|
+
read_bytes << read_byte if read_byte
|
102
|
+
i = i + 1
|
103
|
+
end
|
104
|
+
|
105
|
+
LGPIO.gpio_write(handle, select, 1) if select
|
106
|
+
read_bytes
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/lgpio/version.rb
CHANGED
data/lib/lgpio.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
1
|
require_relative 'lgpio/lgpio'
|
2
2
|
require_relative 'lgpio/version'
|
3
|
+
|
4
|
+
require_relative 'lgpio/i2c_bitbang'
|
5
|
+
require_relative 'lgpio/spi_bitbang'
|
6
|
+
require_relative 'lgpio/one_wire'
|
7
|
+
|
3
8
|
require_relative 'lgpio/hardware_pwm'
|
4
9
|
require_relative 'lgpio/positional_servo'
|
10
|
+
require_relative 'lgpio/infrared'
|
5
11
|
|
6
12
|
module LGPIO
|
7
13
|
LOW = 0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lgpio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- vickash
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-09-19 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Use GPIO / PWM / I2C / SPI / UART on Linux SBCs in Ruby
|
14
14
|
email: mail@vickash.com
|
@@ -24,19 +24,31 @@ files:
|
|
24
24
|
- examples/bench_in.rb
|
25
25
|
- examples/bench_out.rb
|
26
26
|
- examples/blink.rb
|
27
|
+
- examples/dht.rb
|
27
28
|
- examples/group_in.rb
|
28
29
|
- examples/group_out.rb
|
30
|
+
- examples/hcsr04.rb
|
29
31
|
- examples/i2c_aht10.rb
|
30
32
|
- examples/i2c_aht10_zip.rb
|
33
|
+
- examples/i2c_bitbang-rb_aht10.rb
|
34
|
+
- examples/i2c_bitbang-rb_ssd1306_bench.rb
|
35
|
+
- examples/i2c_bitbang_aht10.rb
|
36
|
+
- examples/i2c_bitbang_search.rb
|
37
|
+
- examples/i2c_bitbang_ssd1306_bench.rb
|
31
38
|
- examples/i2c_ssd1306_bench.rb
|
39
|
+
- examples/infrared.rb
|
32
40
|
- examples/momentary.rb
|
41
|
+
- examples/one_wire_ds18b20.rb
|
42
|
+
- examples/one_wire_search.rb
|
33
43
|
- examples/pwm.rb
|
34
44
|
- examples/reports.rb
|
35
45
|
- examples/rotary_encoder.rb
|
36
46
|
- examples/rotary_encoder_led.rb
|
37
47
|
- examples/servo.rb
|
48
|
+
- examples/spi_bitbang_loopback.rb
|
49
|
+
- examples/spi_bitbang_ssd1306_bench.rb
|
50
|
+
- examples/spi_bitbang_ssd1306_sim_bench.rb
|
38
51
|
- examples/spi_loopback.rb
|
39
|
-
- examples/spi_read.rb
|
40
52
|
- examples/spi_ws2812.rb
|
41
53
|
- examples/spi_ws2812_bounce.rb
|
42
54
|
- examples/wave.rb
|
@@ -45,7 +57,11 @@ files:
|
|
45
57
|
- lgpio.gemspec
|
46
58
|
- lib/lgpio.rb
|
47
59
|
- lib/lgpio/hardware_pwm.rb
|
60
|
+
- lib/lgpio/i2c_bitbang.rb
|
61
|
+
- lib/lgpio/infrared.rb
|
62
|
+
- lib/lgpio/one_wire.rb
|
48
63
|
- lib/lgpio/positional_servo.rb
|
64
|
+
- lib/lgpio/spi_bitbang.rb
|
49
65
|
- lib/lgpio/version.rb
|
50
66
|
homepage: https://github.com/denko-rb/lgpio
|
51
67
|
licenses:
|
data/examples/spi_read.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'lgpio'
|
2
|
-
|
3
|
-
SPI_DEV = 1
|
4
|
-
SPI_CHAN = 0
|
5
|
-
SPI_MODE = 0
|
6
|
-
SPI_BAUD = 1_000_000
|
7
|
-
|
8
|
-
spi_handle = LGPIO.spi_open(SPI_DEV, SPI_CHAN, SPI_BAUD, SPI_MODE)
|
9
|
-
|
10
|
-
# Pull MISO high or low. High gives array of 255, low array of 0.
|
11
|
-
rx_bytes = LGPIO.spi_read(spi_handle, 8)
|
12
|
-
puts "RX bytes: #{rx_bytes.inspect}"
|
13
|
-
|
14
|
-
LGPIO.spi_close(spi_handle)
|