rpi_gpio 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,40 +0,0 @@
1
- /*
2
- Original code by Ben Croston modified for Ruby by Nick Lowery
3
- (github.com/clockvapor)
4
- Copyright (c) 2014-2016 Nick Lowery
5
-
6
- Copyright (c) 2013-2015 Ben Croston
7
-
8
- Permission is hereby granted, free of charge, to any person obtaining a copy of
9
- this software and associated documentation files (the "Software"), to deal in
10
- the Software without restriction, including without limitation the rights to
11
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12
- of the Software, and to permit persons to whom the Software is furnished to do
13
- so, subject to the following conditions:
14
-
15
- The above copyright notice and this permission notice shall be included in all
16
- copies or substantial portions of the Software.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- SOFTWARE.
25
- */
26
-
27
- #define NO_EDGE 0
28
- #define RISING_EDGE 1
29
- #define FALLING_EDGE 2
30
- #define BOTH_EDGE 3
31
-
32
- int add_edge_detect(unsigned int gpio, unsigned int edge, int bouncetime);
33
- void remove_edge_detect(unsigned int gpio);
34
- int add_edge_callback(unsigned int gpio, void (*func)(unsigned int gpio));
35
- int event_detected(unsigned int gpio);
36
- int gpio_event_added(unsigned int gpio);
37
- int event_initialise(void);
38
- void event_cleanup(unsigned int gpio);
39
- void event_cleanup_all(void);
40
- int blocking_wait_for_edge(unsigned int gpio, unsigned int edge, int bouncetime, int timeout);
@@ -1,419 +0,0 @@
1
- /*
2
- Original code by Ben Croston modified for Ruby by Nick Lowery
3
- (github.com/clockvapor)
4
- Copyright (c) 2014-2016 Nick Lowery
5
-
6
- Copyright (c) 2013-2016 Ben Croston
7
-
8
- Permission is hereby granted, free of charge, to any person obtaining a copy of
9
- this software and associated documentation files (the "Software"), to deal in
10
- the Software without restriction, including without limitation the rights to
11
- use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12
- of the Software, and to permit persons to whom the Software is furnished to do
13
- so, subject to the following conditions:
14
-
15
- The above copyright notice and this permission notice shall be included in all
16
- copies or substantial portions of the Software.
17
-
18
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
- SOFTWARE.
25
- */
26
-
27
- #include "rb_gpio.h"
28
-
29
- extern VALUE m_GPIO;
30
- int gpio_warnings = 1;
31
-
32
- void define_gpio_module_stuff(void)
33
- {
34
- int i;
35
-
36
- rb_define_module_function(m_GPIO, "setup", GPIO_setup, 2);
37
- rb_define_module_function(m_GPIO, "clean_up", GPIO_clean_up, -1);
38
- rb_define_module_function(m_GPIO, "reset", GPIO_reset, 0);
39
- rb_define_module_function(m_GPIO, "set_numbering", GPIO_set_numbering, 1);
40
- rb_define_module_function(m_GPIO, "set_high", GPIO_set_high, 1);
41
- rb_define_module_function(m_GPIO, "set_low", GPIO_set_low, 1);
42
- rb_define_module_function(m_GPIO, "high?", GPIO_test_high, 1);
43
- rb_define_module_function(m_GPIO, "low?", GPIO_test_low, 1);
44
- rb_define_module_function(m_GPIO, "set_warnings", GPIO_set_warnings, 1);
45
-
46
- for (i=0; i<54; i++) {
47
- gpio_direction[i] = -1;
48
- }
49
-
50
- // detect board revision and set up accordingly
51
- if (get_rpi_info(&rpiinfo)) {
52
- rb_raise(rb_eRuntimeError,
53
- "this gem can only be run on a Raspberry Pi");
54
- setup_error = 1;
55
- return;
56
- } else if (rpiinfo.p1_revision == 1) {
57
- pin_to_gpio = &pin_to_gpio_rev1;
58
- } else if (rpiinfo.p1_revision == 2) {
59
- pin_to_gpio = &pin_to_gpio_rev2;
60
- } else { // assume model B+ or A+
61
- pin_to_gpio = &pin_to_gpio_rev3;
62
- }
63
- }
64
-
65
- int mmap_gpio_mem(void)
66
- {
67
- int result;
68
-
69
- if (module_setup) {
70
- return 0;
71
- }
72
-
73
- result = setup();
74
- if (result == SETUP_DEVMEM_FAIL) {
75
- rb_raise(rb_eRuntimeError, "no access to /dev/mem; try running as "
76
- "root");
77
- return 1;
78
- } else if (result == SETUP_MALLOC_FAIL) {
79
- rb_raise(rb_eNoMemError, "out of memory");
80
- return 2;
81
- } else if (result == SETUP_MMAP_FAIL) {
82
- rb_raise(rb_eRuntimeError, "mmap of GPIO registers failed");
83
- return 3;
84
- } else if (result == SETUP_CPUINFO_FAIL) {
85
- rb_raise(rb_eRuntimeError, "unable to open /proc/cpuinfo");
86
- return 4;
87
- } else if (result == SETUP_NOT_RPI_FAIL) {
88
- rb_raise(rb_eRuntimeError, "not running on a RPi");
89
- return 5;
90
- } else { // result == SETUP_OK
91
- module_setup = 1;
92
- return 0;
93
- }
94
- }
95
-
96
- int is_gpio_input(unsigned int gpio)
97
- {
98
- if (gpio_direction[gpio] != INPUT) {
99
- if (gpio_direction[gpio] != OUTPUT) {
100
- rb_raise(rb_eRuntimeError,
101
- "you must setup the GPIO channel first with "
102
- "RPi::GPIO.setup CHANNEL, :as => :input or "
103
- "RPi::GPIO.setup CHANNEL, :as => :output");
104
- return 0;
105
- }
106
-
107
- rb_raise(rb_eRuntimeError, "GPIO channel not setup as input");
108
- return 0;
109
- }
110
-
111
- return 1;
112
- }
113
-
114
- int is_gpio_output(unsigned int gpio)
115
- {
116
- if (gpio_direction[gpio] != OUTPUT) {
117
- if (gpio_direction[gpio] != INPUT) {
118
- rb_raise(rb_eRuntimeError,
119
- "you must setup the GPIO channel first with "
120
- "RPi::GPIO.setup CHANNEL, :as => :input or "
121
- "RPi::GPIO.setup CHANNEL, :as => :output");
122
- return 0;
123
- }
124
-
125
- rb_raise(rb_eRuntimeError, "GPIO channel not setup as output");
126
- return 0;
127
- }
128
-
129
- return 1;
130
- }
131
-
132
- int is_rpi(void)
133
- {
134
- if (setup_error) {
135
- rb_raise(rb_eRuntimeError,
136
- "this gem can only be run on a Raspberry Pi");
137
- return 0;
138
- }
139
-
140
- return 1;
141
- }
142
-
143
- // RPi::GPIO.clean_up(channel=nil)
144
- // clean up everything by default; otherwise, clean up given channel
145
- VALUE GPIO_clean_up(int argc, VALUE *argv, VALUE self)
146
- {
147
- int i;
148
- int found = 0;
149
- int channel = -666; // lol, quite a flag
150
- unsigned int gpio;
151
-
152
- if (argc == 1) {
153
- channel = NUM2INT(argv[0]);
154
- } else if (argc > 1) {
155
- rb_raise(rb_eArgError, "wrong number of arguments; 0 for all pins, "
156
- "1 for a specific pin");
157
- return Qnil;
158
- }
159
-
160
- if (channel != -666 && get_gpio_number(channel, &gpio)) {
161
- return Qnil;
162
- }
163
-
164
- if (module_setup && !setup_error) {
165
- if (channel == -666) {
166
- // clean up any /sys/class exports
167
- event_cleanup_all();
168
-
169
- // set everything back to input
170
- for (i=0; i<54; i++) {
171
- if (gpio_direction[i] != -1) {
172
- setup_gpio(i, INPUT, PUD_OFF);
173
- gpio_direction[i] = -1;
174
- found = 1;
175
- }
176
- }
177
- } else {
178
- // clean up any /sys/class exports
179
- event_cleanup(gpio);
180
-
181
- // set everything back to input
182
- if (gpio_direction[gpio] != -1) {
183
- setup_gpio(gpio, INPUT, PUD_OFF);
184
- gpio_direction[gpio] = -1;
185
- found = 1;
186
- }
187
- }
188
- }
189
-
190
- // check if any channels set up - if not warn about misuse of GPIO.clean_up()
191
- if (!found && gpio_warnings) {
192
- rb_warn("no channels have been set up yet; nothing to clean up");
193
- }
194
-
195
- return Qnil;
196
- }
197
-
198
- // RPi::GPIO.reset
199
- //
200
- // cleans up all pins, unsets numbering mode, enables warnings.
201
- VALUE GPIO_reset(VALUE self)
202
- {
203
- GPIO_clean_up(0, NULL, self);
204
- gpio_mode = MODE_UNKNOWN;
205
- GPIO_set_warnings(self, Qtrue);
206
- return Qnil;
207
- }
208
-
209
- // RPi::GPIO.setup(channel, hash(:as => {:input, :output}, :pull => {:off,
210
- // :down, :up}(default :off)))
211
- //
212
- // sets up a channel as either input or output, with an option pull-down or
213
- // pull-up resistor.
214
- VALUE GPIO_setup(VALUE self, VALUE channel, VALUE hash)
215
- {
216
- unsigned int gpio;
217
- int chan = -1;
218
- const char *direction_str = NULL;
219
- int direction;
220
- VALUE pud_val = Qnil;
221
- const char *pud_str = NULL;
222
- int pud = PUD_OFF;
223
- int func;
224
-
225
- // func to set up channel stored in channel variable
226
- int setup_one(void) {
227
- if (get_gpio_number(chan, &gpio)) {
228
- return 0;
229
- }
230
-
231
- // warn if the channel is already in use (not from this program).
232
- func = gpio_function(gpio);
233
- if (gpio_warnings &&
234
- ((func != 0 && func != 1) ||
235
- (gpio_direction[gpio] == -1 && func == 1))) {
236
- rb_warn("this channel is already in use... continuing anyway. "
237
- "use RPi::GPIO.set_warnings(false) to disable warnings");
238
- }
239
-
240
- if (gpio_warnings) {
241
- if (rpiinfo.p1_revision == 0) { // compute module - do nothing
242
- } else if ((rpiinfo.p1_revision == 1 &&
243
- (gpio == 0 || gpio == 1)) ||
244
- (gpio == 2 || gpio == 3)) {
245
- if (pud == PUD_UP || pud == PUD_DOWN) {
246
- rb_warn("a physical pull up resistor is fitted on "
247
- "this channel");
248
- }
249
- }
250
- }
251
-
252
- setup_gpio(gpio, direction, pud);
253
- gpio_direction[gpio] = direction;
254
- return 1;
255
- }
256
-
257
- // parse arguments
258
-
259
- // channel
260
- chan = NUM2INT(channel);
261
-
262
- // pin direction
263
- direction_str = rb_id2name(rb_to_id(rb_hash_aref(hash,
264
- ID2SYM(rb_intern("as")))));
265
- if (strcmp("input", direction_str) == 0) {
266
- direction = INPUT;
267
- } else if (strcmp("output", direction_str) == 0) {
268
- direction = OUTPUT;
269
- } else {
270
- rb_raise(rb_eArgError,
271
- "invalid pin direction; must be :input or :output");
272
- }
273
-
274
- // pull up, down, or off
275
- pud_val = rb_hash_aref(hash, ID2SYM(rb_intern("pull")));
276
- if (pud_val != Qnil) {
277
- if (direction == OUTPUT) {
278
- rb_raise(rb_eArgError, "output pin cannot use pull argument");
279
- return Qnil;
280
- }
281
-
282
- pud_str = rb_id2name(rb_to_id(pud_val));
283
- if (strcmp("down", pud_str) == 0) {
284
- pud = PUD_DOWN;
285
- } else if (strcmp("up", pud_str) == 0) {
286
- pud = PUD_UP;
287
- } else if (strcmp("off", pud_str) == 0) {
288
- pud = PUD_OFF;
289
- } else {
290
- rb_raise(rb_eArgError,
291
- "invalid pin pull direction; must be :up, :down, or :off");
292
- return Qnil;
293
- }
294
- } else {
295
- pud = PUD_OFF;
296
- }
297
-
298
- if (!is_rpi() || mmap_gpio_mem()) {
299
- return Qnil;
300
- }
301
-
302
- if (direction != INPUT && direction != OUTPUT) {
303
- rb_raise(rb_eArgError, "invalid direction");
304
- return Qnil;
305
- }
306
-
307
- if (direction == OUTPUT) {
308
- pud = PUD_OFF;
309
- }
310
-
311
- if (!setup_one()) {
312
- return Qnil;
313
- }
314
-
315
- return self;
316
- }
317
-
318
- // RPi::GPIO.set_numbering(mode)
319
- VALUE GPIO_set_numbering(VALUE self, VALUE mode)
320
- {
321
- int new_mode;
322
- const char *mode_str = NULL;
323
-
324
- if (TYPE(mode) == T_SYMBOL) {
325
- mode_str = rb_id2name(rb_to_id(mode));
326
- } else {
327
- mode_str = RSTRING_PTR(mode);
328
- }
329
-
330
- if (strcmp(mode_str, "board") == 0) {
331
- new_mode = BOARD;
332
- } else if (strcmp(mode_str, "bcm") == 0) {
333
- new_mode = BCM;
334
- } else {
335
- rb_raise(rb_eArgError,
336
- "invalid numbering mode; must be :board or :bcm");
337
- }
338
-
339
- if (!is_rpi()) {
340
- return Qnil;
341
- }
342
-
343
- if (new_mode != BOARD && new_mode != BCM) {
344
- rb_raise(rb_eArgError, "invalid mode");
345
- return Qnil;
346
- }
347
-
348
- if (rpiinfo.p1_revision == 0 && new_mode == BOARD) {
349
- rb_raise(rb_eRuntimeError, ":board numbering system not applicable on "
350
- "compute module");
351
- return Qnil;
352
- }
353
-
354
- gpio_mode = new_mode;
355
- return self;
356
- }
357
-
358
- // RPi::GPIO.set_high(channel)
359
- VALUE GPIO_set_high(VALUE self, VALUE channel)
360
- {
361
- unsigned int gpio;
362
- int chan = NUM2INT(channel);
363
-
364
- if (get_gpio_number(chan, &gpio) ||
365
- !is_gpio_output(gpio) ||
366
- check_gpio_priv()) {
367
- return Qnil;
368
- }
369
-
370
- output_gpio(gpio, 1);
371
- return self;
372
- }
373
-
374
- // RPi::GPIO.set_low(channel)
375
- VALUE GPIO_set_low(VALUE self, VALUE channel)
376
- {
377
- unsigned int gpio;
378
- int chan = NUM2INT(channel);
379
-
380
- if (get_gpio_number(chan, &gpio) ||
381
- !is_gpio_output(gpio) ||
382
- check_gpio_priv()) {
383
- return Qnil;
384
- }
385
-
386
- output_gpio(gpio, 0);
387
- return self;
388
- }
389
-
390
- // RPi::GPIO.high?(channel)
391
- VALUE GPIO_test_high(VALUE self, VALUE channel)
392
- {
393
- unsigned int gpio;
394
-
395
- if (get_gpio_number(NUM2INT(channel), &gpio) ||
396
- !is_gpio_input(gpio) ||
397
- check_gpio_priv()) {
398
- return Qnil;
399
- }
400
-
401
- return input_gpio(gpio) ? Qtrue : Qfalse;
402
- }
403
-
404
- // RPi::GPIO.low?(channel)
405
- VALUE GPIO_test_low(VALUE self, VALUE channel)
406
- {
407
- return GPIO_test_high(self, channel) ? Qfalse : Qtrue;
408
- }
409
-
410
- // RPi::GPIO.set_warnings(state)
411
- VALUE GPIO_set_warnings(VALUE self, VALUE setting)
412
- {
413
- if (!is_rpi()) {
414
- return Qnil;
415
- }
416
-
417
- gpio_warnings = RTEST(setting);
418
- return self;
419
- }