rpi_gpio 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,389 +1,399 @@
1
- /*
2
- Original code by Ben Croston modified for Ruby by Nick Lowery
3
- (github.com/clockvapor)
4
- Copyright (c) 2014-2015 Nick Lowery
5
-
6
- Copyright (c) 2013-2014 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, "set_numbering", GPIO_set_numbering, 1);
39
- rb_define_module_function(m_GPIO, "set_high", GPIO_set_high, 1);
40
- rb_define_module_function(m_GPIO, "set_low", GPIO_set_low, 1);
41
- rb_define_module_function(m_GPIO, "high?", GPIO_test_high, 1);
42
- rb_define_module_function(m_GPIO, "low?", GPIO_test_low, 1);
43
- rb_define_module_function(m_GPIO, "set_warnings", GPIO_set_warnings, 1);
44
-
45
- for (i=0; i<54; i++)
46
- gpio_direction[i] = -1;
47
-
48
- // detect board revision and set up accordingly
49
- revision = get_rpi_revision();
50
- if (revision == -1)
51
- {
52
- rb_raise(rb_eRuntimeError, "this gem can only be run on a Raspberry Pi");
53
- setup_error = 1;
54
- return;
55
- }
56
- else if (revision == 1)
57
- pin_to_gpio = &pin_to_gpio_rev1;
58
- else if (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
- rb_define_const(m_GPIO, "RPI_REVISION", INT2NUM(revision));
64
- }
65
-
66
- int mmap_gpio_mem(void)
67
- {
68
- int result;
69
-
70
- if (module_setup)
71
- return 0;
72
-
73
- result = setup();
74
- if (result == SETUP_DEVMEM_FAIL)
75
- {
76
- rb_raise(rb_eRuntimeError, "no access to /dev/mem; try running as "
77
- "root");
78
- return 1;
79
- }
80
- else if (result == SETUP_MALLOC_FAIL)
81
- {
82
- rb_raise(rb_eNoMemError, "out of memory");
83
- return 2;
84
- }
85
- else if (result == SETUP_MMAP_FAIL)
86
- {
87
- rb_raise(rb_eRuntimeError, "mmap of GPIO registers failed");
88
- return 3;
89
- }
90
- else // result == SETUP_OK
91
- {
92
- module_setup = 1;
93
- return 0;
94
- }
95
- }
96
-
97
- int is_gpio_input(unsigned int gpio)
98
- {
99
- if (gpio_direction[gpio] != INPUT)
100
- {
101
- if (gpio_direction[gpio] != OUTPUT)
102
- {
103
- rb_raise(rb_eRuntimeError, "you must setup() the GPIO channel first");
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
- {
118
- if (gpio_direction[gpio] != INPUT)
119
- {
120
- rb_raise(rb_eRuntimeError, "you must setup() the GPIO channel first");
121
- return 0;
122
- }
123
-
124
- rb_raise(rb_eRuntimeError, "GPIO channel not setup as output");
125
- return 0;
126
- }
127
-
128
- return 1;
129
- }
130
-
131
- int is_rpi(void)
132
- {
133
- if (setup_error)
134
- {
135
- rb_raise(rb_eRuntimeError, "this gem can only be run on a Raspberry Pi");
136
- return 0;
137
- }
138
-
139
- return 1;
140
- }
141
-
142
- // RPi::GPIO.clean_up(channel=nil)
143
- // clean up everything by default; otherwise, clean up given channel
144
- VALUE GPIO_clean_up(int argc, VALUE *argv, VALUE self)
145
- {
146
- int i;
147
- int found = 0;
148
- int channel = -666; // lol, quite a flag
149
- unsigned int gpio;
150
-
151
- if (argc == 1)
152
- channel = NUM2INT(argv[0]);
153
- else if (argc > 1)
154
- {
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
- if (module_setup && !setup_error)
164
- {
165
- if (channel == -666)
166
- {
167
- // clean up any /sys/class exports
168
- event_cleanup_all();
169
-
170
- // set everything back to input
171
- for (i=0; i<54; i++) {
172
- if (gpio_direction[i] != -1)
173
- {
174
- setup_gpio(i, INPUT, PUD_OFF);
175
- gpio_direction[i] = -1;
176
- found = 1;
177
- }
178
- }
179
- }
180
- else
181
- {
182
- // clean up any /sys/class exports
183
- event_cleanup(gpio);
184
-
185
- // set everything back to input
186
- if (gpio_direction[gpio] != -1)
187
- {
188
- setup_gpio(gpio, INPUT, PUD_OFF);
189
- gpio_direction[gpio] = -1;
190
- found = 1;
191
- }
192
- }
193
- }
194
-
195
- // check if any channels set up - if not warn about misuse of GPIO.clean_up()
196
- if (!found && gpio_warnings)
197
- rb_warn("no channels have been set up yet; nothing to clean up");
198
-
199
- return Qnil;
200
- }
201
-
202
- // RPI::GPIO.setup(channel, hash(:as => {:input, :output}, :pull => {:off,
203
- // :down, :up}(default :off)))
204
- VALUE GPIO_setup(VALUE self, VALUE channel, VALUE hash)
205
- {
206
- unsigned int gpio;
207
- int chan = -1;
208
- const char *direction_str = NULL;
209
- int direction;
210
- VALUE pud_val = Qnil;
211
- const char *pud_str = NULL;
212
- int pud = PUD_OFF;
213
- int func;
214
-
215
- // func to set up channel stored in channel variable
216
- int setup_one(void)
217
- {
218
- if (get_gpio_number(chan, &gpio))
219
- return 0;
220
-
221
- // warn if the channel is already in use (not from this program).
222
- func = gpio_function(gpio);
223
- if (gpio_warnings &&
224
- ((func != 0 && func != 1) ||
225
- (gpio_direction[gpio] == -1 && func == 1)))
226
- {
227
- rb_warn("this channel is already in use... continuing anyway. "
228
- "use RPi::GPIO.set_warnings(false) to disable warnings");
229
- }
230
-
231
- setup_gpio(gpio, direction, pud);
232
- gpio_direction[gpio] = direction;
233
- return 1;
234
- }
235
-
236
- // parse arguments
237
-
238
- // channel
239
- chan = NUM2INT(channel);
240
-
241
- // pin direction
242
- direction_str = rb_id2name(rb_to_id(rb_hash_aref(hash, ID2SYM(rb_intern("as"))
243
- )));
244
- if (strcmp("input", direction_str) == 0)
245
- direction = INPUT;
246
- else if (strcmp("output", direction_str) == 0)
247
- direction = OUTPUT;
248
- else
249
- rb_raise(rb_eArgError, "invalid pin direction; must be :input or :output");
250
-
251
- // pull up, down, or off
252
- pud_val = rb_hash_aref(hash, ID2SYM(rb_intern("pull")));
253
- if (pud_val != Qnil)
254
- {
255
- if (direction == OUTPUT)
256
- {
257
- rb_raise(rb_eArgError, "output pin cannot use pull argument");
258
- return Qnil;
259
- }
260
-
261
- pud_str = rb_id2name(rb_to_id(pud_val));
262
- if (strcmp("down", pud_str) == 0)
263
- pud = PUD_DOWN;
264
- else if (strcmp("up", pud_str) == 0)
265
- pud = PUD_UP;
266
- else if (strcmp("off", pud_str) == 0)
267
- pud = PUD_OFF;
268
- else
269
- {
270
- rb_raise(rb_eArgError, "invalid pin pull direction; must be :up, :down, "
271
- "or :off");
272
- return Qnil;
273
- }
274
- }
275
- else
276
- pud = PUD_OFF;
277
-
278
- if (!is_rpi() || mmap_gpio_mem())
279
- return Qnil;
280
-
281
- if (direction != INPUT && direction != OUTPUT)
282
- {
283
- rb_raise(rb_eArgError, "invalid direction");
284
- return Qnil;
285
- }
286
-
287
- if (direction == OUTPUT)
288
- pud = PUD_OFF;
289
-
290
- if (!setup_one())
291
- return Qnil;
292
-
293
- return self;
294
- }
295
-
296
- // RPi::GPIO.set_numbering(mode)
297
- VALUE GPIO_set_numbering(VALUE self, VALUE mode)
298
- {
299
- const char *mode_str = NULL;
300
-
301
- if (TYPE(mode) == T_SYMBOL)
302
- mode_str = rb_id2name(rb_to_id(mode));
303
- else
304
- mode_str = RSTRING_PTR(mode);
305
-
306
- if (strcmp(mode_str, "board") == 0)
307
- gpio_mode = BOARD;
308
- else if (strcmp(mode_str, "bcm") == 0)
309
- gpio_mode = BCM;
310
- else
311
- rb_raise(rb_eArgError, "invalid numbering mode; must be :board or :bcm");
312
-
313
- if (!is_rpi())
314
- return Qnil;
315
-
316
- if (gpio_mode != BOARD && gpio_mode != BCM)
317
- {
318
- rb_raise(rb_eArgError, "invalid mode");
319
- return Qnil;
320
- }
321
-
322
- if (revision == 0 && gpio_mode == BOARD)
323
- {
324
- rb_raise(rb_eRuntimeError, ":board numbering system not applicable on "
325
- "computer module");
326
- return Qnil;
327
- }
328
-
329
- return self;
330
- }
331
-
332
- // RPi::GPIO.set_high(channel)
333
- VALUE GPIO_set_high(VALUE self, VALUE channel)
334
- {
335
- unsigned int gpio;
336
- int chan = NUM2INT(channel);
337
-
338
- if (get_gpio_number(chan, &gpio) ||
339
- !is_gpio_output(gpio) ||
340
- check_gpio_priv())
341
- return Qnil;
342
-
343
- output_gpio(gpio, 1);
344
- return self;
345
- }
346
-
347
- // RPi::GPIO.set_low(channel)
348
- VALUE GPIO_set_low(VALUE self, VALUE channel)
349
- {
350
- unsigned int gpio;
351
- int chan = NUM2INT(channel);
352
-
353
- if (get_gpio_number(chan, &gpio) ||
354
- !is_gpio_output(gpio) ||
355
- check_gpio_priv())
356
- return Qnil;
357
-
358
- output_gpio(gpio, 0);
359
- return self;
360
- }
361
-
362
- // RPi::GPIO.high?(channel)
363
- VALUE GPIO_test_high(VALUE self, VALUE channel)
364
- {
365
- unsigned int gpio;
366
-
367
- if (get_gpio_number(NUM2INT(channel), &gpio) ||
368
- !is_gpio_input(gpio) ||
369
- check_gpio_priv())
370
- return Qnil;
371
-
372
- return input_gpio(gpio) ? Qtrue : Qfalse;
373
- }
374
-
375
- // RPi::GPIO.low?(channel)
376
- VALUE GPIO_test_low(VALUE self, VALUE channel)
377
- {
378
- return GPIO_test_high(self, channel) ? Qfalse : Qtrue;
379
- }
380
-
381
- // RPi::GPIO.set_warnings(state)
382
- VALUE GPIO_set_warnings(VALUE self, VALUE setting)
383
- {
384
- if (!is_rpi())
385
- return Qnil;
386
-
387
- gpio_warnings = NUM2INT(setting);
388
- return self;
389
- }
1
+ /*
2
+ Original code by Ben Croston modified for Ruby by Nick Lowery
3
+ (github.com/clockvapor)
4
+ Copyright (c) 2014-2015 Nick Lowery
5
+
6
+ Copyright (c) 2013-2014 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 { // result == SETUP_OK
85
+ module_setup = 1;
86
+ return 0;
87
+ }
88
+ }
89
+
90
+ int is_gpio_input(unsigned int gpio)
91
+ {
92
+ if (gpio_direction[gpio] != INPUT) {
93
+ if (gpio_direction[gpio] != OUTPUT) {
94
+ rb_raise(rb_eRuntimeError,
95
+ "you must setup the GPIO channel first with "
96
+ "RPi::GPIO.setup CHANNEL, :as => :input or "
97
+ "RPi::GPIO.setup CHANNEL, :as => :output");
98
+ return 0;
99
+ }
100
+
101
+ rb_raise(rb_eRuntimeError, "GPIO channel not setup as input");
102
+ return 0;
103
+ }
104
+
105
+ return 1;
106
+ }
107
+
108
+ int is_gpio_output(unsigned int gpio)
109
+ {
110
+ if (gpio_direction[gpio] != OUTPUT) {
111
+ if (gpio_direction[gpio] != INPUT) {
112
+ rb_raise(rb_eRuntimeError,
113
+ "you must setup the GPIO channel first with "
114
+ "RPi::GPIO.setup CHANNEL, :as => :input or "
115
+ "RPi::GPIO.setup CHANNEL, :as => :output");
116
+ return 0;
117
+ }
118
+
119
+ rb_raise(rb_eRuntimeError, "GPIO channel not setup as output");
120
+ return 0;
121
+ }
122
+
123
+ return 1;
124
+ }
125
+
126
+ int is_rpi(void)
127
+ {
128
+ if (setup_error) {
129
+ rb_raise(rb_eRuntimeError,
130
+ "this gem can only be run on a Raspberry Pi");
131
+ return 0;
132
+ }
133
+
134
+ return 1;
135
+ }
136
+
137
+ // RPi::GPIO.clean_up(channel=nil)
138
+ // clean up everything by default; otherwise, clean up given channel
139
+ VALUE GPIO_clean_up(int argc, VALUE *argv, VALUE self)
140
+ {
141
+ int i;
142
+ int found = 0;
143
+ int channel = -666; // lol, quite a flag
144
+ unsigned int gpio;
145
+
146
+ if (argc == 1) {
147
+ channel = NUM2INT(argv[0]);
148
+ } else if (argc > 1) {
149
+ rb_raise(rb_eArgError, "wrong number of arguments; 0 for all pins, "
150
+ "1 for a specific pin");
151
+ return Qnil;
152
+ }
153
+
154
+ if (channel != -666 && get_gpio_number(channel, &gpio)) {
155
+ return Qnil;
156
+ }
157
+
158
+ if (module_setup && !setup_error) {
159
+ if (channel == -666) {
160
+ // clean up any /sys/class exports
161
+ event_cleanup_all();
162
+
163
+ // set everything back to input
164
+ for (i=0; i<54; i++) {
165
+ if (gpio_direction[i] != -1) {
166
+ setup_gpio(i, INPUT, PUD_OFF);
167
+ gpio_direction[i] = -1;
168
+ found = 1;
169
+ }
170
+ }
171
+ } else {
172
+ // clean up any /sys/class exports
173
+ event_cleanup(gpio);
174
+
175
+ // set everything back to input
176
+ if (gpio_direction[gpio] != -1) {
177
+ setup_gpio(gpio, INPUT, PUD_OFF);
178
+ gpio_direction[gpio] = -1;
179
+ found = 1;
180
+ }
181
+ }
182
+ }
183
+
184
+ // check if any channels set up - if not warn about misuse of GPIO.clean_up()
185
+ if (!found && gpio_warnings) {
186
+ rb_warn("no channels have been set up yet; nothing to clean up");
187
+ }
188
+
189
+ return Qnil;
190
+ }
191
+
192
+ // RPi::GPIO.reset
193
+ //
194
+ // cleans up all pins, unsets numbering mode, enables warnings.
195
+ VALUE GPIO_reset(VALUE self)
196
+ {
197
+ GPIO_clean_up(0, NULL, self);
198
+ gpio_mode = MODE_UNKNOWN;
199
+ GPIO_set_warnings(self, Qtrue);
200
+ return Qnil;
201
+ }
202
+
203
+ // RPi::GPIO.setup(channel, hash(:as => {:input, :output}, :pull => {:off,
204
+ // :down, :up}(default :off)))
205
+ //
206
+ // sets up a channel as either input or output, with an option pull-down or
207
+ // pull-up resistor.
208
+ VALUE GPIO_setup(VALUE self, VALUE channel, VALUE hash)
209
+ {
210
+ unsigned int gpio;
211
+ int chan = -1;
212
+ const char *direction_str = NULL;
213
+ int direction;
214
+ VALUE pud_val = Qnil;
215
+ const char *pud_str = NULL;
216
+ int pud = PUD_OFF;
217
+ int func;
218
+
219
+ // func to set up channel stored in channel variable
220
+ int setup_one(void) {
221
+ if (get_gpio_number(chan, &gpio)) {
222
+ return 0;
223
+ }
224
+
225
+ // warn if the channel is already in use (not from this program).
226
+ func = gpio_function(gpio);
227
+ if (gpio_warnings &&
228
+ ((func != 0 && func != 1) ||
229
+ (gpio_direction[gpio] == -1 && func == 1))) {
230
+ rb_warn("this channel is already in use... continuing anyway. "
231
+ "use RPi::GPIO.set_warnings(false) to disable warnings");
232
+ }
233
+
234
+ setup_gpio(gpio, direction, pud);
235
+ gpio_direction[gpio] = direction;
236
+ return 1;
237
+ }
238
+
239
+ // parse arguments
240
+
241
+ // channel
242
+ chan = NUM2INT(channel);
243
+
244
+ // pin direction
245
+ direction_str = rb_id2name(rb_to_id(rb_hash_aref(hash,
246
+ ID2SYM(rb_intern("as")))));
247
+ if (strcmp("input", direction_str) == 0) {
248
+ direction = INPUT;
249
+ } else if (strcmp("output", direction_str) == 0) {
250
+ direction = OUTPUT;
251
+ } else {
252
+ rb_raise(rb_eArgError,
253
+ "invalid pin direction; must be :input or :output");
254
+ }
255
+
256
+ // pull up, down, or off
257
+ pud_val = rb_hash_aref(hash, ID2SYM(rb_intern("pull")));
258
+ if (pud_val != Qnil) {
259
+ if (direction == OUTPUT) {
260
+ rb_raise(rb_eArgError, "output pin cannot use pull argument");
261
+ return Qnil;
262
+ }
263
+
264
+ pud_str = rb_id2name(rb_to_id(pud_val));
265
+ if (strcmp("down", pud_str) == 0) {
266
+ pud = PUD_DOWN;
267
+ } else if (strcmp("up", pud_str) == 0) {
268
+ pud = PUD_UP;
269
+ } else if (strcmp("off", pud_str) == 0) {
270
+ pud = PUD_OFF;
271
+ } else {
272
+ rb_raise(rb_eArgError,
273
+ "invalid pin pull direction; must be :up, :down, or :off");
274
+ return Qnil;
275
+ }
276
+ } else {
277
+ pud = PUD_OFF;
278
+ }
279
+
280
+ if (!is_rpi() || mmap_gpio_mem()) {
281
+ return Qnil;
282
+ }
283
+
284
+ if (direction != INPUT && direction != OUTPUT) {
285
+ rb_raise(rb_eArgError, "invalid direction");
286
+ return Qnil;
287
+ }
288
+
289
+ if (direction == OUTPUT) {
290
+ pud = PUD_OFF;
291
+ }
292
+
293
+ if (!setup_one()) {
294
+ return Qnil;
295
+ }
296
+
297
+ return self;
298
+ }
299
+
300
+ // RPi::GPIO.set_numbering(mode)
301
+ VALUE GPIO_set_numbering(VALUE self, VALUE mode)
302
+ {
303
+ const char *mode_str = NULL;
304
+
305
+ if (TYPE(mode) == T_SYMBOL) {
306
+ mode_str = rb_id2name(rb_to_id(mode));
307
+ } else {
308
+ mode_str = RSTRING_PTR(mode);
309
+ }
310
+
311
+ if (strcmp(mode_str, "board") == 0) {
312
+ gpio_mode = BOARD;
313
+ } else if (strcmp(mode_str, "bcm") == 0) {
314
+ gpio_mode = BCM;
315
+ } else {
316
+ rb_raise(rb_eArgError,
317
+ "invalid numbering mode; must be :board or :bcm");
318
+ }
319
+
320
+ if (!is_rpi()) {
321
+ return Qnil;
322
+ }
323
+
324
+ if (gpio_mode != BOARD && gpio_mode != BCM) {
325
+ rb_raise(rb_eArgError, "invalid mode");
326
+ return Qnil;
327
+ }
328
+
329
+ if (rpiinfo.p1_revision == 0 && gpio_mode == BOARD) {
330
+ rb_raise(rb_eRuntimeError, ":board numbering system not applicable on "
331
+ "computer module");
332
+ return Qnil;
333
+ }
334
+
335
+ return self;
336
+ }
337
+
338
+ // RPi::GPIO.set_high(channel)
339
+ VALUE GPIO_set_high(VALUE self, VALUE channel)
340
+ {
341
+ unsigned int gpio;
342
+ int chan = NUM2INT(channel);
343
+
344
+ if (get_gpio_number(chan, &gpio) ||
345
+ !is_gpio_output(gpio) ||
346
+ check_gpio_priv()) {
347
+ return Qnil;
348
+ }
349
+
350
+ output_gpio(gpio, 1);
351
+ return self;
352
+ }
353
+
354
+ // RPi::GPIO.set_low(channel)
355
+ VALUE GPIO_set_low(VALUE self, VALUE channel)
356
+ {
357
+ unsigned int gpio;
358
+ int chan = NUM2INT(channel);
359
+
360
+ if (get_gpio_number(chan, &gpio) ||
361
+ !is_gpio_output(gpio) ||
362
+ check_gpio_priv()) {
363
+ return Qnil;
364
+ }
365
+
366
+ output_gpio(gpio, 0);
367
+ return self;
368
+ }
369
+
370
+ // RPi::GPIO.high?(channel)
371
+ VALUE GPIO_test_high(VALUE self, VALUE channel)
372
+ {
373
+ unsigned int gpio;
374
+
375
+ if (get_gpio_number(NUM2INT(channel), &gpio) ||
376
+ !is_gpio_input(gpio) ||
377
+ check_gpio_priv()) {
378
+ return Qnil;
379
+ }
380
+
381
+ return input_gpio(gpio) ? Qtrue : Qfalse;
382
+ }
383
+
384
+ // RPi::GPIO.low?(channel)
385
+ VALUE GPIO_test_low(VALUE self, VALUE channel)
386
+ {
387
+ return GPIO_test_high(self, channel) ? Qfalse : Qtrue;
388
+ }
389
+
390
+ // RPi::GPIO.set_warnings(state)
391
+ VALUE GPIO_set_warnings(VALUE self, VALUE setting)
392
+ {
393
+ if (!is_rpi()) {
394
+ return Qnil;
395
+ }
396
+
397
+ gpio_warnings = RTEST(setting);
398
+ return self;
399
+ }