rpi_gpio 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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,5 @@
1
+ require 'mkmf'
2
+
3
+ extension_name = 'rpi_gpio'
4
+ dir_config(extension_name)
5
+ create_makefile(extension_name)
@@ -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);