Advertisement
silver2row

Trying to learn new things...Python Lib for AI/GPIO

May 30th, 2021
1,963
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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 )
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement