c_gpio 0.0.6 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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:
|