Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # This code assumes /dev/gpio contains symlinks for sysfs gpios.
- #
- # Example udev rule:
- #
- # SUBSYSTEM=="subsystem", KERNEL=="gpio", ACTION=="add", \
- # RUN+="/bin/mkdir -p /dev/gpio"
- #
- # SUBSYSTEM=="gpio", ACTION=="add", TEST=="value", ATTR{label}!="sysfs", \
- # RUN+="/bin/ln -sT '/sys/class/gpio/%k' /dev/gpio/%s{label}"
- #
- # To install, save as e.g. /etc/udev/rules.d/gpio-symlinks.rules
- # then "sudo update-initramfs -u" (unless you don't use initramfs) and reboot.
- #
- # Alternatively, the "name" argument of the functions below also accepts an
- # absolute path to the sysfs gpio (e.g. "/sys/class/gpio/gpio42").
- #
- #
- # This code is written to be simple and correct, not necessarily efficient.
- # Performance can probably be greatly improved by keeping a file descriptor
- # open for the 'value' attribute and using os.pread() and os.write(). This
- # would also be step 1 towards supporting input change events.
- from pathlib import Path
- # internal helper functions
- def _gpio_attribute_path( name, attr ):
- return Path( '/dev/gpio', name, attr )
- def _gpio_get_attribute( name, attr ):
- return _gpio_attribute_path( name, attr ).read_text().rstrip()
- def _gpio_set_attribute( name, attr, value ):
- return _gpio_attribute_path( name, attr ).write_text( value )
- # get/set output value (0 or 1) for gpio configured as output.
- # read input value (0 or 1) for gpio configured as input.
- # trying to set the value of an input will fail, it will not change to output.
- def gpio_get_value( name ):
- return int( _gpio_get_attribute( name, 'value' ) )
- def gpio_set_value( name, value ):
- assert type(value) is int and value in (0, 1)
- _gpio_set_attribute( name, 'value', str(value) )
- # get/set direction ('in' or 'out') of gpio.
- #
- # NOTE: changing the direction of a gpio may not always be allowed, in which
- # case attempting to set it will fail even if you're trying to set it to the
- # state it is already in. If you merely want to ensure the gpio direction
- # during initialization, check it before trying to set it.
- def gpio_get_direction( name ):
- return _gpio_get_attribute( name, 'direction' )
- def gpio_set_direction_in( name ):
- _gpio_set_attribute( name, 'direction', 'in' )
- # when changing direction to output, the initial output value must be specified
- # with a keyword argument, e.g. gpio_set_direction_out( "foo", value=0 )
- def gpio_set_direction_out( name, *, value ):
- level = gpio_get_level_for_value( name, value )
- _gpio_set_attribute( name, 'direction', level )
- # The state of a gpio can be described in two ways:
- # - logical value: 0 or 1
- # - voltage level: low or high
- #
- # It is important not to confuse these since the mapping between logical value
- # and voltage level is configurable (both in DT and at runtime).
- #
- # The level corresponding to value=1 is also known as the "active" level, hence
- # a gpio configured such that 1=low and 0=high is known as "active-low", while
- # one configured such that 0=low and 1=high is known as "active-high".
- #
- # Below are therefore three ways to get/set this mapping:
- # - the value (0 or 1) corresponding to low level
- # - the active level ('low' or 'high'), i.e. corresponding to value=1
- # - whether gpio is active-low (bool)
- #
- # Generally speaking you should configure this mapping once and then leave it
- # alone. Ideally you should configure in DT and your software won't need to
- # care about any of this and can just use the value-based functions above.
- def gpio_get_low_value( name ):
- return int( _gpio_get_attribute( name, 'active_low' ) )
- def gpio_set_low_value( name, value ):
- assert type(value) is int and value in (0,1)
- _gpio_set_attribute( name, 'active_low', str(value) )
- def gpio_is_active_low( name ):
- return bool( gpio_get_low_value( name ) )
- def gpio_set_active_low( name, is_active_low ):
- assert type(is_active_low) is bool
- gpio_set_low_value( name, int( is_active_low ) )
- def gpio_get_active_level( name ):
- return ('low', 'high')[ gpio_get_low_value( name ) ]
- def gpio_set_active_level( name, level ):
- gpio_set_low_value( name, ('low', 'high').index( level ) )
- # map between logical value (0 or 1) and voltage level ('low' or 'high')
- def gpio_get_level_for_value( name, value ):
- return ('low', 'high')[ gpio_get_low_value( name ) ^ value ]
- def gpio_get_value_for_level( name, level ):
- return ('low', 'high').index( level ) ^ gpio_get_low_value( name )
Add Comment
Please, Sign In to add comment