c_gpio 0.0.6 → 0.0.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/c_gpio/base.c +147 -0
- data/ext/c_gpio/base.h +23 -0
- data/ext/c_gpio/button.c +41 -0
- data/ext/c_gpio/button.h +2 -0
- data/ext/c_gpio/file_stuff.c +30 -0
- data/ext/c_gpio/file_stuff.h +2 -0
- data/ext/c_gpio/gpio.c +61 -0
- data/ext/c_gpio/internal.c +46 -0
- data/ext/c_gpio/internal.h +5 -0
- data/ext/c_gpio/led.c +46 -0
- data/ext/c_gpio/led.h +3 -0
- data/ext/c_gpio/mount.c +50 -0
- data/ext/c_gpio/mount.h +3 -0
- data/ext/c_gpio/pwm.c +80 -0
- data/ext/c_gpio/pwm.h +3 -0
- data/lib/c_gpio.rb +1 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 165db671c63bd4156e152c4af8b3511c42ea0bd7
|
4
|
+
data.tar.gz: 6ff5273c68bf31c0d95e5d751dd124abe73d366f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4914d74baaa5d0c4abb1687455d2be575fbc1259ba11319699b22f7778bb83f6c617401a19649677b241dff79705ed4a8ff2aef72c9e4becabe6c4074f7d48d3
|
7
|
+
data.tar.gz: d571408860ef7a0e5982a386d17959a29012c5686e59403d686bd053518e668ce20e6fedf1534021a772ed7e4120cf716dfa2560f9188c0f958b7911f154613f
|
data/ext/c_gpio/base.c
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
#ifndef __RUBY_H
|
2
|
+
#define __RUBY_H
|
3
|
+
#include <ruby.h>
|
4
|
+
#endif
|
5
|
+
|
6
|
+
#include "base.h"
|
7
|
+
#include "internal.h"
|
8
|
+
#include "mount.h"
|
9
|
+
#include "file_stuff.h"
|
10
|
+
|
11
|
+
const char *GPIO_IN = "in";
|
12
|
+
const char *GPIO_OUT = "out";
|
13
|
+
const char *GPIO_HIGH = "1";
|
14
|
+
const char *GPIO_LOW = "0";
|
15
|
+
|
16
|
+
VALUE GPIO_BASE_init(VALUE self, VALUE port) {
|
17
|
+
struct GPIO *ptr;
|
18
|
+
int gpio_port = NUM2INT(port);
|
19
|
+
|
20
|
+
GPIO_INTERNAL_validate_pin(gpio_port);
|
21
|
+
|
22
|
+
pi_io_mountPin(gpio_port);
|
23
|
+
|
24
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
25
|
+
|
26
|
+
ptr->port = gpio_port;
|
27
|
+
|
28
|
+
return self;
|
29
|
+
}
|
30
|
+
|
31
|
+
VALUE GPIO_BASE_get_value(VALUE self) {
|
32
|
+
struct GPIO *ptr;
|
33
|
+
// We have assign a default value here, because if the file is empty,
|
34
|
+
// It will NOT get overwritten, and you will see a memdump
|
35
|
+
char content[2] = "";
|
36
|
+
|
37
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
38
|
+
|
39
|
+
GPIO_INTERNAL_get_value(ptr->port, (char *) &content);
|
40
|
+
|
41
|
+
if(strcmp(GPIO_HIGH, content) == 0) {
|
42
|
+
return ID2SYM(rb_intern("high"));
|
43
|
+
} else if(strcmp(GPIO_LOW, content) == 0) {
|
44
|
+
return ID2SYM(rb_intern("low"));
|
45
|
+
}
|
46
|
+
|
47
|
+
rb_raise(rb_eRuntimeError, "Value was neither HIGH nor LOW");
|
48
|
+
}
|
49
|
+
|
50
|
+
VALUE GPIO_BASE_set_value(VALUE self, VALUE value) {
|
51
|
+
struct GPIO *ptr;
|
52
|
+
|
53
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
54
|
+
|
55
|
+
if(SYM2ID(value) == rb_intern("low")) {
|
56
|
+
GPIO_INTERNAL_set_value(ptr->port, (char *) GPIO_LOW);
|
57
|
+
} else if(SYM2ID(value) == rb_intern("high")) {
|
58
|
+
GPIO_INTERNAL_set_value(ptr->port, (char *) GPIO_HIGH);
|
59
|
+
} else {
|
60
|
+
rb_raise(rb_eArgError, "Only :low and :high are valid input");
|
61
|
+
}
|
62
|
+
|
63
|
+
return self;
|
64
|
+
}
|
65
|
+
|
66
|
+
VALUE GPIO_BASE_get_direction(VALUE self) {
|
67
|
+
struct GPIO *ptr;
|
68
|
+
// We have assign a default value here, because if the file is empty,
|
69
|
+
// It will NOT get overwritten, and you will see a memdump
|
70
|
+
char content[4] = "";
|
71
|
+
|
72
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
73
|
+
|
74
|
+
GPIO_INTERNAL_get_direction(ptr->port, (char *) &content);
|
75
|
+
|
76
|
+
if(strcmp(GPIO_IN, content) == 0) {
|
77
|
+
return ID2SYM(rb_intern("in"));
|
78
|
+
} else if(strcmp(GPIO_OUT, content) == 0) {
|
79
|
+
return ID2SYM(rb_intern("out"));
|
80
|
+
}
|
81
|
+
|
82
|
+
rb_raise(rb_eRuntimeError, "Direction was neither IN nor OUT");
|
83
|
+
}
|
84
|
+
|
85
|
+
VALUE GPIO_BASE_set_direction(VALUE self, VALUE direction) {
|
86
|
+
struct GPIO *ptr;
|
87
|
+
|
88
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
89
|
+
|
90
|
+
if(SYM2ID(direction) == rb_intern("in")) {
|
91
|
+
GPIO_INTERNAL_set_direction(ptr->port, (char *) GPIO_IN);
|
92
|
+
} else if(SYM2ID(direction) == rb_intern("out")) {
|
93
|
+
GPIO_INTERNAL_set_direction(ptr->port, (char *) GPIO_OUT);
|
94
|
+
} else {
|
95
|
+
rb_raise(rb_eArgError, "Only :in and :out are valid input");
|
96
|
+
}
|
97
|
+
|
98
|
+
return self;
|
99
|
+
}
|
100
|
+
|
101
|
+
VALUE GPIO_BASE_wait_for_low(VALUE self, VALUE block) {
|
102
|
+
struct GPIO *gpio;
|
103
|
+
char oldVal[20] = "1";
|
104
|
+
char newVal[20] = "1";
|
105
|
+
|
106
|
+
Data_Get_Struct(self, struct GPIO, gpio);
|
107
|
+
|
108
|
+
while(1) {
|
109
|
+
rb_thread_schedule();
|
110
|
+
|
111
|
+
GPIO_INTERNAL_get_value(gpio->port, (char *) &newVal);
|
112
|
+
|
113
|
+
if (strcmp(oldVal, newVal) != 0 && strcmp(newVal, (char *) GPIO_LOW) == 0) {
|
114
|
+
rb_funcall(block, rb_intern("call"), 0);
|
115
|
+
}
|
116
|
+
|
117
|
+
strcpy(oldVal, newVal);
|
118
|
+
|
119
|
+
usleep(10 * 1000);
|
120
|
+
}
|
121
|
+
|
122
|
+
return self;
|
123
|
+
}
|
124
|
+
|
125
|
+
VALUE GPIO_BASE_wait_for_high(VALUE self, VALUE block) {
|
126
|
+
struct GPIO *gpio;
|
127
|
+
char oldVal[20] = "1";
|
128
|
+
char newVal[20] = "1";
|
129
|
+
|
130
|
+
Data_Get_Struct(self, struct GPIO, gpio);
|
131
|
+
|
132
|
+
while(1) {
|
133
|
+
rb_thread_schedule();
|
134
|
+
|
135
|
+
GPIO_INTERNAL_get_value(gpio->port, (char *) &newVal);
|
136
|
+
|
137
|
+
if (strcmp(oldVal, newVal) != 0 && strcmp(newVal, (char *) GPIO_HIGH) == 0) {
|
138
|
+
rb_funcall(block, rb_intern("call"), 0);
|
139
|
+
}
|
140
|
+
|
141
|
+
strcpy(oldVal, newVal);
|
142
|
+
|
143
|
+
usleep(10 * 1000);
|
144
|
+
}
|
145
|
+
|
146
|
+
return self;
|
147
|
+
}
|
data/ext/c_gpio/base.h
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#ifndef S_GPIO
|
2
|
+
#define S_GPIO
|
3
|
+
|
4
|
+
struct GPIO {
|
5
|
+
int port;
|
6
|
+
int pwmPosition;
|
7
|
+
void *ptr;
|
8
|
+
};
|
9
|
+
|
10
|
+
extern const char *GPIO_IN;
|
11
|
+
extern const char *GPIO_OUT;
|
12
|
+
extern const char *GPIO_HIGH;
|
13
|
+
extern const char *GPIO_LOW;
|
14
|
+
|
15
|
+
#endif
|
16
|
+
|
17
|
+
VALUE GPIO_BASE_init(VALUE self, VALUE port);
|
18
|
+
VALUE GPIO_BASE_get_value(VALUE self);
|
19
|
+
VALUE GPIO_BASE_set_value(VALUE self, VALUE value);
|
20
|
+
VALUE GPIO_BASE_get_direction(VALUE self);
|
21
|
+
VALUE GPIO_BASE_set_direction(VALUE self, VALUE direction);
|
22
|
+
VALUE GPIO_BASE_wait_for_high(VALUE self, VALUE block);
|
23
|
+
VALUE GPIO_BASE_wait_for_low(VALUE self, VALUE block);
|
data/ext/c_gpio/button.c
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#ifndef __RUBY_H
|
2
|
+
#define __RUBY_H
|
3
|
+
#include <ruby.h>
|
4
|
+
#endif
|
5
|
+
|
6
|
+
#include "mount.h"
|
7
|
+
#include "base.h"
|
8
|
+
#include "internal.h"
|
9
|
+
#include "file_stuff.h"
|
10
|
+
|
11
|
+
VALUE GPIO_BUTTON_init(VALUE self, VALUE port) {
|
12
|
+
struct GPIO *ptr;
|
13
|
+
int gpio_port = NUM2INT(port);
|
14
|
+
|
15
|
+
GPIO_INTERNAL_validate_pin(gpio_port);
|
16
|
+
|
17
|
+
pi_io_mountPin(gpio_port);
|
18
|
+
|
19
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
20
|
+
|
21
|
+
ptr->port = gpio_port;
|
22
|
+
|
23
|
+
GPIO_INTERNAL_set_direction(ptr->port, (char *) GPIO_IN);
|
24
|
+
|
25
|
+
return self;
|
26
|
+
}
|
27
|
+
|
28
|
+
VALUE GPIO_BUTTON_is_pressed(VALUE self) {
|
29
|
+
struct GPIO *ptr;
|
30
|
+
char content[20];
|
31
|
+
|
32
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
33
|
+
|
34
|
+
GPIO_INTERNAL_get_value(ptr->port, (char *) &content);
|
35
|
+
|
36
|
+
if( strcmp(GPIO_LOW, content) ) {
|
37
|
+
return Qtrue;
|
38
|
+
} else {
|
39
|
+
return Qfalse;
|
40
|
+
}
|
41
|
+
}
|
data/ext/c_gpio/button.h
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#ifndef __RUBY_H
|
2
|
+
#define __RUBY_H
|
3
|
+
#include <ruby.h>
|
4
|
+
#endif
|
5
|
+
|
6
|
+
#include <fcntl.h>
|
7
|
+
|
8
|
+
void GPIO_INTERNAL_getFileContent(char *filePath, char *dst) {
|
9
|
+
FILE *file = fopen(filePath,"r");
|
10
|
+
if(file == NULL) {
|
11
|
+
rb_raise(rb_eArgError, "Could not open GPIO connection");
|
12
|
+
}
|
13
|
+
|
14
|
+
fscanf(file, "%s", dst);
|
15
|
+
|
16
|
+
fclose(file);
|
17
|
+
}
|
18
|
+
|
19
|
+
void GPIO_INTERNAL_writeFileContent(char *filePath, char* content, size_t size) {
|
20
|
+
int fd;
|
21
|
+
|
22
|
+
fd = open(filePath, O_WRONLY);
|
23
|
+
if (-1 == fd) {
|
24
|
+
rb_raise(rb_eArgError, "Could not open File for writing");
|
25
|
+
}
|
26
|
+
|
27
|
+
write(fd, content, size);
|
28
|
+
|
29
|
+
close(fd);
|
30
|
+
}
|
data/ext/c_gpio/gpio.c
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "mount.h"
|
4
|
+
#include "led.h"
|
5
|
+
#include "button.h"
|
6
|
+
#include "base.h"
|
7
|
+
#include "pwm.h"
|
8
|
+
#include "file_stuff.h"
|
9
|
+
|
10
|
+
|
11
|
+
void GPIO_deallocate(void *pi_io) {
|
12
|
+
// We can not unmount it here, because maybe another object is looking for the same pin?
|
13
|
+
//pi_io_unmountPin(ptr->port);
|
14
|
+
|
15
|
+
free(pi_io);
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE GPIO_allocate(VALUE self) {
|
19
|
+
struct GPIO *pi_io = malloc(sizeof(struct GPIO));
|
20
|
+
|
21
|
+
return Data_Wrap_Struct(self, NULL, GPIO_deallocate, pi_io);
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
//Ruby-Einstiegsmethode. Sie muss immer mit Init_ beginnen und auf den Namen der Extension enden.
|
26
|
+
void Init_gpio(void) {
|
27
|
+
VALUE GPIO_MODULE, GPIO_PWM, GPIO_LED, GPIO_BASE, GPIO_BUTTON;
|
28
|
+
|
29
|
+
GPIO_MODULE = rb_const_get(rb_cObject, rb_intern("GPIO"));
|
30
|
+
|
31
|
+
GPIO_LED = rb_define_class_under(GPIO_MODULE, "Led", rb_cObject);
|
32
|
+
rb_define_alloc_func(GPIO_LED, GPIO_allocate);
|
33
|
+
rb_define_method(GPIO_LED, "initialize", GPIO_LED_init, 1);
|
34
|
+
rb_define_method(GPIO_LED, "turn_on!", GPIO_LED_turn_on, 0);
|
35
|
+
rb_define_method(GPIO_LED, "turn_off!", GPIO_LED_turn_off, 0);
|
36
|
+
|
37
|
+
|
38
|
+
GPIO_BASE = rb_define_class_under(GPIO_MODULE, "Base", rb_cObject);
|
39
|
+
rb_define_alloc_func(GPIO_BASE, GPIO_allocate);
|
40
|
+
rb_define_method(GPIO_BASE, "initialize", GPIO_BASE_init, 1);
|
41
|
+
rb_define_method(GPIO_BASE, "value", GPIO_BASE_get_value, 0);
|
42
|
+
rb_define_method(GPIO_BASE, "value=", GPIO_BASE_set_value, 1);
|
43
|
+
rb_define_method(GPIO_BASE, "direction", GPIO_BASE_get_direction, 0);
|
44
|
+
rb_define_method(GPIO_BASE, "direction=", GPIO_BASE_set_direction, 1);
|
45
|
+
rb_define_method(GPIO_BASE, "wait_for_high", GPIO_BASE_wait_for_high, 1);
|
46
|
+
rb_define_method(GPIO_BASE, "wait_for_low", GPIO_BASE_wait_for_low, 1);
|
47
|
+
|
48
|
+
|
49
|
+
GPIO_BUTTON = rb_define_class_under(GPIO_MODULE, "Button", rb_cObject);
|
50
|
+
rb_define_alloc_func(GPIO_BUTTON, GPIO_allocate);
|
51
|
+
rb_define_method(GPIO_BUTTON, "initialize", GPIO_BUTTON_init, 1);
|
52
|
+
rb_define_method(GPIO_BUTTON, "pressed?", GPIO_BUTTON_is_pressed, 0);
|
53
|
+
// Yes e want to delegate to the GPIO_BASE here
|
54
|
+
rb_define_method(GPIO_BUTTON, "wait_for_high", GPIO_BASE_wait_for_high, 1);
|
55
|
+
rb_define_method(GPIO_BUTTON, "wait_for_low", GPIO_BASE_wait_for_low, 1);
|
56
|
+
|
57
|
+
GPIO_PWM = rb_define_class_under(GPIO_MODULE, "Pwm", rb_cObject);
|
58
|
+
rb_define_alloc_func(GPIO_PWM, GPIO_allocate);
|
59
|
+
rb_define_method(GPIO_PWM, "initialize", GPIO_PWM_init, 1);
|
60
|
+
rb_define_method(GPIO_PWM, "move_to", GPIO_PWM_position, 1);
|
61
|
+
}
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#ifndef __RUBY_H
|
2
|
+
#define __RUBY_H
|
3
|
+
#include <ruby.h>
|
4
|
+
#endif
|
5
|
+
|
6
|
+
#include "file_stuff.h"
|
7
|
+
#define FILE_NAME_BUFFER_SIZE 50
|
8
|
+
|
9
|
+
void GPIO_INTERNAL_validate_pin(int pinNumber) {
|
10
|
+
// Currently the rPI does only have GPIO Pins from 2 to 27
|
11
|
+
if(pinNumber < 2 || pinNumber > 27) {
|
12
|
+
rb_raise(rb_eArgError, "The GPIO Port has to be between 2 and 27");
|
13
|
+
}
|
14
|
+
}
|
15
|
+
|
16
|
+
void GPIO_INTERNAL_get_value(int pinNumber, char *dst) {
|
17
|
+
char filename[FILE_NAME_BUFFER_SIZE];
|
18
|
+
|
19
|
+
sprintf(filename, "/sys/class/gpio/gpio%d/value", pinNumber);
|
20
|
+
|
21
|
+
GPIO_INTERNAL_getFileContent(filename, dst);
|
22
|
+
}
|
23
|
+
|
24
|
+
void GPIO_INTERNAL_set_value(int pinNumber, char* content) {
|
25
|
+
char filename[FILE_NAME_BUFFER_SIZE];
|
26
|
+
|
27
|
+
sprintf(filename, "/sys/class/gpio/gpio%d/value", pinNumber);
|
28
|
+
|
29
|
+
GPIO_INTERNAL_writeFileContent(filename, content, strlen(content));
|
30
|
+
}
|
31
|
+
|
32
|
+
void GPIO_INTERNAL_get_direction(int pinNumber, char *dst) {
|
33
|
+
char filename[FILE_NAME_BUFFER_SIZE];
|
34
|
+
|
35
|
+
sprintf(filename, "/sys/class/gpio/gpio%d/direction", pinNumber);
|
36
|
+
|
37
|
+
GPIO_INTERNAL_getFileContent(filename, dst);
|
38
|
+
}
|
39
|
+
|
40
|
+
void GPIO_INTERNAL_set_direction(int pinNumber, char *content) {
|
41
|
+
char filename[FILE_NAME_BUFFER_SIZE];
|
42
|
+
|
43
|
+
sprintf(filename, "/sys/class/gpio/gpio%d/direction", pinNumber);
|
44
|
+
|
45
|
+
GPIO_INTERNAL_writeFileContent(filename, content, strlen(content));
|
46
|
+
}
|
@@ -0,0 +1,5 @@
|
|
1
|
+
void GPIO_INTERNAL_validate_pin(int pinNumber);
|
2
|
+
void GPIO_INTERNAL_get_value(int pinNumber, char *dst);
|
3
|
+
void GPIO_INTERNAL_set_value(int pinNumber, char *content);
|
4
|
+
void GPIO_INTERNAL_get_direction(int pinNumber, char *dst);
|
5
|
+
void GPIO_INTERNAL_set_direction(int pinNumber, char *content);
|
data/ext/c_gpio/led.c
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#ifndef __RUBY_H
|
2
|
+
#define __RUBY_H
|
3
|
+
#include <ruby.h>
|
4
|
+
#endif
|
5
|
+
|
6
|
+
#include "mount.h"
|
7
|
+
#include "base.h"
|
8
|
+
#include "led.h"
|
9
|
+
#include "internal.h"
|
10
|
+
#include "file_stuff.h"
|
11
|
+
|
12
|
+
|
13
|
+
VALUE GPIO_LED_init(VALUE self, VALUE port) {
|
14
|
+
struct GPIO *ptr;
|
15
|
+
int gpio_port = NUM2INT(port);
|
16
|
+
|
17
|
+
GPIO_INTERNAL_validate_pin(gpio_port);
|
18
|
+
|
19
|
+
pi_io_mountPin(gpio_port);
|
20
|
+
|
21
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
22
|
+
|
23
|
+
ptr->port = gpio_port;
|
24
|
+
|
25
|
+
GPIO_INTERNAL_set_direction(ptr->port, (char *) GPIO_OUT);
|
26
|
+
|
27
|
+
return self;
|
28
|
+
}
|
29
|
+
|
30
|
+
VALUE GPIO_LED_turn_on(VALUE self) {
|
31
|
+
struct GPIO *ptr;
|
32
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
33
|
+
|
34
|
+
GPIO_INTERNAL_set_value(ptr->port, (char *) GPIO_LOW);
|
35
|
+
|
36
|
+
return self;
|
37
|
+
}
|
38
|
+
|
39
|
+
VALUE GPIO_LED_turn_off(VALUE self) {
|
40
|
+
struct GPIO *ptr;
|
41
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
42
|
+
|
43
|
+
GPIO_INTERNAL_set_value(ptr->port, (char *) GPIO_HIGH);
|
44
|
+
|
45
|
+
return self;
|
46
|
+
}
|
data/ext/c_gpio/led.h
ADDED
data/ext/c_gpio/mount.c
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
#ifndef __RUBY_H
|
2
|
+
#define __RUBY_H
|
3
|
+
#include <ruby.h>
|
4
|
+
#endif
|
5
|
+
|
6
|
+
#include <fcntl.h>
|
7
|
+
#define BUFFER_SIZE 5
|
8
|
+
|
9
|
+
void pi_io_writeToMountFile(char *fileName, int content) {
|
10
|
+
int fd;
|
11
|
+
char buffer[BUFFER_SIZE];
|
12
|
+
ssize_t bytes_written;
|
13
|
+
|
14
|
+
fd = open(fileName, O_WRONLY);
|
15
|
+
if (-1 == fd) {
|
16
|
+
rb_raise(rb_eArgError, "Could not open GPIO connection - mounting GPIO pin not possible");
|
17
|
+
}
|
18
|
+
|
19
|
+
bytes_written = snprintf(buffer, BUFFER_SIZE, "%d", content);
|
20
|
+
write(fd, buffer, bytes_written);
|
21
|
+
|
22
|
+
close(fd);
|
23
|
+
}
|
24
|
+
|
25
|
+
void pi_io_mountPin(int pinNumber) {
|
26
|
+
pi_io_writeToMountFile((char*)"/sys/class/gpio/export", pinNumber);
|
27
|
+
|
28
|
+
char mountedPinDirection[40];
|
29
|
+
|
30
|
+
sprintf(mountedPinDirection, "/sys/class/gpio/gpio%d/direction", pinNumber);
|
31
|
+
|
32
|
+
int i;
|
33
|
+
for (i = 0; i < 10; i++) {
|
34
|
+
if( access( mountedPinDirection, W_OK ) != -1 ) {
|
35
|
+
// The pin is mounted, so we can return
|
36
|
+
return;
|
37
|
+
} else {
|
38
|
+
// The pin seems to be not mounted yet.
|
39
|
+
// so we wait 20ms and check again
|
40
|
+
usleep(20 * 1000);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
// If we reach this part, mounting in time was not possible
|
45
|
+
rb_raise(rb_eSystemCallError, "Was not able to mount GPIO pin");
|
46
|
+
}
|
47
|
+
|
48
|
+
void pi_io_unmountPin(int pinNumber) {
|
49
|
+
pi_io_writeToMountFile((char*)"/sys/class/gpio/unexport", pinNumber);
|
50
|
+
}
|
data/ext/c_gpio/mount.h
ADDED
data/ext/c_gpio/pwm.c
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#ifndef __RUBY_H
|
2
|
+
#define __RUBY_H
|
3
|
+
#include <ruby.h>
|
4
|
+
#endif
|
5
|
+
|
6
|
+
#include "mount.h"
|
7
|
+
#include "base.h"
|
8
|
+
#include "internal.h"
|
9
|
+
#include "file_stuff.h"
|
10
|
+
#include "pwm.h"
|
11
|
+
|
12
|
+
#include <pthread.h>
|
13
|
+
|
14
|
+
VALUE GPIO_PWM_init(VALUE self, VALUE port) {
|
15
|
+
struct GPIO *ptr;
|
16
|
+
int gpio_port = NUM2INT(port);
|
17
|
+
|
18
|
+
GPIO_INTERNAL_validate_pin(gpio_port);
|
19
|
+
|
20
|
+
pi_io_mountPin(gpio_port);
|
21
|
+
|
22
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
23
|
+
|
24
|
+
ptr->port = gpio_port;
|
25
|
+
|
26
|
+
GPIO_INTERNAL_set_direction(ptr->port, (char *) GPIO_OUT);
|
27
|
+
|
28
|
+
return self;
|
29
|
+
}
|
30
|
+
|
31
|
+
VALUE GPIO_PWM_position(VALUE self, VALUE vPosition) {
|
32
|
+
struct GPIO *ptr;
|
33
|
+
Data_Get_Struct(self, struct GPIO, ptr);
|
34
|
+
|
35
|
+
int position = NUM2INT(vPosition);
|
36
|
+
|
37
|
+
if(position < 0 || position > 200) {
|
38
|
+
rb_raise(rb_eArgError, "Argument must be between 0 and 200");
|
39
|
+
}
|
40
|
+
|
41
|
+
// Position 0 is not 0 but 30, and max is not 200 but 230
|
42
|
+
// Just for interface reasons, we accept values from 0 to 200
|
43
|
+
// But internally we have to add 30
|
44
|
+
ptr->pwmPosition = position + 30;
|
45
|
+
|
46
|
+
pthread_t myThread;
|
47
|
+
|
48
|
+
pthread_create(&myThread, NULL, &positioner, ptr);
|
49
|
+
|
50
|
+
return self;
|
51
|
+
}
|
52
|
+
|
53
|
+
|
54
|
+
void *positioner(void *ptr) {
|
55
|
+
|
56
|
+
struct GPIO *gpio = (struct GPIO *) ptr;
|
57
|
+
|
58
|
+
float duration = 40.0;
|
59
|
+
float uptime = gpio->pwmPosition / 100.0;
|
60
|
+
|
61
|
+
// We can not use while(1) atm, because this whole thing is that unprecise, that the stepper engine will start jittering
|
62
|
+
// while(1) {
|
63
|
+
// GPIO_INTERNAL_set_value(gpio->port, (char *) GPIO_HIGH);
|
64
|
+
// usleep(uptime * 1000);
|
65
|
+
// GPIO_INTERNAL_set_value(gpio->port, (char *) GPIO_LOW);
|
66
|
+
// usleep((duration - uptime) * 1000);
|
67
|
+
// }
|
68
|
+
|
69
|
+
int i;
|
70
|
+
for (i = 0; i < 35; i++) {
|
71
|
+
GPIO_INTERNAL_set_value(gpio->port, (char *) GPIO_HIGH);
|
72
|
+
|
73
|
+
usleep(uptime * 1000);
|
74
|
+
|
75
|
+
GPIO_INTERNAL_set_value(gpio->port, (char *) GPIO_LOW);
|
76
|
+
usleep((duration - uptime) * 1000);
|
77
|
+
}
|
78
|
+
|
79
|
+
return NULL;
|
80
|
+
}
|
data/ext/c_gpio/pwm.h
ADDED
data/lib/c_gpio.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: c_gpio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- hujiko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-06-
|
11
|
+
date: 2018-06-26 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Ruby gem to control GPIO ports of a raspberry PI
|
14
14
|
email:
|
@@ -18,7 +18,22 @@ extensions:
|
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
20
|
- README.md
|
21
|
+
- ext/c_gpio/base.c
|
22
|
+
- ext/c_gpio/base.h
|
23
|
+
- ext/c_gpio/button.c
|
24
|
+
- ext/c_gpio/button.h
|
21
25
|
- ext/c_gpio/extconf.rb
|
26
|
+
- ext/c_gpio/file_stuff.c
|
27
|
+
- ext/c_gpio/file_stuff.h
|
28
|
+
- ext/c_gpio/gpio.c
|
29
|
+
- ext/c_gpio/internal.c
|
30
|
+
- ext/c_gpio/internal.h
|
31
|
+
- ext/c_gpio/led.c
|
32
|
+
- ext/c_gpio/led.h
|
33
|
+
- ext/c_gpio/mount.c
|
34
|
+
- ext/c_gpio/mount.h
|
35
|
+
- ext/c_gpio/pwm.c
|
36
|
+
- ext/c_gpio/pwm.h
|
22
37
|
- lib/c_gpio.rb
|
23
38
|
homepage: https://github.com/hujiko/c_GPIO
|
24
39
|
licenses:
|