lgpio 0.1.1 → 0.1.2
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 +1 -1
- data/examples/reports.rb +18 -0
- data/examples/rotary_encoder.rb +51 -0
- data/ext/lgpio/lgpio.c +59 -0
- data/lib/lgpio/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bb351b8041dc3f5e78ed92128c3c971cf3f9e35d247a71e8d4ce56acec87f32
|
4
|
+
data.tar.gz: a4df4836decc51de97ad16093bbd19e649cd02b675d6511c601feddde0cded66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f94daeeaba65d22c4ee2e0205a9399f18f886cc5f42e15f53a4991381756b7a33d97d29113918b809b6ff96d7900a327ee26d441d9249e86020cee7c21c34765
|
7
|
+
data.tar.gz: 367559fcd9750f88e728b80836c3dfa7d9273dcb2c734bc67faed29b23e177fc03e9e18df9678533907f3ddbe85be5d4d443a5d45404a03322ac09e586827e11
|
data/README.md
CHANGED
@@ -8,7 +8,7 @@ Ruby bindings for the [lgpio (lg)](https://github.com/joan2937/lg) C library, wh
|
|
8
8
|
|
9
9
|
- [x] GPIO Read/Write
|
10
10
|
- [x] GPIO Group Read/Write
|
11
|
-
- [
|
11
|
+
- [x] GPIO Alerts / Callbacks (read from a queue)
|
12
12
|
- [x] PWM (software-timed)
|
13
13
|
- [x] Wave (software-timed)
|
14
14
|
- [ ] I2C
|
data/examples/reports.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'lgpio'
|
2
|
+
|
3
|
+
GPIO_CHIP = 0
|
4
|
+
PIN = 76
|
5
|
+
|
6
|
+
chip_handle = LGPIO.chip_open(GPIO_CHIP)
|
7
|
+
|
8
|
+
LGPIO.gpio_claim_input(chip_handle, LGPIO::SET_PULL_NONE, PIN)
|
9
|
+
LGPIO.gpio_claim_alert(chip_handle, 0, LGPIO::BOTH_EDGES, PIN)
|
10
|
+
LGPIO.gpio_start_reporting
|
11
|
+
|
12
|
+
loop do
|
13
|
+
report = LGPIO.gpio_get_report
|
14
|
+
report ? puts(report) : sleep(0.001)
|
15
|
+
end
|
16
|
+
|
17
|
+
LGPIO.gpio_free(chip_handle, PIN)
|
18
|
+
LGPIO.chip_close(chip_handle)
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# Demo of a simple 30-detent rotary encoder.
|
3
|
+
# PIN_A = CLK/CLOCK, PIN_B = DT/DATA, PIN_SW = SWITCH
|
4
|
+
#
|
5
|
+
require 'lgpio'
|
6
|
+
|
7
|
+
GPIO_CHIP = 0
|
8
|
+
PIN_A = 76
|
9
|
+
PIN_B = 228
|
10
|
+
PIN_SW = 226
|
11
|
+
|
12
|
+
# Encoder state
|
13
|
+
position = 0
|
14
|
+
state_a = 0
|
15
|
+
state_b = 0
|
16
|
+
|
17
|
+
chip_handle = LGPIO.chip_open(GPIO_CHIP)
|
18
|
+
|
19
|
+
# Encoder pin setup
|
20
|
+
LGPIO.gpio_claim_input(chip_handle, LGPIO::SET_PULL_NONE, PIN_A)
|
21
|
+
LGPIO.gpio_claim_alert(chip_handle, 0, LGPIO::BOTH_EDGES, PIN_A)
|
22
|
+
LGPIO.gpio_claim_input(chip_handle, LGPIO::SET_PULL_NONE, PIN_B)
|
23
|
+
LGPIO.gpio_claim_alert(chip_handle, 0, LGPIO::BOTH_EDGES, PIN_B)
|
24
|
+
|
25
|
+
# Switch pin setup
|
26
|
+
LGPIO.gpio_claim_input(chip_handle, LGPIO::SET_PULL_UP, PIN_SW)
|
27
|
+
LGPIO.gpio_claim_alert(chip_handle, 0, LGPIO::FALLING_EDGE, PIN_SW)
|
28
|
+
|
29
|
+
# Start generating reports for GPIO level changes.
|
30
|
+
LGPIO.gpio_start_reporting
|
31
|
+
|
32
|
+
# Get and reports to update state.
|
33
|
+
loop do
|
34
|
+
report = LGPIO.gpio_get_report
|
35
|
+
if report
|
36
|
+
if report[:gpio] == PIN_A
|
37
|
+
# Half quadrature, so we count every detent.
|
38
|
+
state_a = report[:level]
|
39
|
+
elsif report[:gpio] == PIN_B
|
40
|
+
delta = (report[:level] == state_a) ? -1 : 1
|
41
|
+
position += delta
|
42
|
+
state_b = report[:level]
|
43
|
+
puts "Position: #{position}"
|
44
|
+
elsif report[:gpio] == PIN_SW
|
45
|
+
position = 0
|
46
|
+
puts "Position: 0"
|
47
|
+
end
|
48
|
+
else
|
49
|
+
sleep(0.001)
|
50
|
+
end
|
51
|
+
end
|
data/ext/lgpio/lgpio.c
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
#include <lgpio.h>
|
2
2
|
#include <ruby.h>
|
3
3
|
|
4
|
+
// Set up a queue for up to 2**16 GPIO reports.
|
5
|
+
static pthread_mutex_t queueLock;
|
6
|
+
#define QUEUE_LENGTH UINT16_MAX + 1
|
7
|
+
static lgGpioReport_t reportQueue[QUEUE_LENGTH];
|
8
|
+
static uint16_t qWritePos = 1;
|
9
|
+
static uint16_t qReadPos = 0;
|
10
|
+
|
4
11
|
static VALUE chip_open(VALUE self, VALUE gpio_dev) {
|
5
12
|
int result = lgGpiochipOpen(NUM2INT(gpio_dev));
|
6
13
|
return INT2NUM(result);
|
@@ -76,6 +83,50 @@ static VALUE group_write(VALUE self, VALUE handle, VALUE gpio, VALUE bits, VALUE
|
|
76
83
|
return INT2NUM(result);
|
77
84
|
}
|
78
85
|
|
86
|
+
static VALUE gpio_claim_alert(VALUE self, VALUE handle, VALUE flags, VALUE eFlags, VALUE gpio) {
|
87
|
+
int result = lgGpioClaimAlert(NUM2INT(handle), NUM2INT(flags), NUM2INT(eFlags), NUM2INT(gpio), -1);
|
88
|
+
return INT2NUM(result);
|
89
|
+
}
|
90
|
+
|
91
|
+
void queue_gpio_reports(int count, lgGpioAlert_p events, void *data){
|
92
|
+
pthread_mutex_lock(&queueLock);
|
93
|
+
for(int i=0; i<count; i++) {
|
94
|
+
memcpy(&reportQueue[qWritePos], &events[i].report, sizeof(lgGpioReport_t));
|
95
|
+
qWritePos += 1;
|
96
|
+
// qReadPos is the LAST report read. If passing by 1, increment it too. Lose oldest data first.
|
97
|
+
if (qWritePos - qReadPos == 1) qReadPos += 1;
|
98
|
+
}
|
99
|
+
pthread_mutex_unlock(&queueLock);
|
100
|
+
}
|
101
|
+
|
102
|
+
static VALUE gpio_start_reporting(VALUE self) {
|
103
|
+
lgGpioSetSamplesFunc(queue_gpio_reports, NULL);
|
104
|
+
}
|
105
|
+
|
106
|
+
static VALUE gpio_get_report(VALUE self){
|
107
|
+
VALUE hash = rb_hash_new();
|
108
|
+
bool popped = false;
|
109
|
+
|
110
|
+
pthread_mutex_lock(&queueLock);
|
111
|
+
// qWritePos is where the NEXT report will go. Always trail it by 1.
|
112
|
+
if (qWritePos - qReadPos != 1){
|
113
|
+
qReadPos += 1;
|
114
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("timestamp")), ULL2NUM(reportQueue[qReadPos].timestamp));
|
115
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("chip")), UINT2NUM(reportQueue[qReadPos].chip));
|
116
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("gpio")), UINT2NUM(reportQueue[qReadPos].gpio));
|
117
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("level")), UINT2NUM(reportQueue[qReadPos].level));
|
118
|
+
rb_hash_aset(hash, ID2SYM(rb_intern("flags")), UINT2NUM(reportQueue[qReadPos].flags));
|
119
|
+
popped = true;
|
120
|
+
}
|
121
|
+
pthread_mutex_unlock(&queueLock);
|
122
|
+
|
123
|
+
if (popped){
|
124
|
+
return hash;
|
125
|
+
} else {
|
126
|
+
return Qnil;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
79
130
|
static VALUE tx_busy(VALUE self, VALUE handle, VALUE gpio, VALUE kind) {
|
80
131
|
int result = lgTxBusy(NUM2INT(handle), NUM2INT(gpio), NUM2INT(kind));
|
81
132
|
return INT2NUM(result);
|
@@ -130,6 +181,9 @@ void Init_lgpio(void) {
|
|
130
181
|
rb_define_const(mLGPIO, "SET_PULL_UP", INT2NUM(LG_SET_PULL_UP));
|
131
182
|
rb_define_const(mLGPIO, "SET_PULL_DOWN", INT2NUM(LG_SET_PULL_DOWN));
|
132
183
|
rb_define_const(mLGPIO, "SET_PULL_NONE", INT2NUM(LG_SET_PULL_NONE));
|
184
|
+
rb_define_const(mLGPIO, "RISING_EDGE", INT2NUM(LG_RISING_EDGE));
|
185
|
+
rb_define_const(mLGPIO, "FALLING_EDGE", INT2NUM(LG_FALLING_EDGE));
|
186
|
+
rb_define_const(mLGPIO, "BOTH_EDGES", INT2NUM(LG_BOTH_EDGES));
|
133
187
|
rb_define_singleton_method(mLGPIO, "chip_open", chip_open, 1);
|
134
188
|
rb_define_singleton_method(mLGPIO, "chip_close", chip_close, 1);
|
135
189
|
rb_define_singleton_method(mLGPIO, "gpio_free", gpio_free, 2);
|
@@ -144,6 +198,11 @@ void Init_lgpio(void) {
|
|
144
198
|
rb_define_singleton_method(mLGPIO, "group_free", group_free, 2);
|
145
199
|
rb_define_singleton_method(mLGPIO, "group_read", group_read, 2);
|
146
200
|
rb_define_singleton_method(mLGPIO, "group_write", group_write, 4);
|
201
|
+
|
202
|
+
// Alerts / Reports
|
203
|
+
rb_define_singleton_method(mLGPIO, "gpio_claim_alert", gpio_claim_alert, 4);
|
204
|
+
rb_define_singleton_method(mLGPIO, "gpio_start_reporting", gpio_start_reporting, 0);
|
205
|
+
rb_define_singleton_method(mLGPIO, "gpio_get_report", gpio_get_report, 0);
|
147
206
|
|
148
207
|
// PWM / Servo / Wave
|
149
208
|
rb_define_const(mLGPIO, "TX_PWM", INT2NUM(LG_TX_PWM));
|
data/lib/lgpio/version.rb
CHANGED
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.2
|
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-07-31 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
|
@@ -28,6 +28,8 @@ files:
|
|
28
28
|
- examples/group_out.rb
|
29
29
|
- examples/momentary.rb
|
30
30
|
- examples/pwm.rb
|
31
|
+
- examples/reports.rb
|
32
|
+
- examples/rotary_encoder.rb
|
31
33
|
- examples/wave.rb
|
32
34
|
- ext/lgpio/extconf.rb
|
33
35
|
- ext/lgpio/lgpio.c
|
@@ -54,7 +56,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
54
56
|
- !ruby/object:Gem::Version
|
55
57
|
version: '0'
|
56
58
|
requirements: []
|
57
|
-
rubygems_version: 3.5.
|
59
|
+
rubygems_version: 3.5.16
|
58
60
|
signing_key:
|
59
61
|
specification_version: 4
|
60
62
|
summary: lgpio (lg) bindings for Ruby
|