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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d173e84c707ec6e3d84715dbc7c56287a22d735fbbf118adc4d3b602513b852e
4
- data.tar.gz: cb8d9acbdc1ed6da8fe9f037f8b837ee989b50d48b173980165b34e5c19d9b92
3
+ metadata.gz: 4bb351b8041dc3f5e78ed92128c3c971cf3f9e35d247a71e8d4ce56acec87f32
4
+ data.tar.gz: a4df4836decc51de97ad16093bbd19e649cd02b675d6511c601feddde0cded66
5
5
  SHA512:
6
- metadata.gz: 4959700837149d70e16f550cbd02e13d03b4507ec1b50910c45bf7809e2c711547939ad50d2ba559c0b167befb6c670202e5de371bbe40bf764032d580e94830
7
- data.tar.gz: 360a46aa061edb191ce80f67be784ac4edae21d7126cb4e05c3ce3812d416d2daa6f804ecfa532c790637d51f63010e01a07277971897fa26d7442f1c581a251
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
- - [ ] GPIO Callbacks
11
+ - [x] GPIO Alerts / Callbacks (read from a queue)
12
12
  - [x] PWM (software-timed)
13
13
  - [x] Wave (software-timed)
14
14
  - [ ] I2C
@@ -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
@@ -1,3 +1,3 @@
1
1
  module LGPIO
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
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.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-05-03 00:00:00.000000000 Z
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.9
59
+ rubygems_version: 3.5.16
58
60
  signing_key:
59
61
  specification_version: 4
60
62
  summary: lgpio (lg) bindings for Ruby