gpiod 0.1.0
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +9 -0
- data/Rakefile +5 -0
- data/examples/bench_out.rb +21 -0
- data/ext/gpiod/extconf.rb +9 -0
- data/ext/gpiod/gpiod.c +178 -0
- data/gpiod.gemspec +18 -0
- data/lib/gpiod/version.rb +3 -0
- data/lib/gpiod.rb +2 -0
- metadata +53 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: aa08910a821f653b7a8e24bb23d4179b1bc830ad476b07483c7b07ad8932348e
|
4
|
+
data.tar.gz: 335c870b62e4a83ae059d40ea161ab213d9af5ebff25803005c29b3259e59bd9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 27996555e451e2cd7c4bb1d79f5cd5a69979d2db1ef66a6bd1613d8862075d22d71da8c0969ace049db5ff30b42f4399ba18a911396ad31e9d72fcee32c9615c
|
7
|
+
data.tar.gz: d54d80244f65bf29ae4fa928c0d065f3dfc19f87f7095a4eb6c1afb0f1ea27e99627c31ee84a5cdaf455d7f797bbd8124fbbab85aac2f7b6c158a4dc04710d17
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 denko-rb
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# gpiod
|
2
|
+
|
3
|
+
# Experimental (DO NOT USE!)
|
4
|
+
|
5
|
+
If you need to use Linux GPIO in Ruby, please see [denko-piboard](https://github.com/denko-rb/denko-piboard) or [lgpio](https://github.com/denko-rb/lgpio) instead.
|
6
|
+
|
7
|
+
This gem only contains some (probably bad) code, extracted from an old version of `denko-piboard`. I started building that on top of `libgpiod` directly, but eventually settled on [lgpio](https://github.com/joan2937/lg) which has more features and was simpler to implement.
|
8
|
+
|
9
|
+
At some point, I will probably finish the `libgpiod` implementation, and substitute it where applicable in `denko-piboard`, in place of `lgpio`. It performs ~15-20% better, but `lgpio` + YJIT is already pretty fast, so this isn't a priority.
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'gpiod'
|
2
|
+
|
3
|
+
GPIO_CHIP = 0
|
4
|
+
PIN = 17
|
5
|
+
COUNT = 1000000
|
6
|
+
|
7
|
+
# Always opens gpiochip0 for now.
|
8
|
+
GPIOD.open_chip
|
9
|
+
GPIOD.open_line_output(PIN)
|
10
|
+
|
11
|
+
t1 = Time.now
|
12
|
+
COUNT.times do
|
13
|
+
GPIOD.set_value(PIN, 1)
|
14
|
+
GPIOD.set_value(PIN, 0)
|
15
|
+
end
|
16
|
+
t2 = Time.now
|
17
|
+
|
18
|
+
puts "Toggles per second: #{COUNT.to_f / (t2 - t1).to_f}"
|
19
|
+
|
20
|
+
GPIOD.close_line(PIN)
|
21
|
+
GPIOD.close_chip
|
data/ext/gpiod/gpiod.c
ADDED
@@ -0,0 +1,178 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <gpiod.h>
|
3
|
+
|
4
|
+
#define GPIO_CHIP_NAME "gpiochip0"
|
5
|
+
|
6
|
+
static struct gpiod_chip *chip;
|
7
|
+
|
8
|
+
// Save mapping of lowest 32 GPIOs to gpiod_line structs.
|
9
|
+
static struct gpiod_line *lines[32] = { NULL };
|
10
|
+
|
11
|
+
// Input and output values.
|
12
|
+
static int gpio_number;
|
13
|
+
static int gpio_value;
|
14
|
+
static int return_value;
|
15
|
+
|
16
|
+
static VALUE open_chip(VALUE self) {
|
17
|
+
chip = gpiod_chip_open_by_name(GPIO_CHIP_NAME);
|
18
|
+
if (!chip) {
|
19
|
+
rb_raise(rb_eRuntimeError, "libgpiod error: Could not open GPIO chip");
|
20
|
+
return Qnil;
|
21
|
+
}
|
22
|
+
return Qnil;
|
23
|
+
}
|
24
|
+
|
25
|
+
static VALUE close_chip(VALUE self) {
|
26
|
+
gpiod_chip_close(chip);
|
27
|
+
return Qnil;
|
28
|
+
}
|
29
|
+
|
30
|
+
static void validate_gpio_number(int gpio_number) {
|
31
|
+
if ((gpio_number < 0) || (gpio_number > 31)) {
|
32
|
+
VALUE error_message = rb_sprintf("libgpiod error: GPIO line (%d) out of range. Valid range is 0..31", gpio_number);
|
33
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
static void validate_gpio_value(int value) {
|
38
|
+
if (!((value == 0) || (value == 1))) {
|
39
|
+
VALUE error_message = rb_sprintf("libgpiod error: GPIO value (%d) out of range. Valid values are 0 or 1", value);
|
40
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
static VALUE open_line_output(VALUE self, VALUE gpio) {
|
45
|
+
gpio_number = NUM2INT(gpio);
|
46
|
+
validate_gpio_number(gpio_number);
|
47
|
+
|
48
|
+
lines[gpio_number] = gpiod_chip_get_line(chip, gpio_number);
|
49
|
+
if (!lines[gpio_number]) {
|
50
|
+
gpiod_chip_close(chip);
|
51
|
+
VALUE error_message = rb_sprintf("libgpiod error: Could not get GPIO line %d", gpio_number);
|
52
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
53
|
+
return Qnil;
|
54
|
+
}
|
55
|
+
|
56
|
+
return_value = gpiod_line_request_output(lines[gpio_number], "GPIOD_RB", 0);
|
57
|
+
if (return_value < 0) {
|
58
|
+
gpiod_chip_close(chip);
|
59
|
+
VALUE error_message = rb_sprintf("libgpiod error: Could not request output for GPIO line %d", gpio_number);
|
60
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
61
|
+
return Qnil;
|
62
|
+
}
|
63
|
+
|
64
|
+
return Qnil;
|
65
|
+
}
|
66
|
+
|
67
|
+
static VALUE set_value(VALUE self, VALUE gpio, VALUE value) {
|
68
|
+
gpio_number = NUM2INT(gpio);
|
69
|
+
validate_gpio_number(gpio_number);
|
70
|
+
gpio_value = NUM2INT(value);
|
71
|
+
validate_gpio_value(gpio_value);
|
72
|
+
|
73
|
+
return_value = gpiod_line_set_value(lines[gpio_number], gpio_value);
|
74
|
+
|
75
|
+
if (return_value < 0) {
|
76
|
+
gpiod_chip_close(chip);
|
77
|
+
VALUE error_message = rb_sprintf("libgpiod error: Could not set value %d on GPIO line %d", gpio_value, gpio_number);
|
78
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
79
|
+
return Qnil;
|
80
|
+
}
|
81
|
+
|
82
|
+
return value;
|
83
|
+
}
|
84
|
+
|
85
|
+
static VALUE open_line_input(VALUE self, VALUE gpio) {
|
86
|
+
gpio_number = NUM2INT(gpio);
|
87
|
+
validate_gpio_number(gpio_number);
|
88
|
+
|
89
|
+
lines[gpio_number] = gpiod_chip_get_line(chip, gpio_number);
|
90
|
+
if (!lines[gpio_number]) {
|
91
|
+
gpiod_chip_close(chip);
|
92
|
+
VALUE error_message = rb_sprintf("libgpiod error: Could not get GPIO line %d", gpio_number);
|
93
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
94
|
+
return Qnil;
|
95
|
+
}
|
96
|
+
|
97
|
+
return_value = gpiod_line_request_input(lines[gpio_number], "GPIOD_RB");
|
98
|
+
if (return_value < 0) {
|
99
|
+
gpiod_chip_close(chip);
|
100
|
+
VALUE error_message = rb_sprintf("libgpiod error: Could not request input for GPIO line %d", gpio_number);
|
101
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
102
|
+
return Qnil;
|
103
|
+
}
|
104
|
+
|
105
|
+
return Qnil;
|
106
|
+
}
|
107
|
+
|
108
|
+
static VALUE get_value(VALUE self, VALUE gpio) {
|
109
|
+
gpio_number = NUM2INT(gpio);
|
110
|
+
validate_gpio_number(gpio_number);
|
111
|
+
|
112
|
+
return_value = gpiod_line_get_value(lines[gpio_number]);
|
113
|
+
|
114
|
+
if (return_value < 0) {
|
115
|
+
gpiod_chip_close(chip);
|
116
|
+
VALUE error_message = rb_sprintf("libgpiod error: Could not get value from GPIO line %d", gpio_number);
|
117
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
118
|
+
return Qnil;
|
119
|
+
}
|
120
|
+
|
121
|
+
return INT2NUM(return_value);
|
122
|
+
}
|
123
|
+
|
124
|
+
static VALUE close_line(VALUE self, VALUE gpio) {
|
125
|
+
gpio_number = NUM2INT(gpio);
|
126
|
+
validate_gpio_number(gpio_number);
|
127
|
+
|
128
|
+
// Only try to close the line if it was opened before.
|
129
|
+
if (lines[gpio_number] == NULL) return Qnil;
|
130
|
+
|
131
|
+
gpiod_line_release(lines[gpio_number]);
|
132
|
+
lines[gpio_number] = NULL;
|
133
|
+
return Qnil;
|
134
|
+
}
|
135
|
+
|
136
|
+
static VALUE set_value_raw(VALUE self, VALUE gpio, VALUE value) {
|
137
|
+
gpio_number = NUM2INT(gpio);
|
138
|
+
gpio_value = NUM2INT(value);
|
139
|
+
|
140
|
+
return_value = gpiod_line_set_value(lines[gpio_number], gpio_value);
|
141
|
+
|
142
|
+
if (return_value < 0) {
|
143
|
+
gpiod_chip_close(chip);
|
144
|
+
VALUE error_message = rb_sprintf("libgpiod error: Could not set value %d on GPIO line %d", gpio_value, gpio_number);
|
145
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
146
|
+
return Qnil;
|
147
|
+
}
|
148
|
+
return value;
|
149
|
+
}
|
150
|
+
|
151
|
+
static VALUE get_value_raw(VALUE self, VALUE gpio) {
|
152
|
+
gpio_number = NUM2INT(gpio);
|
153
|
+
|
154
|
+
return_value = gpiod_line_get_value(lines[gpio_number]);
|
155
|
+
|
156
|
+
if (return_value < 0) {
|
157
|
+
gpiod_chip_close(chip);
|
158
|
+
VALUE error_message = rb_sprintf("libgpiod error: Could not get value from GPIO line %d", gpio_number);
|
159
|
+
rb_raise(rb_eRuntimeError, "%s", StringValueCStr(error_message));
|
160
|
+
return Qnil;
|
161
|
+
}
|
162
|
+
return INT2NUM(return_value);
|
163
|
+
}
|
164
|
+
|
165
|
+
void Init_gpiod(void) {
|
166
|
+
VALUE mGPIOD = rb_define_module("GPIOD");
|
167
|
+
rb_define_singleton_method(mGPIOD, "open_chip", open_chip, 0);
|
168
|
+
rb_define_singleton_method(mGPIOD, "close_chip", close_chip, 0);
|
169
|
+
rb_define_singleton_method(mGPIOD, "open_line_output", open_line_output, 1);
|
170
|
+
rb_define_singleton_method(mGPIOD, "set_value", set_value, 2);
|
171
|
+
rb_define_singleton_method(mGPIOD, "open_line_input", open_line_input, 1);
|
172
|
+
rb_define_singleton_method(mGPIOD, "get_value", get_value, 1);
|
173
|
+
rb_define_singleton_method(mGPIOD, "close_line", close_line, 1);
|
174
|
+
|
175
|
+
// These do no validation.
|
176
|
+
rb_define_singleton_method(mGPIOD, "set_value_raw", set_value_raw, 2);
|
177
|
+
rb_define_singleton_method(mGPIOD, "get_value_raw", get_value_raw, 1);
|
178
|
+
}
|
data/gpiod.gemspec
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative 'lib/gpiod/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = 'gpiod'
|
5
|
+
s.version = GPIOD::VERSION
|
6
|
+
s.licenses = ['MIT']
|
7
|
+
s.summary = "Use Linux SBC GPIO in Ruby"
|
8
|
+
s.description = "This gem provides Ruby bindings to the Linux gpiod C library"
|
9
|
+
|
10
|
+
s.authors = ["vickash"]
|
11
|
+
s.email = 'mail@vickash.com'
|
12
|
+
s.files = Dir['**/*'].reject { |f| f.match /.gem\z/}
|
13
|
+
s.homepage = "https://github.com/denko-rb/gpiod"
|
14
|
+
s.metadata = { "source_code_uri" => "https://github.com/denko-rb/gpiod" }
|
15
|
+
|
16
|
+
# libgpio C extension
|
17
|
+
s.extensions = %w[ext/gpiod/extconf.rb]
|
18
|
+
end
|
data/lib/gpiod.rb
ADDED
metadata
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gpiod
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- vickash
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-10-02 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: This gem provides Ruby bindings to the Linux gpiod C library
|
14
|
+
email: mail@vickash.com
|
15
|
+
executables: []
|
16
|
+
extensions:
|
17
|
+
- ext/gpiod/extconf.rb
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- LICENSE
|
21
|
+
- README.md
|
22
|
+
- Rakefile
|
23
|
+
- examples/bench_out.rb
|
24
|
+
- ext/gpiod/extconf.rb
|
25
|
+
- ext/gpiod/gpiod.c
|
26
|
+
- gpiod.gemspec
|
27
|
+
- lib/gpiod.rb
|
28
|
+
- lib/gpiod/version.rb
|
29
|
+
homepage: https://github.com/denko-rb/gpiod
|
30
|
+
licenses:
|
31
|
+
- MIT
|
32
|
+
metadata:
|
33
|
+
source_code_uri: https://github.com/denko-rb/gpiod
|
34
|
+
post_install_message:
|
35
|
+
rdoc_options: []
|
36
|
+
require_paths:
|
37
|
+
- lib
|
38
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
requirements: []
|
49
|
+
rubygems_version: 3.5.16
|
50
|
+
signing_key:
|
51
|
+
specification_version: 4
|
52
|
+
summary: Use Linux SBC GPIO in Ruby
|
53
|
+
test_files: []
|