rpi_gpio 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +12 -0
- data/LICENSE +23 -0
- data/README.md +122 -0
- data/Rakefile +3 -0
- data/ext/rpi_gpio/c_gpio.c +233 -0
- data/ext/rpi_gpio/c_gpio.h +50 -0
- data/ext/rpi_gpio/common.c +100 -0
- data/ext/rpi_gpio/common.h +46 -0
- data/ext/rpi_gpio/constants.c +61 -0
- data/ext/rpi_gpio/constants.h +40 -0
- data/ext/rpi_gpio/cpuinfo.c +88 -0
- data/ext/rpi_gpio/cpuinfo.h +27 -0
- data/ext/rpi_gpio/event_gpio.c +556 -0
- data/ext/rpi_gpio/event_gpio.h +40 -0
- data/ext/rpi_gpio/extconf.rb +5 -0
- data/ext/rpi_gpio/rb_gpio.c +405 -0
- data/ext/rpi_gpio/rb_gpio.h +44 -0
- data/ext/rpi_gpio/rb_pwm.c +131 -0
- data/ext/rpi_gpio/rb_pwm.h +40 -0
- data/ext/rpi_gpio/rpi_gpio.c +45 -0
- data/ext/rpi_gpio/rpi_gpio.h +28 -0
- data/ext/rpi_gpio/soft_pwm.c +218 -0
- data/ext/rpi_gpio/soft_pwm.h +32 -0
- data/lib/rpi_gpio.so +0 -0
- metadata +69 -0
@@ -0,0 +1,40 @@
|
|
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
|
+
#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);
|
@@ -0,0 +1,405 @@
|
|
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_singleton_method(m_GPIO, "setup", GPIO_setup, 2);
|
37
|
+
rb_define_singleton_method(m_GPIO, "clean_up", GPIO_clean_up, -1);
|
38
|
+
rb_define_singleton_method(m_GPIO, "set_numbering", GPIO_set_numbering, 1);
|
39
|
+
rb_define_singleton_method(m_GPIO, "set_high", GPIO_set_high, 1);
|
40
|
+
rb_define_singleton_method(m_GPIO, "set_low", GPIO_set_low, 1);
|
41
|
+
rb_define_singleton_method(m_GPIO, "high?", GPIO_test_high, 1);
|
42
|
+
rb_define_singleton_method(m_GPIO, "low?", GPIO_test_low, 1);
|
43
|
+
rb_define_singleton_method(m_GPIO, "set_warnings", GPIO_set_warnings, 1);
|
44
|
+
define_constants(m_GPIO);
|
45
|
+
|
46
|
+
for (i=0; i<54; i++)
|
47
|
+
gpio_direction[i] = -1;
|
48
|
+
|
49
|
+
// detect board revision and set up accordingly
|
50
|
+
revision = get_rpi_revision();
|
51
|
+
if (revision == -1)
|
52
|
+
{
|
53
|
+
rb_raise(rb_eRuntimeError, "this gem can only be run on a Raspberry Pi");
|
54
|
+
setup_error = 1;
|
55
|
+
return;
|
56
|
+
}
|
57
|
+
else if (revision == 1)
|
58
|
+
pin_to_gpio = &pin_to_gpio_rev1;
|
59
|
+
else if (revision == 2)
|
60
|
+
pin_to_gpio = &pin_to_gpio_rev2;
|
61
|
+
else // assume model B+ or A+
|
62
|
+
pin_to_gpio = &pin_to_gpio_rev3;
|
63
|
+
|
64
|
+
rb_define_const(m_GPIO, "RPI_REVISION", INT2NUM(revision));
|
65
|
+
}
|
66
|
+
|
67
|
+
int mmap_gpio_mem(void)
|
68
|
+
{
|
69
|
+
int result;
|
70
|
+
|
71
|
+
if (module_setup)
|
72
|
+
return 0;
|
73
|
+
|
74
|
+
result = setup();
|
75
|
+
if (result == SETUP_DEVMEM_FAIL)
|
76
|
+
{
|
77
|
+
rb_raise(rb_eRuntimeError, "no access to /dev/mem; try running as "
|
78
|
+
"root");
|
79
|
+
return 1;
|
80
|
+
}
|
81
|
+
else if (result == SETUP_MALLOC_FAIL)
|
82
|
+
{
|
83
|
+
rb_raise(rb_eNoMemError, "out of memory");
|
84
|
+
return 2;
|
85
|
+
}
|
86
|
+
else if (result == SETUP_MMAP_FAIL)
|
87
|
+
{
|
88
|
+
rb_raise(rb_eRuntimeError, "mmap of GPIO registers failed");
|
89
|
+
return 3;
|
90
|
+
}
|
91
|
+
else // result == SETUP_OK
|
92
|
+
{
|
93
|
+
module_setup = 1;
|
94
|
+
return 0;
|
95
|
+
}
|
96
|
+
}
|
97
|
+
|
98
|
+
// RPi::GPIO.clean_up(channel=nil)
|
99
|
+
// clean up everything by default; otherwise, clean up given channel
|
100
|
+
VALUE GPIO_clean_up(int argc, VALUE *argv, VALUE self)
|
101
|
+
{
|
102
|
+
int i;
|
103
|
+
int found = 0;
|
104
|
+
int channel = -666; // lol, quite a flag
|
105
|
+
unsigned int gpio;
|
106
|
+
|
107
|
+
if (argc == 1)
|
108
|
+
channel = NUM2INT(argv[0]);
|
109
|
+
else if (argc > 1)
|
110
|
+
{
|
111
|
+
rb_raise(rb_eArgError, "wrong number of arguments; 0 for all pins, 1 for a specific pin");
|
112
|
+
return Qnil;
|
113
|
+
}
|
114
|
+
|
115
|
+
if (channel != -666 && get_gpio_number(channel, &gpio))
|
116
|
+
return Qnil;
|
117
|
+
|
118
|
+
if (module_setup && !setup_error)
|
119
|
+
{
|
120
|
+
if (channel == -666)
|
121
|
+
{
|
122
|
+
// clean up any /sys/class exports
|
123
|
+
event_cleanup_all();
|
124
|
+
|
125
|
+
// set everything back to input
|
126
|
+
for (i=0; i<54; i++) {
|
127
|
+
if (gpio_direction[i] != -1)
|
128
|
+
{
|
129
|
+
setup_gpio(i, INPUT, PUD_OFF);
|
130
|
+
gpio_direction[i] = -1;
|
131
|
+
found = 1;
|
132
|
+
}
|
133
|
+
}
|
134
|
+
}
|
135
|
+
else
|
136
|
+
{
|
137
|
+
// clean up any /sys/class exports
|
138
|
+
event_cleanup(gpio);
|
139
|
+
|
140
|
+
// set everything back to input
|
141
|
+
if (gpio_direction[gpio] != -1)
|
142
|
+
{
|
143
|
+
setup_gpio(gpio, INPUT, PUD_OFF);
|
144
|
+
gpio_direction[gpio] = -1;
|
145
|
+
found = 1;
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
// check if any channels set up - if not warn about misuse of GPIO.clean_up()
|
151
|
+
if (!found && gpio_warnings)
|
152
|
+
rb_warn("no channels have been set up yet; nothing to clean up");
|
153
|
+
|
154
|
+
return Qnil;
|
155
|
+
}
|
156
|
+
|
157
|
+
// RPI::GPIO.setup(channel, hash(:as => {:input, :output}, :pull => {:off,
|
158
|
+
// :down, :up}(default :off)))
|
159
|
+
VALUE GPIO_setup(VALUE self, VALUE channel, VALUE hash)
|
160
|
+
{
|
161
|
+
unsigned int gpio;
|
162
|
+
int chan = -1;
|
163
|
+
const char *direction_str = NULL;
|
164
|
+
int direction;
|
165
|
+
VALUE pud_val = Qnil;
|
166
|
+
const char *pud_str = NULL;
|
167
|
+
int pud = PUD_OFF + PY_PUD_CONST_OFFSET;
|
168
|
+
int func;
|
169
|
+
|
170
|
+
// func to set up channel stored in channel variable
|
171
|
+
int setup_one(void)
|
172
|
+
{
|
173
|
+
if (get_gpio_number(chan, &gpio))
|
174
|
+
return 0;
|
175
|
+
|
176
|
+
// warn if the channel is already in use (not from this program).
|
177
|
+
func = gpio_function(gpio);
|
178
|
+
if (gpio_warnings &&
|
179
|
+
((func != 0 && func != 1) ||
|
180
|
+
(gpio_direction[gpio] == -1 && func == 1)))
|
181
|
+
{
|
182
|
+
rb_warn("this channel is already in use... continuing anyway. "
|
183
|
+
"use RPi::GPIO.set_warnings(false) to disable warnings");
|
184
|
+
}
|
185
|
+
|
186
|
+
setup_gpio(gpio, direction, pud);
|
187
|
+
gpio_direction[gpio] = direction;
|
188
|
+
return 1;
|
189
|
+
}
|
190
|
+
|
191
|
+
// parse arguments
|
192
|
+
|
193
|
+
// channel
|
194
|
+
chan = NUM2INT(channel);
|
195
|
+
|
196
|
+
// pin direction
|
197
|
+
direction_str = rb_id2name(rb_to_id(rb_hash_aref(hash, ID2SYM(rb_intern("as"))
|
198
|
+
)));
|
199
|
+
if (strcmp("input", direction_str) == 0)
|
200
|
+
direction = INPUT;
|
201
|
+
else if (strcmp("output", direction_str) == 0)
|
202
|
+
direction = OUTPUT;
|
203
|
+
else
|
204
|
+
rb_raise(rb_eArgError, "invalid pin direction; must be :input or :output");
|
205
|
+
|
206
|
+
// pull up, down, or off
|
207
|
+
pud_val = rb_hash_aref(hash, ID2SYM(rb_intern("pull")));
|
208
|
+
if (pud_val != Qnil)
|
209
|
+
{
|
210
|
+
if (direction == OUTPUT)
|
211
|
+
{
|
212
|
+
rb_raise(rb_eArgError, "output pin cannot use pull argument");
|
213
|
+
return Qnil;
|
214
|
+
}
|
215
|
+
|
216
|
+
pud_str = rb_id2name(rb_to_id(pud_val));
|
217
|
+
if (strcmp("down", pud_str) == 0)
|
218
|
+
pud = PUD_DOWN + PY_PUD_CONST_OFFSET;
|
219
|
+
else if (strcmp("up", pud_str) == 0)
|
220
|
+
pud = PUD_UP + PY_PUD_CONST_OFFSET;
|
221
|
+
else if (strcmp("off", pud_str) == 0)
|
222
|
+
pud = PUD_OFF + PY_PUD_CONST_OFFSET;
|
223
|
+
else
|
224
|
+
{
|
225
|
+
rb_raise(rb_eArgError, "invalid pin pull direction; must be :up, :down, "
|
226
|
+
"or :off");
|
227
|
+
return Qnil;
|
228
|
+
}
|
229
|
+
}
|
230
|
+
else
|
231
|
+
pud = PUD_OFF + PY_PUD_CONST_OFFSET;
|
232
|
+
|
233
|
+
// check module has been imported cleanly
|
234
|
+
if (setup_error)
|
235
|
+
{
|
236
|
+
rb_raise(rb_eRuntimeError, "gem not imported correctly");
|
237
|
+
return Qnil;
|
238
|
+
}
|
239
|
+
|
240
|
+
if (mmap_gpio_mem())
|
241
|
+
return Qnil;
|
242
|
+
|
243
|
+
if (direction != INPUT && direction != OUTPUT)
|
244
|
+
{
|
245
|
+
rb_raise(rb_eArgError, "invalid direction");
|
246
|
+
return Qnil;
|
247
|
+
}
|
248
|
+
|
249
|
+
if (direction == OUTPUT)
|
250
|
+
pud = PUD_OFF + PY_PUD_CONST_OFFSET;
|
251
|
+
pud -= PY_PUD_CONST_OFFSET;
|
252
|
+
|
253
|
+
if (!setup_one())
|
254
|
+
return Qnil;
|
255
|
+
|
256
|
+
return self;
|
257
|
+
}
|
258
|
+
|
259
|
+
// RPi::GPIO.set_numbering(mode)
|
260
|
+
VALUE GPIO_set_numbering(VALUE self, VALUE mode)
|
261
|
+
{
|
262
|
+
const char *mode_str = NULL;
|
263
|
+
|
264
|
+
if (TYPE(mode) == T_SYMBOL)
|
265
|
+
mode_str = rb_id2name(rb_to_id(mode));
|
266
|
+
else
|
267
|
+
mode_str = RSTRING_PTR(mode);
|
268
|
+
|
269
|
+
if (strcmp(mode_str, "board") == 0)
|
270
|
+
gpio_mode = BOARD;
|
271
|
+
else if (strcmp(mode_str, "bcm") == 0)
|
272
|
+
gpio_mode = BCM;
|
273
|
+
else
|
274
|
+
rb_raise(rb_eArgError, "invalid numbering mode; must be :board or :bcm");
|
275
|
+
|
276
|
+
if (setup_error)
|
277
|
+
{
|
278
|
+
rb_raise(rb_eRuntimeError, "gem not imported correctly");
|
279
|
+
return Qnil;
|
280
|
+
}
|
281
|
+
|
282
|
+
if (gpio_mode != BOARD && gpio_mode != BCM)
|
283
|
+
{
|
284
|
+
rb_raise(rb_eArgError, "invalid mode");
|
285
|
+
return Qnil;
|
286
|
+
}
|
287
|
+
|
288
|
+
if (revision == 0 && gpio_mode == BOARD)
|
289
|
+
{
|
290
|
+
rb_raise(rb_eRuntimeError, ":board numbering system not applicable on "
|
291
|
+
"computer module");
|
292
|
+
return Qnil;
|
293
|
+
}
|
294
|
+
|
295
|
+
return self;
|
296
|
+
}
|
297
|
+
|
298
|
+
// RPi::GPIO.set_high(channel)
|
299
|
+
VALUE GPIO_set_high(VALUE self, VALUE channel)
|
300
|
+
{
|
301
|
+
unsigned int gpio;
|
302
|
+
int chan = -1;
|
303
|
+
|
304
|
+
// func to output value var on channel var
|
305
|
+
int output(void)
|
306
|
+
{
|
307
|
+
if (get_gpio_number(chan, &gpio))
|
308
|
+
return 0;
|
309
|
+
|
310
|
+
if (gpio_direction[gpio] != OUTPUT)
|
311
|
+
{
|
312
|
+
rb_raise(rb_eRuntimeError, "GPIO channel not set as output");
|
313
|
+
return 0;
|
314
|
+
}
|
315
|
+
|
316
|
+
if (check_gpio_priv())
|
317
|
+
return 0;
|
318
|
+
|
319
|
+
output_gpio(gpio, 1);
|
320
|
+
return 1;
|
321
|
+
}
|
322
|
+
|
323
|
+
chan = NUM2INT(channel);
|
324
|
+
if (!output())
|
325
|
+
return Qnil;
|
326
|
+
|
327
|
+
return self;
|
328
|
+
}
|
329
|
+
|
330
|
+
// RPi::GPIO.set_low(channel)
|
331
|
+
VALUE GPIO_set_low(VALUE self, VALUE channel)
|
332
|
+
{
|
333
|
+
unsigned int gpio;
|
334
|
+
int chan = -1;
|
335
|
+
|
336
|
+
// func to output value var on channel var
|
337
|
+
int output(void)
|
338
|
+
{
|
339
|
+
if (get_gpio_number(chan, &gpio))
|
340
|
+
return 0;
|
341
|
+
|
342
|
+
if (gpio_direction[gpio] != OUTPUT)
|
343
|
+
{
|
344
|
+
rb_raise(rb_eRuntimeError, "GPIO channel not set as output");
|
345
|
+
return 0;
|
346
|
+
}
|
347
|
+
|
348
|
+
if (check_gpio_priv())
|
349
|
+
return 0;
|
350
|
+
|
351
|
+
output_gpio(gpio, 0);
|
352
|
+
return 1;
|
353
|
+
}
|
354
|
+
|
355
|
+
chan = NUM2INT(channel);
|
356
|
+
if (!output())
|
357
|
+
return Qnil;
|
358
|
+
|
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
|
+
return Qnil;
|
369
|
+
|
370
|
+
if (gpio_direction[gpio] != INPUT && gpio_direction[gpio] != OUTPUT)
|
371
|
+
{
|
372
|
+
rb_raise(rb_eRuntimeError, "you must setup() the GPIO channel first");
|
373
|
+
return Qnil;
|
374
|
+
}
|
375
|
+
|
376
|
+
if (check_gpio_priv())
|
377
|
+
return Qnil;
|
378
|
+
|
379
|
+
if (input_gpio(gpio))
|
380
|
+
return Qtrue;
|
381
|
+
else
|
382
|
+
return Qfalse;
|
383
|
+
}
|
384
|
+
|
385
|
+
// RPi::GPIO.low?(channel)
|
386
|
+
VALUE GPIO_test_low(VALUE self, VALUE channel)
|
387
|
+
{
|
388
|
+
VALUE val = GPIO_test_high(self, channel);
|
389
|
+
if (val == Qtrue) return Qfalse;
|
390
|
+
else if (val == Qfalse) return Qtrue;
|
391
|
+
else return Qnil;
|
392
|
+
}
|
393
|
+
|
394
|
+
// RPi::GPIO.set_warnings(state)
|
395
|
+
VALUE GPIO_set_warnings(VALUE self, VALUE setting)
|
396
|
+
{
|
397
|
+
if (setup_error)
|
398
|
+
{
|
399
|
+
rb_raise(rb_eRuntimeError, "gem not imported correctly");
|
400
|
+
return Qnil;
|
401
|
+
}
|
402
|
+
|
403
|
+
gpio_warnings = NUM2INT(setting);
|
404
|
+
return self;
|
405
|
+
}
|
@@ -0,0 +1,44 @@
|
|
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 "ruby.h"
|
28
|
+
#include "c_gpio.h"
|
29
|
+
#include "event_gpio.h"
|
30
|
+
#include "cpuinfo.h"
|
31
|
+
#include "common.h"
|
32
|
+
#include "constants.h"
|
33
|
+
#include "rb_pwm.h"
|
34
|
+
|
35
|
+
void define_gpio_module_stuff(void);
|
36
|
+
int mmap_gpio_mem(void);
|
37
|
+
VALUE GPIO_clean_up(int argc, VALUE *argv, VALUE self);
|
38
|
+
VALUE GPIO_setup(VALUE self, VALUE channel, VALUE hash);
|
39
|
+
VALUE GPIO_set_numbering(VALUE self, VALUE mode);
|
40
|
+
VALUE GPIO_set_high(VALUE self, VALUE channel);
|
41
|
+
VALUE GPIO_set_low(VALUE self, VALUE channel);
|
42
|
+
VALUE GPIO_test_high(VALUE self, VALUE channel);
|
43
|
+
VALUE GPIO_test_low(VALUE self, VALUE channel);
|
44
|
+
VALUE GPIO_set_warnings(VALUE self, VALUE setting);
|
@@ -0,0 +1,131 @@
|
|
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_pwm.h"
|
28
|
+
|
29
|
+
extern VALUE m_GPIO;
|
30
|
+
VALUE c_PWM = Qnil;
|
31
|
+
|
32
|
+
void define_pwm_class_stuff(void)
|
33
|
+
{
|
34
|
+
c_PWM = rb_define_class_under(m_GPIO, "PWM", rb_cObject);
|
35
|
+
rb_define_method(c_PWM, "initialize", PWM_initialize, 2);
|
36
|
+
rb_define_method(c_PWM, "start", PWM_start, 1);
|
37
|
+
rb_define_method(c_PWM, "pin", PWM_get_pin, 0);
|
38
|
+
rb_define_method(c_PWM, "duty_cycle", PWM_get_duty_cycle, 0);
|
39
|
+
rb_define_method(c_PWM, "duty_cycle=", PWM_set_duty_cycle, 1);
|
40
|
+
rb_define_method(c_PWM, "frequency", PWM_get_frequency, 0);
|
41
|
+
rb_define_method(c_PWM, "frequency=", PWM_set_frequency, 1);
|
42
|
+
rb_define_method(c_PWM, "stop", PWM_stop, 0);
|
43
|
+
}
|
44
|
+
|
45
|
+
// RPi::GPIO::PWM#initialize
|
46
|
+
VALUE PWM_initialize(VALUE self, VALUE channel, VALUE frequency)
|
47
|
+
{
|
48
|
+
int chan;
|
49
|
+
unsigned int gpio;
|
50
|
+
|
51
|
+
chan = NUM2INT(channel);
|
52
|
+
|
53
|
+
// convert channel to gpio
|
54
|
+
if (get_gpio_number(chan, &gpio))
|
55
|
+
return Qnil;
|
56
|
+
|
57
|
+
// ensure channel is set as output
|
58
|
+
if (gpio_direction[gpio] != OUTPUT)
|
59
|
+
{
|
60
|
+
rb_raise(rb_eRuntimeError, "you must setup() the GPIO channel as output "
|
61
|
+
"first");
|
62
|
+
return Qnil;
|
63
|
+
}
|
64
|
+
|
65
|
+
rb_iv_set(self, "@pin", UINT2NUM(gpio));
|
66
|
+
PWM_set_frequency(self, frequency);
|
67
|
+
return self;
|
68
|
+
}
|
69
|
+
|
70
|
+
// RPi::GPIO::PWM#start
|
71
|
+
VALUE PWM_start(VALUE self, VALUE duty_cycle)
|
72
|
+
{
|
73
|
+
pwm_start(NUM2UINT(rb_iv_get(self, "@pin")));
|
74
|
+
PWM_set_duty_cycle(self, duty_cycle);
|
75
|
+
return self;
|
76
|
+
}
|
77
|
+
|
78
|
+
// RPi::GPIO::PWM#pin
|
79
|
+
VALUE PWM_get_pin(VALUE self)
|
80
|
+
{
|
81
|
+
return rb_iv_get(self, "@pin");
|
82
|
+
}
|
83
|
+
|
84
|
+
// RPi::GPIO::PWM#duty_cycle
|
85
|
+
VALUE PWM_get_duty_cycle(VALUE self)
|
86
|
+
{
|
87
|
+
return rb_iv_get(self, "@duty_cycle");
|
88
|
+
}
|
89
|
+
|
90
|
+
// RPi::GPIO::PWM#duty_cycle=
|
91
|
+
VALUE PWM_set_duty_cycle(VALUE self, VALUE duty_cycle)
|
92
|
+
{
|
93
|
+
float dc = (float) NUM2DBL(duty_cycle);
|
94
|
+
if (dc < 0.0f || dc > 100.0f)
|
95
|
+
{
|
96
|
+
rb_raise(rb_eArgError, "duty cycle must be between 0.0 and 100.0");
|
97
|
+
return Qnil;
|
98
|
+
}
|
99
|
+
|
100
|
+
rb_iv_set(self, "@duty_cycle", duty_cycle);
|
101
|
+
pwm_set_duty_cycle(NUM2UINT(rb_iv_get(self, "@pin")), dc);
|
102
|
+
return self;
|
103
|
+
}
|
104
|
+
|
105
|
+
// RPi::GPIO::PWM#frequency
|
106
|
+
VALUE PWM_get_frequency(VALUE self)
|
107
|
+
{
|
108
|
+
return rb_iv_get(self, "@frequency");
|
109
|
+
}
|
110
|
+
|
111
|
+
// RPi::GPIO::PWM#frequency=
|
112
|
+
VALUE PWM_set_frequency(VALUE self, VALUE frequency)
|
113
|
+
{
|
114
|
+
float freq = (float) NUM2DBL(frequency);
|
115
|
+
if (freq <= 0.0f)
|
116
|
+
{
|
117
|
+
rb_raise(rb_eArgError, "frequency must be greater than 0.0");
|
118
|
+
return Qnil;
|
119
|
+
}
|
120
|
+
|
121
|
+
rb_iv_set(self, "@frequency", frequency);
|
122
|
+
pwm_set_frequency(NUM2UINT(rb_iv_get(self, "@pin")), freq);
|
123
|
+
return self;
|
124
|
+
}
|
125
|
+
|
126
|
+
// RPi::GPIO::PWM#stop
|
127
|
+
VALUE PWM_stop(VALUE self)
|
128
|
+
{
|
129
|
+
pwm_stop(NUM2UINT(rb_iv_get(self, "@pin")));
|
130
|
+
return self;
|
131
|
+
}
|
@@ -0,0 +1,40 @@
|
|
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 "ruby.h"
|
28
|
+
#include "soft_pwm.h"
|
29
|
+
#include "common.h"
|
30
|
+
#include "c_gpio.h"
|
31
|
+
|
32
|
+
void define_pwm_class_stuff(void);
|
33
|
+
VALUE PWM_initialize(VALUE self, VALUE channel, VALUE frequency);
|
34
|
+
VALUE PWM_start(VALUE self, VALUE duty_cycle);
|
35
|
+
VALUE PWM_get_pin(VALUE self);
|
36
|
+
VALUE PWM_get_duty_cycle(VALUE self);
|
37
|
+
VALUE PWM_set_duty_cycle(VALUE self, VALUE duty_cycle);
|
38
|
+
VALUE PWM_get_frequency(VALUE self);
|
39
|
+
VALUE PWM_set_frequency(VALUE self, VALUE frequency);
|
40
|
+
VALUE PWM_stop(VALUE self);
|