summaryrefslogtreecommitdiffstats
path: root/python/native/bridge.c
diff options
context:
space:
mode:
Diffstat (limited to 'python/native/bridge.c')
-rw-r--r--python/native/bridge.c720
1 files changed, 720 insertions, 0 deletions
diff --git a/python/native/bridge.c b/python/native/bridge.c
new file mode 100644
index 0000000..8b2b8da
--- /dev/null
+++ b/python/native/bridge.c
@@ -0,0 +1,720 @@
1/*
2Copyright (c) 2012 Ben Croston / 2012-2013 Eric PTAK
3
4Permission is hereby granted, free of charge, to any person obtaining a copy of
5this software and associated documentation files (the "Software"), to deal in
6the Software without restriction, including without limitation the rights to
7use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
8of the Software, and to permit persons to whom the Software is furnished to do
9so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in all
12copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20SOFTWARE.
21*/
22
23#include "Python.h"
24#include "gpio.h"
25#include "cpuinfo.h"
26
27static PyObject *_SetupException;
28static PyObject *_InvalidDirectionException;
29static PyObject *_InvalidChannelException;
30static PyObject *_InvalidPullException;
31
32static PyObject *_gpioCount;
33
34
35static PyObject *_low;
36static PyObject *_high;
37
38static PyObject *_in;
39static PyObject *_out;
40static PyObject *_alt0;
41static PyObject *_alt1;
42static PyObject *_alt2;
43static PyObject *_alt3;
44static PyObject *_alt4;
45static PyObject *_alt5;
46static PyObject *_pwm;
47
48static PyObject *_pud_off;
49static PyObject *_pud_up;
50static PyObject *_pud_down;
51
52static PyObject *_board_revision;
53
54static char* FUNCTIONS[] = {"IN", "OUT", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3", "PWM"};
55static char* PWM_MODES[] = {"none", "ratio", "angle"};
56
57static int module_state = -1;
58
59// setup function run on import of the RPi.GPIO module
60static int module_setup(void)
61{
62 if (module_state == SETUP_OK) {
63 return SETUP_OK;
64 }
65
66 module_state = setup();
67 if (module_state == SETUP_DEVMEM_FAIL)
68 {
69 PyErr_SetString(_SetupException, "No access to /dev/mem. Try running as root!");
70 } else if (module_state == SETUP_MALLOC_FAIL) {
71 PyErr_NoMemory();
72 } else if (module_state == SETUP_MMAP_FAIL) {
73 PyErr_SetString(_SetupException, "Mmap failed on module import");
74 }
75
76 return module_state;
77}
78
79// python function getFunction(channel)
80static PyObject *py_get_function(PyObject *self, PyObject *args)
81{
82 if (module_setup() != SETUP_OK) {
83 return NULL;
84 }
85
86 int channel, f;
87
88 if (!PyArg_ParseTuple(args, "i", &channel))
89 return NULL;
90
91 if (channel < 0 || channel >= GPIO_COUNT)
92 {
93 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
94 return NULL;
95 }
96
97 f = get_function(channel);
98 return Py_BuildValue("i", f);
99}
100
101// python function getFunctionString(channel)
102static PyObject *py_get_function_string(PyObject *self, PyObject *args)
103{
104 if (module_setup() != SETUP_OK) {
105 return NULL;
106 }
107
108 int channel, f;
109 char *str;
110
111 if (!PyArg_ParseTuple(args, "i", &channel))
112 return NULL;
113
114 if (channel < 0 || channel >= GPIO_COUNT)
115 {
116 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
117 return NULL;
118 }
119
120 f = get_function(channel);
121 str = FUNCTIONS[f];
122 return Py_BuildValue("s", str);
123}
124
125// python function setFunction(channel, direction, pull_up_down=PUD_OFF)
126static PyObject *py_set_function(PyObject *self, PyObject *args, PyObject *kwargs)
127{
128 if (module_setup() != SETUP_OK) {
129 return NULL;
130 }
131
132 int channel, function;
133 int pud = PUD_OFF;
134 static char *kwlist[] = {"channel", "function", "pull_up_down", NULL};
135
136 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii|i", kwlist, &channel, &function, &pud))
137 return NULL;
138
139 if (function != IN && function != OUT && function != PWM)
140 {
141 PyErr_SetString(_InvalidDirectionException, "Invalid function");
142 return NULL;
143 }
144
145 if (function == OUT || function == PWM)
146 pud = PUD_OFF;
147
148 if (pud != PUD_OFF && pud != PUD_DOWN && pud != PUD_UP)
149 {
150 PyErr_SetString(_InvalidPullException, "Invalid value for pull_up_down - should be either PUD_OFF, PUD_UP or PUD_DOWN");
151 return NULL;
152 }
153
154 if (channel < 0 || channel >= GPIO_COUNT)
155 {
156 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
157 return NULL;
158 }
159
160 set_function(channel, function, pud);
161
162 Py_INCREF(Py_None);
163 return Py_None;
164}
165
166// python function value = input(channel)
167static PyObject *py_input(PyObject *self, PyObject *args)
168{
169 if (module_setup() != SETUP_OK) {
170 return NULL;
171 }
172
173 int channel;
174
175 if (!PyArg_ParseTuple(args, "i", &channel))
176 return NULL;
177
178 if (channel < 0 || channel >= GPIO_COUNT)
179 {
180 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
181 return NULL;
182 }
183
184 if (input(channel))
185 Py_RETURN_TRUE;
186 else
187 Py_RETURN_FALSE;
188}
189
190// python function output(channel, value)
191static PyObject *py_output(PyObject *self, PyObject *args, PyObject *kwargs)
192{
193 if (module_setup() != SETUP_OK) {
194 return NULL;
195 }
196
197 int channel, value;
198 static char *kwlist[] = {"channel", "value", NULL};
199
200 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "ii", kwlist, &channel, &value))
201 return NULL;
202
203 if (channel < 0 || channel >= GPIO_COUNT)
204 {
205 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
206 return NULL;
207 }
208
209 if (get_function(channel) != OUT)
210 {
211 PyErr_SetString(_InvalidDirectionException, "The GPIO channel is not an OUTPUT");
212 return NULL;
213 }
214
215 output(channel, value);
216
217 Py_INCREF(Py_None);
218 return Py_None;
219}
220
221// python function outputSequence(channel, period, sequence)
222static PyObject *py_output_sequence(PyObject *self, PyObject *args, PyObject *kwargs)
223{
224 if (module_setup() != SETUP_OK) {
225 return NULL;
226 }
227
228 int channel, period;
229 char* sequence;
230 static char *kwlist[] = {"channel", "period", "sequence", NULL};
231
232 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iis", kwlist, &channel, &period, &sequence))
233 return NULL;
234
235 if (channel < 0 || channel >= GPIO_COUNT)
236 {
237 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
238 return NULL;
239 }
240
241 if (get_function(channel) != OUT)
242 {
243 PyErr_SetString(_InvalidDirectionException, "The GPIO channel is not an OUTPUT");
244 return NULL;
245 }
246
247 outputSequence(channel, period, sequence);
248
249 Py_INCREF(Py_None);
250 return Py_None;
251}
252
253
254static PyObject *py_pulseMilli(PyObject *self, PyObject *args, PyObject *kwargs)
255{
256 if (module_setup() != SETUP_OK) {
257 return NULL;
258 }
259
260 int channel, function, up, down;
261 static char *kwlist[] = {"channel", "up", "down", NULL};
262
263 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii", kwlist, &channel, &up, &down))
264 return NULL;
265
266 if (channel < 0 || channel >= GPIO_COUNT)
267 {
268 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
269 return NULL;
270 }
271
272 function = get_function(channel);
273 if ((function != OUT) && (function != PWM))
274 {
275 PyErr_SetString(_InvalidDirectionException, "The GPIO channel is not an OUTPUT or PWM");
276 return NULL;
277 }
278
279 pulseMilli(channel, up, down);
280
281 Py_INCREF(Py_None);
282 return Py_None;
283}
284
285
286static PyObject *py_pulseMilliRatio(PyObject *self, PyObject *args, PyObject *kwargs)
287{
288 if (module_setup() != SETUP_OK) {
289 return NULL;
290 }
291
292 int channel, function, width;
293 float ratio;
294 static char *kwlist[] = {"channel", "width", "ratio", NULL};
295
296 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iif", kwlist, &channel, &width, &ratio))
297 return NULL;
298
299 if (channel < 0 || channel >= GPIO_COUNT)
300 {
301 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
302 return NULL;
303 }
304
305 function = get_function(channel);
306 if ((function != OUT) && (function != PWM))
307 {
308 PyErr_SetString(_InvalidDirectionException, "The GPIO channel is not an OUTPUT or PWM");
309 return NULL;
310 }
311
312 pulseMilliRatio(channel, width, ratio);
313
314 Py_INCREF(Py_None);
315 return Py_None;
316}
317
318
319static PyObject *py_pulseMicro(PyObject *self, PyObject *args, PyObject *kwargs)
320{
321 if (module_setup() != SETUP_OK) {
322 return NULL;
323 }
324
325 int channel, function, up, down;
326 static char *kwlist[] = {"channel", "up", "down", NULL};
327
328 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iii", kwlist, &channel, &up, &down))
329 return NULL;
330
331 if (channel < 0 || channel >= GPIO_COUNT)
332 {
333 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
334 return NULL;
335 }
336
337 function = get_function(channel);
338 if ((function != OUT) && (function != PWM))
339 {
340 PyErr_SetString(_InvalidDirectionException, "The GPIO channel is not an OUTPUT or PWM");
341 return NULL;
342 }
343
344 pulseMicro(channel, up, down);
345
346 Py_INCREF(Py_None);
347 return Py_None;
348}
349
350static PyObject *py_pulseMicroRatio(PyObject *self, PyObject *args, PyObject *kwargs)
351{
352 if (module_setup() != SETUP_OK) {
353 return NULL;
354 }
355
356 int channel, function, width;
357 float ratio;
358 static char *kwlist[] = {"channel", "width", "ratio", NULL};
359
360 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "iif", kwlist, &channel, &width, &ratio))
361 return NULL;
362
363 if (channel < 0 || channel >= GPIO_COUNT)
364 {
365 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
366 return NULL;
367 }
368
369 function = get_function(channel);
370 if ((function != OUT) && (function != PWM))
371 {
372 PyErr_SetString(_InvalidDirectionException, "The GPIO channel is not an OUTPUT or PWM");
373 return NULL;
374 }
375
376 pulseMicroRatio(channel, width, ratio);
377
378 Py_INCREF(Py_None);
379 return Py_None;
380}
381
382static PyObject *py_pulseAngle(PyObject *self, PyObject *args, PyObject *kwargs)
383{
384 if (module_setup() != SETUP_OK) {
385 return NULL;
386 }
387
388 int channel, function;
389 float angle;
390 static char *kwlist[] = {"channel", "angle", NULL};
391
392 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "if", kwlist, &channel, &angle))
393 return NULL;
394
395 if (channel < 0 || channel >= GPIO_COUNT)
396 {
397 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
398 return NULL;
399 }
400
401 function = get_function(channel);
402 if ((function != OUT) && (function != PWM))
403 {
404 PyErr_SetString(_InvalidDirectionException, "The GPIO channel is not an OUTPUT or PWM");
405 return NULL;
406 }
407
408 pulseAngle(channel, angle);
409
410 Py_INCREF(Py_None);
411 return Py_None;
412}
413
414static PyObject *py_pulseRatio(PyObject *self, PyObject *args, PyObject *kwargs)
415{
416 if (module_setup() != SETUP_OK) {
417 return NULL;
418 }
419
420 int channel, function;
421 float ratio;
422 static char *kwlist[] = {"channel", "ratio", NULL};
423
424 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "if", kwlist, &channel, &ratio))
425 return NULL;
426
427 if (channel < 0 || channel >= GPIO_COUNT)
428 {
429 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
430 return NULL;
431 }
432
433 function = get_function(channel);
434 if ((function != OUT) && (function != PWM))
435 {
436 PyErr_SetString(_InvalidDirectionException, "The GPIO channel is not an OUTPUT or PWM");
437 return NULL;
438 }
439
440 pulseRatio(channel, ratio);
441
442 Py_INCREF(Py_None);
443 return Py_None;
444}
445
446static PyObject *py_pulse(PyObject *self, PyObject *args)
447{
448 if (module_setup() != SETUP_OK) {
449 return NULL;
450 }
451
452 int channel;
453
454 if (!PyArg_ParseTuple(args, "i", &channel))
455 return NULL;
456
457 if (channel < 0 || channel >= GPIO_COUNT)
458 {
459 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
460 return NULL;
461 }
462
463 pulseRatio(channel, 0.5);
464 return Py_None;
465}
466
467static PyObject *py_getPulse(PyObject *self, PyObject *args)
468{
469 if (module_setup() != SETUP_OK) {
470 return NULL;
471 }
472
473 int channel;
474 char str[256];
475 struct pulse *p;
476
477 if (!PyArg_ParseTuple(args, "i", &channel))
478 return NULL;
479
480 if (channel < 0 || channel >= GPIO_COUNT)
481 {
482 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
483 return NULL;
484 }
485
486 p = getPulse(channel);
487
488 sprintf(str, "%s:%.2f", PWM_MODES[p->type], p->value);
489#if PY_MAJOR_VERSION > 2
490 return PyUnicode_FromString(str);
491#else
492 return PyString_FromString(str);
493#endif
494}
495
496static PyObject *py_enablePWM(PyObject *self, PyObject *args)
497{
498 if (module_setup() != SETUP_OK) {
499 return NULL;
500 }
501
502 int channel;
503
504 if (!PyArg_ParseTuple(args, "i", &channel))
505 return NULL;
506
507 if (channel < 0 || channel >= GPIO_COUNT)
508 {
509 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
510 return NULL;
511 }
512
513 enablePWM(channel);
514 return Py_None;
515}
516
517static PyObject *py_disablePWM(PyObject *self, PyObject *args)
518{
519 if (module_setup() != SETUP_OK) {
520 return NULL;
521 }
522
523 int channel;
524
525 if (!PyArg_ParseTuple(args, "i", &channel))
526 return NULL;
527
528 if (channel < 0 || channel >= GPIO_COUNT)
529 {
530 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
531 return NULL;
532 }
533
534 disablePWM(channel);
535 return Py_None;
536}
537
538
539
540static PyObject *py_isPWMEnabled(PyObject *self, PyObject *args)
541{
542 if (module_setup() != SETUP_OK) {
543 return NULL;
544 }
545
546 int channel;
547
548 if (!PyArg_ParseTuple(args, "i", &channel))
549 return NULL;
550
551 if (channel < 0 || channel >= GPIO_COUNT)
552 {
553 PyErr_SetString(_InvalidChannelException, "The GPIO channel is invalid");
554 return NULL;
555 }
556
557 if (isPWMEnabled(channel))
558 Py_RETURN_TRUE;
559 else
560 Py_RETURN_FALSE;
561}
562
563PyMethodDef python_methods[] = {
564 {"getFunction", py_get_function, METH_VARARGS, "Return the current GPIO setup (IN, OUT, ALT0)"},
565 {"getSetup", py_get_function, METH_VARARGS, "Return the current GPIO setup (IN, OUT, ALT0)"},
566
567 {"getFunctionString", py_get_function_string, METH_VARARGS, "Return the current GPIO setup (IN, OUT, ALT0) as string"},
568 {"getSetupString", py_get_function_string, METH_VARARGS, "Return the current GPIO setup (IN, OUT, ALT0) as string"},
569
570 {"setFunction", (PyCFunction)py_set_function, METH_VARARGS | METH_KEYWORDS, "Setup the GPIO channel, direction and (optional) pull/up down control\nchannel - BCM GPIO number\ndirection - IN or OUT\n[pull_up_down] - PUD_OFF (default), PUD_UP or PUD_DOWN"},
571 {"setup", (PyCFunction)py_set_function, METH_VARARGS | METH_KEYWORDS, "Setup the GPIO channel, direction and (optional) pull/up down control\nchannel - BCM GPIO number\ndirection - IN or OUT\n[pull_up_down] - PUD_OFF (default), PUD_UP or PUD_DOWN"},
572
573 {"input", py_input, METH_VARARGS, "Input from a GPIO channel - Deprecated, use digitalRead instead"},
574 {"digitalRead", py_input, METH_VARARGS, "Read a GPIO channel"},
575
576 {"output", (PyCFunction)py_output, METH_VARARGS | METH_KEYWORDS, "Output to a GPIO channel - Deprecated, use digitalWrite instead"},
577 {"digitalWrite", (PyCFunction)py_output, METH_VARARGS | METH_KEYWORDS, "Write to a GPIO channel"},
578
579 {"outputSequence", (PyCFunction)py_output_sequence, METH_VARARGS | METH_KEYWORDS, "Output a sequence to a GPIO channel"},
580
581 {"getPulse", py_getPulse, METH_VARARGS, "Read current PWM output"},
582 {"pwmRead", py_getPulse, METH_VARARGS, "Read current PWM output"},
583
584 {"pulseMilli", (PyCFunction)py_pulseMilli, METH_VARARGS | METH_KEYWORDS, "Output a PWM to a GPIO channel using milliseconds for both HIGH and LOW state widths"},
585 {"pulseMilliRatio", (PyCFunction)py_pulseMilliRatio, METH_VARARGS | METH_KEYWORDS, "Output a PWM to a GPIO channel using millisecond for the total width and a ratio (duty cycle) for the HIGH state width"},
586 {"pulseMicro", (PyCFunction)py_pulseMicro, METH_VARARGS | METH_KEYWORDS, "Output a PWM pulse to a GPIO channel using microseconds for both HIGH and LOW state widths"},
587 {"pulseMicroRatio", (PyCFunction)py_pulseMicroRatio, METH_VARARGS | METH_KEYWORDS, "Output a PWM to a GPIO channel using microseconds for the total width and a ratio (duty cycle) for the HIGH state width"},
588
589 {"pulseAngle", (PyCFunction)py_pulseAngle, METH_VARARGS | METH_KEYWORDS, "Output a PWM to a GPIO channel using an angle - Deprecated, use pwmWriteAngle instead"},
590 {"pwmWriteAngle", (PyCFunction)py_pulseAngle, METH_VARARGS | METH_KEYWORDS, "Output a PWM to a GPIO channel using an angle"},
591
592 {"pulseRatio", (PyCFunction)py_pulseRatio, METH_VARARGS | METH_KEYWORDS, "Output a PWM to a GPIO channel using a ratio (duty cycle) with the default 50Hz signal - Deprecated, use pwmWrite instead"},
593 {"pwmWrite", (PyCFunction)py_pulseRatio, METH_VARARGS | METH_KEYWORDS, "Output a PWM to a GPIO channel using a ratio (duty cycle) with the default 50Hz signal"},
594
595 {"pulse", py_pulse, METH_VARARGS, "Output a PWM to a GPIO channel using a 50% ratio (duty cycle) with the default 50Hz signal"},
596
597 {"enablePWM", py_enablePWM, METH_VARARGS, "Enable software PWM loop for a GPIO channel"},
598 {"disablePWM", py_disablePWM, METH_VARARGS, "Disable software PWM loop of a GPIO channel"},
599 {"isPWMEnabled", py_isPWMEnabled, METH_VARARGS, "Returns software PWM state"},
600
601 {NULL, NULL, 0, NULL}
602};
603
604#if PY_MAJOR_VERSION > 2
605static struct PyModuleDef python_module = {
606 PyModuleDef_HEAD_INIT,
607 "_webiopi.GPIO", /* name of module */
608 NULL, /* module documentation, may be NULL */
609 -1, /* size of per-interpreter state of the module,
610 or -1 if the module keeps state in global variables. */
611 python_methods
612};
613#endif
614
615#if PY_MAJOR_VERSION > 2
616PyMODINIT_FUNC PyInit_GPIO(void)
617#else
618PyMODINIT_FUNC initGPIO(void)
619#endif
620{
621 PyObject *module = NULL;
622 int revision = -1;
623
624#if PY_MAJOR_VERSION > 2
625 if ((module = PyModule_Create(&python_module)) == NULL)
626 goto exit;
627#else
628 if ((module = Py_InitModule("_webiopi.GPIO", python_methods)) == NULL)
629 goto exit;
630#endif
631
632 _SetupException = PyErr_NewException("_webiopi.GPIO.SetupException", NULL, NULL);
633 PyModule_AddObject(module, "SetupException", _SetupException);
634
635 _InvalidDirectionException = PyErr_NewException("_webiopi.GPIO.InvalidDirectionException", NULL, NULL);
636 PyModule_AddObject(module, "InvalidDirectionException", _InvalidDirectionException);
637
638 _InvalidChannelException = PyErr_NewException("_webiopi.GPIO.InvalidChannelException", NULL, NULL);
639 PyModule_AddObject(module, "InvalidChannelException", _InvalidChannelException);
640
641 _InvalidPullException = PyErr_NewException("_webiopi.GPIO.InvalidPullException", NULL, NULL);
642 PyModule_AddObject(module, "InvalidPullException", _InvalidPullException);
643
644 _gpioCount = Py_BuildValue("i", GPIO_COUNT);
645 PyModule_AddObject(module, "GPIO_COUNT", _gpioCount);
646
647 _low = Py_BuildValue("i", LOW);
648 PyModule_AddObject(module, "LOW", _low);
649
650 _high = Py_BuildValue("i", HIGH);
651 PyModule_AddObject(module, "HIGH", _high);
652
653 _in = Py_BuildValue("i", IN);
654 PyModule_AddObject(module, "IN", _in);
655
656 _out = Py_BuildValue("i", OUT);
657 PyModule_AddObject(module, "OUT", _out);
658
659 _alt0 = Py_BuildValue("i", ALT0);
660 PyModule_AddObject(module, "ALT0", _alt0);
661
662 _alt1 = Py_BuildValue("i", ALT1);
663 PyModule_AddObject(module, "ALT1", _alt1);
664
665 _alt2 = Py_BuildValue("i", ALT2);
666 PyModule_AddObject(module, "ALT2", _alt2);
667
668 _alt3 = Py_BuildValue("i", ALT3);
669 PyModule_AddObject(module, "ALT3", _alt3);
670
671 _alt4 = Py_BuildValue("i", ALT4);
672 PyModule_AddObject(module, "ALT4", _alt4);
673
674 _alt5 = Py_BuildValue("i", ALT5);
675 PyModule_AddObject(module, "ALT5", _alt5);
676
677 _pwm = Py_BuildValue("i", PWM);
678 PyModule_AddObject(module, "PWM", _pwm);
679
680 _pud_off = Py_BuildValue("i", PUD_OFF);
681 PyModule_AddObject(module, "PUD_OFF", _pud_off);
682
683 _pud_up = Py_BuildValue("i", PUD_UP);
684 PyModule_AddObject(module, "PUD_UP", _pud_up);
685
686 _pud_down = Py_BuildValue("i", PUD_DOWN);
687 PyModule_AddObject(module, "PUD_DOWN", _pud_down);
688
689 // detect board revision and set up accordingly
690 revision = get_rpi_revision();
691 if (revision == -1)
692 {
693 PyErr_SetString(_SetupException, "This module can only be run on a Raspberry Pi!");
694#if PY_MAJOR_VERSION > 2
695 return NULL;
696#else
697 return;
698#endif
699 }
700
701 _board_revision = Py_BuildValue("i", revision);
702 PyModule_AddObject(module, "BOARD_REVISION", _board_revision);
703
704 if (Py_AtExit(cleanup) != 0)
705 {
706 cleanup();
707#if PY_MAJOR_VERSION > 2
708 return NULL;
709#else
710 return;
711#endif
712 }
713
714exit:
715#if PY_MAJOR_VERSION > 2
716 return module;
717#else
718 return;
719#endif
720}