rpi_gpio 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,55 @@
1
+ /*
2
+ Original code by Ben Croston modified for Ruby by Nick Lowery
3
+ (github.com/clockvapor)
4
+ Copyright (c) 2014-2020 Nick Lowery
5
+
6
+ Copyright (c) 2013-2015 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
+ int setup(void);
28
+ void setup_gpio(int gpio, int direction, int pud);
29
+ int gpio_function(int gpio);
30
+ void output_gpio(int gpio, int value);
31
+ int input_gpio(int gpio);
32
+ void set_rising_event(int gpio, int enable);
33
+ void set_falling_event(int gpio, int enable);
34
+ void set_high_event(int gpio, int enable);
35
+ void set_low_event(int gpio, int enable);
36
+ int eventdetected(int gpio);
37
+ void cleanup(void);
38
+
39
+ #define SETUP_OK 0
40
+ #define SETUP_DEVMEM_FAIL 1
41
+ #define SETUP_MALLOC_FAIL 2
42
+ #define SETUP_MMAP_FAIL 3
43
+ #define SETUP_CPUINFO_FAIL 4
44
+ #define SETUP_NOT_RPI_FAIL 5
45
+
46
+ #define INPUT 1 // is really 0 for control register!
47
+ #define OUTPUT 0 // is really 1 for control register!
48
+ #define ALT0 4
49
+
50
+ #define HIGH 1
51
+ #define LOW 0
52
+
53
+ #define PUD_OFF 0
54
+ #define PUD_DOWN 1
55
+ #define PUD_UP 2
@@ -0,0 +1,93 @@
1
+ /*
2
+ Original code by Ben Croston modified for Ruby by Nick Lowery
3
+ (github.com/clockvapor)
4
+ Copyright (c) 2014-2020 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 "common.h"
30
+
31
+ int gpio_mode = MODE_UNKNOWN;
32
+ const int pin_to_gpio_rev1[41] = {-1, -1, -1, 0, -1, 1, -1, 4, 14, -1, 15, 17, 18, 21, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
33
+ const int pin_to_gpio_rev2[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
34
+ const int pin_to_gpio_rev3[41] = {-1, -1, -1, 2, -1, 3, -1, 4, 14, -1, 15, 17, 18, 27, -1, 22, 23, -1, 24, 10, -1, 9, 25, 11, 8, -1, 7, -1, -1, 5, -1, 6, 12, 13, -1, 19, 16, 26, 20, -1, 21 };
35
+ int setup_error = 0;
36
+ int module_setup = 0;
37
+
38
+ int check_gpio_priv(void)
39
+ {
40
+ // check module has been imported cleanly
41
+ if (setup_error)
42
+ {
43
+ rb_raise(rb_eRuntimeError, "gem not imported correctly!");
44
+ return 1;
45
+ }
46
+
47
+ // check mmap setup has worked
48
+ if (!module_setup)
49
+ {
50
+ rb_raise(rb_eRuntimeError, "no access to /dev/mem. Try running as root!");
51
+ return 2;
52
+ }
53
+ return 0;
54
+ }
55
+
56
+ int get_gpio_number(int channel, unsigned int *gpio)
57
+ {
58
+ // check setmode() has been run
59
+ if (gpio_mode != BOARD && gpio_mode != BCM)
60
+ {
61
+ rb_raise(rb_eRuntimeError, "please set pin numbering mode "
62
+ "using RPi::GPIO.set_numbering :board or "
63
+ "RPi::GPIO.set_numbering :bcm");
64
+ return 3;
65
+ }
66
+
67
+ // check channel number is in range
68
+ if ( (gpio_mode == BCM && (channel < 0 || channel > 53))
69
+ || (gpio_mode == BOARD && (channel < 1 || channel > 26) && rpiinfo.p1_revision != 3)
70
+ || (gpio_mode == BOARD && (channel < 1 || channel > 40) && rpiinfo.p1_revision == 3) )
71
+ {
72
+ rb_raise(rb_eArgError, "the channel sent is invalid on a Raspberry Pi");
73
+ return 4;
74
+ }
75
+
76
+ // convert channel to gpio
77
+ if (gpio_mode == BOARD)
78
+ {
79
+ if (*(*pin_to_gpio+channel) == -1)
80
+ {
81
+ rb_raise(rb_eArgError, "the channel sent is invalid on a Raspberry Pi");
82
+ return 5;
83
+ } else {
84
+ *gpio = *(*pin_to_gpio+channel);
85
+ }
86
+ }
87
+ else // gpio_mode == BCM
88
+ {
89
+ *gpio = channel;
90
+ }
91
+
92
+ return 0;
93
+ }
@@ -0,0 +1,47 @@
1
+ /*
2
+ Original code by Ben Croston modified for Ruby by Nick Lowery
3
+ (github.com/clockvapor)
4
+ Copyright (c) 2014-2020 Nick Lowery
5
+
6
+ Copyright (c) 2013-2015 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 "cpuinfo.h"
28
+
29
+ #define MODE_UNKNOWN -1
30
+ #define BOARD 10
31
+ #define BCM 11
32
+ #define SERIAL 40
33
+ #define SPI 41
34
+ #define I2C 42
35
+ #define PWM 43
36
+
37
+ int gpio_mode;
38
+ const int pin_to_gpio_rev1[41];
39
+ const int pin_to_gpio_rev2[41];
40
+ const int pin_to_gpio_rev3[41];
41
+ const int (*pin_to_gpio)[41];
42
+ int gpio_direction[54];
43
+ rpi_info rpiinfo;
44
+ int setup_error;
45
+ int module_setup;
46
+ int check_gpio_priv(void);
47
+ int get_gpio_number(int channel, unsigned int *gpio);
@@ -0,0 +1,272 @@
1
+ /*
2
+ Original code by Ben Croston modified for Ruby by Nick Lowery
3
+ (github.com/clockvapor)
4
+ Copyright (c) 2014-2020 Nick Lowery
5
+
6
+ Copyright (c) 2012-2019 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
+ /* See the following for up to date information:
28
+ * https://www.raspberrypi.org/documentation/hardware/raspberrypi/revision-codes/README.md
29
+ */
30
+
31
+ #include <stdio.h>
32
+ #include <stdint.h>
33
+ #include <stdlib.h>
34
+ #include <string.h>
35
+ #include <arpa/inet.h>
36
+ #include "cpuinfo.h"
37
+
38
+ int get_rpi_info(rpi_info *info)
39
+ {
40
+ FILE *fp;
41
+ char buffer[1024];
42
+ char hardware[1024];
43
+ char revision[1024];
44
+ int found = 0;
45
+ int len;
46
+
47
+ if ((fp = fopen("/proc/device-tree/system/linux,revision", "r"))) {
48
+ uint32_t n;
49
+ if (fread(&n, sizeof(n), 1, fp) != 1) {
50
+ fclose(fp);
51
+ return -1;
52
+ }
53
+ sprintf(revision, "%x", ntohl(n));
54
+ found = 1;
55
+ }
56
+ else if ((fp = fopen("/proc/cpuinfo", "r"))) {
57
+ while(!feof(fp) && fgets(buffer, sizeof(buffer), fp)) {
58
+ sscanf(buffer, "Hardware : %s", hardware);
59
+ if (strcmp(hardware, "BCM2708") == 0 ||
60
+ strcmp(hardware, "BCM2709") == 0 ||
61
+ strcmp(hardware, "BCM2835") == 0 ||
62
+ strcmp(hardware, "BCM2836") == 0 ||
63
+ strcmp(hardware, "BCM2837") == 0 ) {
64
+ found = 1;
65
+ }
66
+ sscanf(buffer, "Revision : %s", revision);
67
+ }
68
+ }
69
+ else
70
+ return -1;
71
+ fclose(fp);
72
+
73
+ if (!found)
74
+ return -1;
75
+
76
+ if ((len = strlen(revision)) == 0)
77
+ return -1;
78
+
79
+ if (len >= 6 && strtol((char[]){revision[len-6],0}, NULL, 16) & 8) {
80
+ // new scheme
81
+ //info->rev = revision[len-1]-'0';
82
+ strcpy(info->revision, revision);
83
+ switch (revision[len-3]) {
84
+ case '0' :
85
+ switch (revision[len-2]) {
86
+ case '0': info->type = "Model A"; info->p1_revision = 2; break;
87
+ case '1': info->type = "Model B"; info->p1_revision = 2; break;
88
+ case '2': info->type = "Model A+"; info->p1_revision = 3; break;
89
+ case '3': info->type = "Model B+"; info->p1_revision = 3; break;
90
+ case '4': info->type = "Pi 2 Model B"; info->p1_revision = 3; break;
91
+ case '5': info->type = "Alpha"; info->p1_revision = 3; break;
92
+ case '6': info->type = "Compute Module 1"; info->p1_revision = 0; break;
93
+ case '8': info->type = "Pi 3 Model B"; info->p1_revision = 3; break;
94
+ case '9': info->type = "Zero"; info->p1_revision = 3; break;
95
+ case 'a': info->type = "Compute Module 3"; info->p1_revision = 0; break;
96
+ case 'c': info->type = "Zero W"; info->p1_revision = 3; break;
97
+ case 'd': info->type = "Pi 3 Model B+"; info->p1_revision = 3; break;
98
+ case 'e': info->type = "Pi 3 Model A+"; info->p1_revision = 3; break;
99
+ default : info->type = "Unknown"; info->p1_revision = 3; break;
100
+ } break;
101
+ case '1':
102
+ switch (revision[len-2]) {
103
+ case '0': info->type = "Compute Module 3+"; info->p1_revision = 0; break;
104
+ case '1': info->type = "Pi 4 Model B"; info->p1_revision = 3; break;
105
+ default : info->type = "Unknown"; info->p1_revision = 3; break;
106
+ } break;
107
+ default: info->type = "Unknown"; info->p1_revision = 3; break;
108
+ }
109
+
110
+ switch (revision[len-4]) {
111
+ case '0': info->processor = "BCM2835"; break;
112
+ case '1': info->processor = "BCM2836"; break;
113
+ case '2': info->processor = "BCM2837"; break;
114
+ case '3': info->processor = "BCM2711"; break;
115
+ default : info->processor = "Unknown"; break;
116
+ }
117
+ switch (revision[len-5]) {
118
+ case '0': info->manufacturer = "Sony"; break;
119
+ case '1': info->manufacturer = "Egoman"; break;
120
+ case '2': info->manufacturer = "Embest"; break;
121
+ case '3': info->manufacturer = "Sony Japan"; break;
122
+ case '4': info->manufacturer = "Embest"; break;
123
+ case '5': info->manufacturer = "Stadium"; break;
124
+ default : info->manufacturer = "Unknown"; break;
125
+ }
126
+ switch (strtol((char[]){revision[len-6],0}, NULL, 16) & 7) {
127
+ case 0: info->ram = "256M"; break;
128
+ case 1: info->ram = "512M"; break;
129
+ case 2: info->ram = "1G"; break;
130
+ case 3: info->ram = "2G"; break;
131
+ case 4: info->ram = "4G"; break;
132
+ default: info->ram = "Unknown"; break;
133
+ }
134
+ } else {
135
+ // old scheme
136
+ info->ram = "Unknown";
137
+ info->manufacturer = "Unknown";
138
+ info->processor = "Unknown";
139
+ info->type = "Unknown";
140
+ strcpy(info->revision, revision);
141
+
142
+ uint64_t rev;
143
+ sscanf(revision, "%llx", &rev);
144
+ rev = rev & 0xefffffff; // ignore preceeding 1000 for overvolt
145
+
146
+ if (rev == 0x0002 || rev == 0x0003) {
147
+ info->type = "Model B";
148
+ info->p1_revision = 1;
149
+ info->ram = "256M";
150
+ info->manufacturer = "Egoman";
151
+ info->processor = "BCM2835";
152
+ } else if (rev == 0x0004) {
153
+ info->type = "Model B";
154
+ info->p1_revision = 2;
155
+ info->ram = "256M";
156
+ info->manufacturer = "Sony UK";
157
+ info->processor = "BCM2835";
158
+ } else if (rev == 0x0005) {
159
+ info->type = "Model B";
160
+ info->p1_revision = 2;
161
+ info->ram = "256M";
162
+ info->manufacturer = "Qisda";
163
+ info->processor = "BCM2835";
164
+ } else if (rev == 0x0006) {
165
+ info->type = "Model B";
166
+ info->p1_revision = 2;
167
+ info->ram = "256M";
168
+ info->manufacturer = "Egoman";
169
+ info->processor = "BCM2835";
170
+ } else if (rev == 0x0007) {
171
+ info->type = "Model A";
172
+ info->p1_revision = 2;
173
+ info->ram = "256M";
174
+ info->manufacturer = "Egoman";
175
+ info->processor = "BCM2835";
176
+ } else if (rev == 0x0008) {
177
+ info->type = "Model A";
178
+ info->p1_revision = 2;
179
+ info->ram = "256M";
180
+ info->manufacturer = "Sony UK";
181
+ info->processor = "BCM2835";
182
+ } else if (rev == 0x0009) {
183
+ info->type = "Model A";
184
+ info->p1_revision = 2;
185
+ info->ram = "256M";
186
+ info->manufacturer = "Qisda";
187
+ info->processor = "BCM2835";
188
+ } else if (rev == 0x000d) {
189
+ info->type = "Model B";
190
+ info->p1_revision = 2;
191
+ info->ram = "512M";
192
+ info->manufacturer = "Egoman";
193
+ info->processor = "BCM2835";
194
+ } else if (rev == 0x000e) {
195
+ info->type = "Model B";
196
+ info->p1_revision = 2;
197
+ info->ram = "512M";
198
+ info->manufacturer = "Sony UK";
199
+ info->processor = "BCM2835";
200
+ } else if (rev == 0x000f) {
201
+ info->type = "Model B";
202
+ info->p1_revision = 2;
203
+ info->ram = "512M";
204
+ info->manufacturer = "Qisda";
205
+ info->processor = "BCM2835";
206
+ } else if (rev == 0x0010) {
207
+ info->type = "Model B+";
208
+ info->p1_revision = 3;
209
+ info->ram = "512M";
210
+ info->manufacturer = "Sony UK";
211
+ info->processor = "BCM2835";
212
+ } else if (rev == 0x0011) {
213
+ info->type = "Compute Module 1";
214
+ info->p1_revision = 0;
215
+ info->ram = "512M";
216
+ info->manufacturer = "Sony UK";
217
+ info->processor = "BCM2835";
218
+ } else if (rev == 0x0012) {
219
+ info->type = "Model A+";
220
+ info->p1_revision = 3;
221
+ info->ram = "256M";
222
+ info->manufacturer = "Sony UK";
223
+ info->processor = "BCM2835";
224
+ } else if (rev == 0x0013) {
225
+ info->type = "Model B+";
226
+ info->p1_revision = 3;
227
+ info->ram = "512M";
228
+ info->manufacturer = "Embest";
229
+ info->processor = "BCM2835";
230
+ } else if (rev == 0x0014) {
231
+ info->type = "Compute Module 1";
232
+ info->p1_revision = 0;
233
+ info->ram = "512M";
234
+ info->manufacturer = "Embest";
235
+ info->processor = "BCM2835";
236
+ } else if (rev == 0x0015) {
237
+ info->type = "Model A+";
238
+ info->p1_revision = 3;
239
+ info->ram = "Unknown";
240
+ info->manufacturer = "Embest";
241
+ info->processor = "BCM2835";
242
+ } else { // don't know - assume revision 3 p1 connector
243
+ info->p1_revision = 3;
244
+ }
245
+ }
246
+ return 0;
247
+ }
248
+
249
+ /*
250
+
251
+ 32 bits
252
+ NEW 23: will be 1 for the new scheme, 0 for the old scheme
253
+ MEMSIZE 20: 0=256M 1=512M 2=1G
254
+ MANUFACTURER 16: 0=SONY 1=EGOMAN
255
+ PROCESSOR 12: 0=2835 1=2836
256
+ TYPE 04: 0=MODELA 1=MODELB 2=MODELA+ 3=MODELB+ 4=Pi2 MODEL B 5=ALPHA 6=CM
257
+ REV 00: 0=REV0 1=REV1 2=REV2
258
+
259
+ pi2 = 1<<23 | 2<<20 | 1<<12 | 4<<4 = 0xa01040
260
+
261
+ --------------------
262
+
263
+ SRRR MMMM PPPP TTTT TTTT VVVV
264
+
265
+ S scheme (0=old, 1=new)
266
+ R RAM (0=256, 1=512, 2=1024)
267
+ M manufacturer (0='SONY',1='EGOMAN',2='EMBEST',3='UNKNOWN',4='EMBEST')
268
+ P processor (0=2835, 1=2836 2=2837)
269
+ T type (0='A', 1='B', 2='A+', 3='B+', 4='Pi 2 B', 5='Alpha', 6='Compute Module')
270
+ V revision (0-15)
271
+
272
+ */