forked from vitiral/gpio
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Garrett Berg
committed
Mar 10, 2015
1 parent
0439aa8
commit 60a04da
Showing
8 changed files
with
193 additions
and
93 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# Linux [sysfs](https://www.kernel.org/doc/Documentation/gpio/sysfs.txt) gpio access | ||
|
||
This library provides gpio access via the standard linux [sysfs interface](https://www.kernel.org/doc/Documentation/gpio/sysfs.txt) | ||
|
||
It is intended to mimick [RPIO](http://pythonhosted.org/RPIO/) as much as possible for all features, | ||
while also supporting additional (and better named) functionality to the same methods. | ||
|
||
## Supported Features | ||
**sysfs** is still under development, and so only supports minimal features | ||
|
||
- get pin values with `read(pin)` or `input(pin)` | ||
- set pin values with `set(pin, value)` or `output(pin)` | ||
- get the pin mode with `mode(pin)` | ||
- set the pin mode with `setup(pin, mode)` | ||
- `mode` can currently equal `sysfs.IN` or `sysfs.OUT` | ||
|
||
# Future Features | ||
- setting pullup / pulldown values for pins | ||
- setting pins as pwm |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,116 @@ | ||
|
||
import functools | ||
import threading | ||
import os | ||
|
||
path = os.path | ||
pjoin = os.path.join | ||
|
||
gpio_root = '/sys/class/gpio' | ||
gpiopath = lambda pin: os.path.join(gpio_root, 'gpio{}'.format(pin)) | ||
_export_lock = threading.Lock() | ||
|
||
_pyset = set | ||
|
||
_open = dict() | ||
FMODE = 'w+' | ||
|
||
IN, OUT = 'in', 'out' | ||
|
||
|
||
def _write(f, v): | ||
f.write(str(v)) | ||
|
||
|
||
def _read(f): | ||
f.seek(0) | ||
return f.read() | ||
|
||
|
||
def _verify(function): | ||
"""decorator to ensure pin is properly set up""" | ||
@functools.wraps | ||
def wrapped(pin, *args, **kwargs): | ||
pin = int(pin) | ||
if pin not in _open: | ||
ppath = gpiopath(pin) | ||
if not os.path.exists(ppath): | ||
with _export_lock: | ||
with open(pjoin(gpio_root, 'export'), 'w') as f: | ||
_write(f, pin) | ||
_open[pin] = { | ||
'value': open(pjoin(ppath, 'value'), FMODE), | ||
'direction': open(pjoin(ppath, 'direction'), FMODE), | ||
'drive': open(pjoin(ppath, 'drive'), FMODE) | ||
} | ||
return function(pin, *args, **kwargs) | ||
return wrapped | ||
|
||
|
||
@_verify | ||
def setup(pin, mode, pullup=None): | ||
if mode not in {IN, OUT}: | ||
raise ValueError(mode) | ||
f = _open[pin]['direction'] | ||
_write(f, mode) | ||
|
||
|
||
@_verify | ||
def mode(pin): | ||
'''get the pin mode''' | ||
f = _open[pin]['direction'] | ||
return _read(f) | ||
|
||
|
||
@_verify | ||
def read(pin): | ||
'''read the pin value | ||
Returns: | ||
bool: 0 or 1 | ||
''' | ||
f = _open[pin]['value'] | ||
return _read(f) | ||
|
||
|
||
@_verify | ||
def set(pin, value): | ||
'''set the pin value to 0 or 1''' | ||
value = int(value) | ||
f = _open[pin]['value'] | ||
_write(f, value) | ||
|
||
|
||
@_verify | ||
def input(pin): | ||
'''read the pin. Same as read''' | ||
return read(pin) | ||
|
||
|
||
@_verify | ||
def output(pin, value): | ||
'''set the pin. Same as set''' | ||
return set(pin) | ||
# -*- coding: utf-8 -*- | ||
import functools | ||
import threading | ||
import os | ||
import sys | ||
import traceback | ||
import pdb | ||
|
||
def except_hook(exctype, value, tb): | ||
traceback.print_tb(tb) | ||
print(repr(value)) | ||
pdb.post_mortem(tb) | ||
|
||
sys.excepthook = except_hook | ||
|
||
path = os.path | ||
pjoin = os.path.join | ||
|
||
gpio_root = '/sys/class/gpio' | ||
gpiopath = lambda pin: os.path.join(gpio_root, 'gpio{}'.format(pin)) | ||
_export_lock = threading.Lock() | ||
|
||
_pyset = set | ||
|
||
_open = dict() | ||
FMODE = 'w+' | ||
|
||
IN, OUT = 'in', 'out' | ||
|
||
|
||
def _write(f, v): | ||
print("writing: {}: {}".format(f, v)) | ||
f.write(str(v)) | ||
|
||
|
||
def _read(f): | ||
f.seek(0) | ||
return f.read() | ||
|
||
|
||
def _verify(function): | ||
"""decorator to ensure pin is properly set up""" | ||
# @functools.wraps | ||
def wrapped(pin, *args, **kwargs): | ||
pin = int(pin) | ||
if pin not in _open: | ||
ppath = gpiopath(pin) | ||
if not os.path.exists(ppath): | ||
with _export_lock: | ||
with open(pjoin(gpio_root, 'export'), 'w') as f: | ||
_write(f, pin) | ||
_open[pin] = { | ||
'value': open(pjoin(ppath, 'value'), FMODE), | ||
'direction': open(pjoin(ppath, 'direction'), FMODE), | ||
'drive': open(pjoin(ppath, 'drive'), FMODE), | ||
} | ||
return function(pin, *args, **kwargs) | ||
return wrapped | ||
|
||
|
||
@_verify | ||
def setup(pin, mode, pullup=None): | ||
if mode not in {IN, OUT}: | ||
raise ValueError(mode) | ||
f = _open[pin]['direction'] | ||
_write(f, mode) | ||
|
||
|
||
@_verify | ||
def mode(pin): | ||
'''get the pin mode''' | ||
f = _open[pin]['direction'] | ||
return _read(f) | ||
|
||
|
||
@_verify | ||
def read(pin): | ||
'''read the pin value | ||
Returns: | ||
bool: 0 or 1 | ||
''' | ||
f = _open[pin]['value'] | ||
return int(_read(f)) | ||
|
||
|
||
@_verify | ||
def set(pin, value): | ||
'''set the pin value to 0 or 1''' | ||
value = int(value) | ||
f = _open[pin]['value'] | ||
_write(f, value) | ||
|
||
|
||
@_verify | ||
def input(pin): | ||
'''read the pin. Same as read''' | ||
return read(pin) | ||
|
||
|
||
@_verify | ||
def output(pin, value): | ||
'''set the pin. Same as set''' | ||
return set(pin) | ||
|
||
|
||
if __name__ == '__main__': | ||
print("starting") | ||
skip = {8, 10, 16, 17} | ||
values = [] | ||
for n in xrange(24, 29): | ||
if n in skip: continue | ||
# print("pin {:3d} = {}".format(n, read(n))) | ||
values.append(read(n)) | ||
print(values) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
# -*- coding: utf-8 -*- |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# -*- coding: utf-8 -*- | ||
from unittest import TestCase | ||
from unittest.mock import mock_open, patch | ||
import sys | ||
import os | ||
pjoin = os.path.join | ||
import gpio | ||
|
||
if sys.version_info.major < 3: | ||
bins = '__builtin__' | ||
else: | ||
bins = 'builtins' | ||
|
||
root = gpio.gpio_root | ||
|
||
|
||
def mockargs(mock): | ||
return [m[0] for m in mock.call_args_list] | ||
|
||
|
||
def assertInitialized(self, mfile, gpio=0): | ||
margs = mockargs(mfile) | ||
groot = pjoin(root, 'gpio{}'.format(gpio)) | ||
self.assertEqual(margs[0], (pjoin(root, 'export'), 'w')) | ||
self.assertEqual(margs[1], (pjoin(groot, 'value'), 'w+')) | ||
self.assertEqual(margs[2], (pjoin(groot, 'direction'), 'w+')) | ||
self.assertEqual(margs[3], (pjoin(groot, 'drive'), 'w+')) | ||
|
||
|
||
def reset(method): | ||
def wrapped(*args, **kwargs): | ||
gpio._open.clear() | ||
return method(*args, **kwargs) | ||
return wrapped | ||
|
||
|
||
class TestRead(TestCase): | ||
@reset | ||
def test_basic(self): | ||
mopen = mock_open(read_data='0') | ||
with patch(bins + '.open', mopen, create=True) as m: | ||
result = gpio.read(0) | ||
assertInitialized(self, m) | ||
self.assertEqual(result, 0) | ||
|
||
|
||
class TestWrite(TestCase): | ||
@reset | ||
def test_basic(self): | ||
mopen = mock_open(read_data='0') | ||
with patch(bins + '.open', mopen, create=True) as m: | ||
import pdb; pdb.set_trace() | ||
gpio.setup(0, gpio.OUT) | ||
gpio.set(0, 0) | ||
assertInitialized(self, m) | ||
written = mockargs(gpio._open[0]['value'].write) | ||
import ipdb; ipdb.set_trace() |