lgpio 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
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