View difference between Paste ID: sDdaGxNR and cVHktYPn
SHOW: | | - or go back to the newest paste.
1
# From @zmatt, i.e. mvduin
2
3
# This code assumes /dev/gpio contains symlinks for sysfs gpios.
4
#
5
# Example udev rule:
6
#
7
#	SUBSYSTEM=="subsystem", KERNEL=="gpio", ACTION=="add", \
8
#		RUN+="/bin/mkdir -p /dev/gpio"
9
#
10
#	SUBSYSTEM=="gpio", ACTION=="add", TEST=="value", ATTR{label}!="sysfs", \
11
#		RUN+="/bin/ln -sT '/sys/class/gpio/%k' /dev/gpio/%s{label}"
12
#
13
# To install, save as e.g. /etc/udev/rules.d/gpio-symlinks.rules
14
# then "sudo update-initramfs -u" (unless you don't use initramfs) and reboot.
15
#
16
# Alternatively, the "name" argument of the functions below also accepts an
17
# absolute path to the sysfs gpio (e.g. "/sys/class/gpio/gpio42").
18
#
19
#
20
# This code is written to be simple and correct, not necessarily efficient.
21
# Performance can probably be greatly improved by keeping a file descriptor
22
# open for the 'value' attribute and using os.pread() and os.write().  This
23
# would also be step 1 towards supporting input change events.
24
25
26
from pathlib import Path
27
28
29
# internal helper functions
30
31
def _gpio_attribute_path( name, attr ):
32
    return Path( '/dev/gpio', name, attr )
33
34
def _gpio_get_attribute( name, attr ):
35
    return _gpio_attribute_path( name, attr ).read_text().rstrip()
36
37
def _gpio_set_attribute( name, attr, value ):
38
    return _gpio_attribute_path( name, attr ).write_text( value )
39
40
41
# get/set output value (0 or 1) for gpio configured as output.
42
# read input value (0 or 1) for gpio configured as input.
43
# trying to set the value of an input will fail, it will not change to output.
44
45
def gpio_get_value( name ):
46
    return int( _gpio_get_attribute( name, 'value' ) )
47
48
def gpio_set_value( name, value ):
49
    assert type(value) is int and value in (0, 1)
50
    _gpio_set_attribute( name, 'value', str(value) )
51
52
53
# get/set direction ('in' or 'out') of gpio.
54
#
55
# NOTE: changing the direction of a gpio may not always be allowed, in which
56
# case attempting to set it will fail even if you're trying to set it to the
57
# state it is already in.  If you merely want to ensure the gpio direction
58
# during initialization, check it before trying to set it.
59
60
def gpio_get_direction( name ):
61
    return _gpio_get_attribute( name, 'direction' )
62
63
def gpio_set_direction_in( name ):
64
    _gpio_set_attribute( name, 'direction', 'in' )
65
66
# when changing direction to output, the initial output value must be specified
67
# with a keyword argument, e.g.  gpio_set_direction_out( "foo", value=0 )
68
def gpio_set_direction_out( name, *, value ):
69
    level = gpio_get_level_for_value( name, value )
70
    _gpio_set_attribute( name, 'direction', level )
71
72
73
# The state of a gpio can be described in two ways:
74
# - logical value: 0 or 1
75
# - voltage level: low or high
76
#
77
# It is important not to confuse these since the mapping between logical value
78
# and voltage level is configurable (both in DT and at runtime).
79
#
80
# The level corresponding to value=1 is also known as the "active" level, hence
81
# a gpio configured such that 1=low and 0=high is known as "active-low", while
82
# one configured such that 0=low and 1=high is known as "active-high".
83
#
84
# Below are therefore three ways to get/set this mapping:
85
# - the value (0 or 1) corresponding to low level
86
# - the active level ('low' or 'high'), i.e. corresponding to value=1
87
# - whether gpio is active-low (bool)
88
#
89
# Generally speaking you should configure this mapping once and then leave it
90
# alone.  Ideally you should configure in DT and your software won't need to
91
# care about any of this and can just use the value-based functions above.
92
93
def gpio_get_low_value( name ):
94
    return int( _gpio_get_attribute( name, 'active_low' ) )
95
96
def gpio_set_low_value( name, value ):
97
    assert type(value) is int and value in (0,1)
98
    _gpio_set_attribute( name, 'active_low', str(value) )
99
100
def gpio_is_active_low( name ):
101
    return bool( gpio_get_low_value( name ) )
102
103
def gpio_set_active_low( name, is_active_low ):
104
    assert type(is_active_low) is bool
105
    gpio_set_low_value( name, int( is_active_low ) )
106
107
def gpio_get_active_level( name ):
108
    return ('low', 'high')[ gpio_get_low_value( name ) ]
109
110
def gpio_set_active_level( name, level ):
111
    gpio_set_low_value( name, ('low', 'high').index( level ) )
112
113
# map between logical value (0 or 1) and voltage level ('low' or 'high')
114
115
def gpio_get_level_for_value( name, value ):
116
    return ('low', 'high')[ gpio_get_low_value( name ) ^ value ]
117
118
def gpio_get_value_for_level( name, level ):
119
    return ('low', 'high').index( level ) ^ gpio_get_low_value( name )