├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── Adafruit_BBIO ├── Encoder.py ├── README.md ├── __init__.py └── sysfs.py ├── Adafruit_I2C.py ├── CHANGELOG.md ├── MANIFEST.in ├── Makefile ├── Makefile.am ├── README.md ├── configure.ac ├── distribute_setup.py ├── docs ├── ADC.rst ├── Encoder.rst ├── GPIO.rst ├── Makefile ├── PWM.rst ├── README.md ├── SPI.rst ├── UART.rst ├── conf.py └── index.rst ├── fix_py_compile.py ├── install_all_python_versions.sh ├── m4 ├── .gitkeep ├── gtest.m4 └── kernel-release.m4 ├── overlays ├── ADAFRUIT-SPI0-00A0.dts ├── ADAFRUIT-SPI1-00A0.dts ├── ADAFRUIT-UART1-00A0.dts ├── ADAFRUIT-UART2-00A0.dts ├── ADAFRUIT-UART4-00A0.dts ├── ADAFRUIT-UART5-00A0.dts ├── __init__.py └── builder.py ├── pytest_all_versions.sh ├── setup.py ├── source ├── Makefile.am ├── c_adc.c ├── c_adc.h ├── c_pinmux.c ├── c_pinmux.h ├── c_pwm.c ├── c_pwm.h ├── c_uart.c ├── c_uart.h ├── common.c ├── common.h ├── constants.c ├── constants.h ├── event_gpio.c ├── event_gpio.h ├── examples │ ├── cpp │ │ ├── gpio.cpp │ │ └── pwm.cpp │ └── python │ │ ├── blinkLEDs.py │ │ ├── button.py │ │ ├── gpio.py │ │ ├── i2cmatrix.py │ │ ├── i2ctmp101.py │ │ ├── install.sh │ │ ├── leds.py │ │ ├── pwm.old.py │ │ └── pwm.py ├── include │ └── adafruit │ │ ├── bbio.h │ │ └── bbio │ │ ├── error.h │ │ ├── gpio.h │ │ └── pwm.h ├── library │ ├── bbio.cpp │ ├── gpio.cpp │ └── pwm.cpp ├── py_adc.c ├── py_gpio.c ├── py_pwm.c ├── py_uart.c ├── spimodule.c └── test │ └── cpp │ ├── abi.cpp │ └── pwm.cpp ├── test ├── issue170-pwm.py ├── issue178.py ├── notes │ ├── rotary-encoder-eqep-test.md │ ├── run_config-pin_during_startup.md │ ├── spi_loopback_test.md │ └── test_read_write_all_gpio_pins.md ├── setup │ └── 0001-rename-USR-LED-names-to-test-Adafruit_BBIO-issue-129.patch ├── start_all_pwm.py ├── test_adc.py ├── test_gpio_input.py ├── test_gpio_output.py ├── test_gpio_setup.py ├── test_led.py ├── test_pwm_setup.py ├── test_spi.py └── test_uart.py ├── tox.ini └── udev ├── 80-non-root-gpio-permissions.rules └── udev-non-root-gpio-permissions.sh /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for opening an issue on the Adafruit BeagleBone Python library repository. 2 | 3 | 4 | In order to understand your system configuration better, please run: 5 | ``` 6 | sudo /opt/scripts/tools/version.sh 7 | ``` 8 | 9 | and paste the output in a reply. 10 | 11 | This script should be present for any image downloaded from: 12 | https://beagleboard.org/ or https://rcn-ee.com/ 13 | 14 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | Thank you for creating a pull request to contribute to Adafruit's GitHub code! 2 | Before you open the request please review the following guidelines and tips to 3 | help it be more easily integrated: 4 | 5 | - **Describe the scope of your change--i.e. what the change does and what parts 6 | of the code were modified.** This will help us understand any risks of integrating 7 | the code. 8 | 9 | - **Describe any known limitations with your change.** For example if the change 10 | doesn't apply to a supported platform of the library please mention it. 11 | 12 | - **Please run any tests or examples that can exercise your modified code.** We 13 | strive to not break users of the code and running tests/examples helps with this 14 | process. 15 | 16 | Thank you again for contributing! We will try to test and integrate the change 17 | as soon as we can, but be aware we have many GitHub repositories to manage and 18 | can't immediately respond to every request. There is no need to bump or check in 19 | on a pull request (it will clutter the discussion of the request). 20 | 21 | Also don't be worried if the request is closed or not integrated--sometimes the 22 | priorities of Adafruit's GitHub code (education, ease of use) might not match the 23 | priorities of the pull request. Don't fret, the open source community thrives on 24 | forks and GitHub makes it easy to keep your changes in a forked repo. 25 | 26 | After reviewing the guidelines above you can delete this text from the pull request. 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #Useful gitignore for python: https://github.com/github/gitignore/blob/master/Python.gitignore 2 | *.py[cod] 3 | 4 | # C extensions 5 | *.so 6 | 7 | # Packages 8 | *.egg 9 | *.egg-info 10 | dist 11 | build 12 | eggs 13 | parts 14 | bin 15 | var 16 | sdist 17 | develop-eggs 18 | .installed.cfg 19 | lib 20 | lib64 21 | __pycache__ 22 | distribute-0.* 23 | 24 | # Unit test / coverage reports 25 | .coverage 26 | .tox 27 | nosetests.xml 28 | 29 | # Translations 30 | *.mo 31 | 32 | # Annoying MacOSX files. 33 | .DS_Store 34 | ._.DS_Store 35 | 36 | # autotools 37 | Makefile.in 38 | aclocal.m4 39 | autom4te.cache/ 40 | compile 41 | configure 42 | config.guess 43 | config.h.in 44 | config.sub 45 | depcomp 46 | install-sh 47 | ltmain.sh 48 | m4/libtool.m4 49 | m4/ltoptions.m4 50 | m4/ltsugar.m4 51 | m4/ltversion.m4 52 | m4/lt~obsolete.m4 53 | missing 54 | source/Makefile.in 55 | test-driver 56 | docs/_build 57 | docs/_static 58 | docs/_templates 59 | 60 | # vim temp files 61 | *~ 62 | *.swp 63 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - "3.6" 4 | install: 5 | - pip install tox 6 | script: 7 | - tox 8 | -------------------------------------------------------------------------------- /Adafruit_BBIO/Encoder.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | """Quadrature Encoder Pulse interface. 4 | 5 | This module enables access to the enhanced Quadrature Encoder Pulse (eQEP) 6 | channels, which can be used to seamlessly interface with rotary encoder 7 | hardware. 8 | 9 | The channel identifiers are available as module variables :data:`eQEP0`, 10 | :data:`eQEP1`, :data:`eQEP2` and :data:`eQEP2b`. 11 | 12 | ======= ======= ======= =================================================== 13 | Channel Pin A Pin B Notes 14 | ======= ======= ======= =================================================== 15 | eQEP0 P9.27 P9.92 16 | eQEP1 P8.33 P8.35 Only available with video disabled 17 | eQEP2 P8.11 P8.12 Only available with eQEP2b unused (same channel) 18 | eQEP2b P8.41 P8.42 Only available with video disabled and eQEP2 unused 19 | ======= ======= ======= =================================================== 20 | 21 | Example: 22 | To use the module, you can connect a rotary encoder to your Beaglebone 23 | and then simply instantiate the :class:`RotaryEncoder` class to read its 24 | position:: 25 | 26 | from Adafruit_BBIO.Encoder import RotaryEncoder, eQEP2 27 | 28 | # Instantiate the class to access channel eQEP2, and initialize 29 | # that channel 30 | myEncoder = RotaryEncoder(eQEP2) 31 | 32 | # Get the current position 33 | cur_position = myEncoder.position 34 | 35 | # Set the current position 36 | next_position = 15 37 | myEncoder.position = next_position 38 | 39 | # Reset position to 0 40 | myEncoder.zero() 41 | 42 | # Change mode to relative (default is absolute) 43 | # You can use setAbsolute() to change back to absolute 44 | # Absolute: the position starts at zero and is incremented or 45 | # decremented by the encoder's movement 46 | # Relative: the position is reset when the unit timer overflows. 47 | myEncoder.setRelative() 48 | 49 | # Read the current mode (0: absolute, 1: relative) 50 | # Mode can also be set as a property 51 | mode = myEncoder.mode 52 | 53 | # Get the current frequency of update in Hz 54 | freq = myEncoder.frequency 55 | 56 | # Set the update frequency to 1 kHz 57 | myEncoder.frequency = 1000 58 | 59 | # Disable the eQEP channel 60 | myEncoder.disable() 61 | 62 | # Check if the channel is enabled 63 | # The 'enabled' property is read-only 64 | # Use the enable() and disable() methods to 65 | # safely enable or disable the module 66 | isEnabled = myEncoder.enabled 67 | 68 | """ 69 | 70 | from subprocess import check_output, STDOUT, CalledProcessError 71 | import os 72 | import logging 73 | import itertools 74 | from .sysfs import Node 75 | import platform 76 | 77 | (major, minor, patch) = platform.release().split("-")[0].split(".") 78 | if not (int(major) >= 4 and int(minor) >= 4) \ 79 | and platform.node() == 'beaglebone': 80 | raise ImportError( 81 | 'The Encoder module requires Linux kernel version >= 4.4.x.\n' 82 | 'Please upgrade your kernel to use this module.\n' 83 | 'Your Linux kernel version is {}.'.format(platform.release())) 84 | 85 | 86 | eQEP0 = 0 87 | '''eQEP0 channel identifier, pin A-- P9.92, pin B-- P9.27 on Beaglebone 88 | Black.''' 89 | eQEP1 = 1 90 | '''eQEP1 channel identifier, pin A-- P9.35, pin B-- P9.33 on Beaglebone 91 | Black.''' 92 | eQEP2 = 2 93 | '''eQEP2 channel identifier, pin A-- P8.12, pin B-- P8.11 on Beaglebone Black. 94 | Note that there is only one eQEP2 module. This is one alternative set of pins 95 | where it is exposed, which is mutually-exclusive with eQEP2b''' 96 | eQEP2b = 3 97 | '''eQEP2(b) channel identifier, pin A-- P8.41, pin B-- P8.42 on Beaglebone 98 | Black. Note that there is only one eQEP2 module. This is one alternative set of 99 | pins where it is exposed, which is mutually-exclusive with eQEP2''' 100 | 101 | # Definitions to initialize the eQEP modules 102 | _OCP_PATH = "/sys/devices/platform/ocp" 103 | _eQEP_DEFS = [ 104 | {'channel': 'eQEP0', 'pin_A': 'P9_92', 'pin_B': 'P9_27', 105 | 'sys_path': os.path.join(_OCP_PATH, '48300000.epwmss/48300180.eqep')}, 106 | {'channel': 'eQEP1', 'pin_A': 'P8_35', 'pin_B': 'P8_33', 107 | 'sys_path': os.path.join(_OCP_PATH, '48302000.epwmss/48302180.eqep')}, 108 | {'channel': 'eQEP2', 'pin_A': 'P8_12', 'pin_B': 'P8_11', 109 | 'sys_path': os.path.join(_OCP_PATH, '48304000.epwmss/48304180.eqep')}, 110 | {'channel': 'eQEP2b', 'pin_A': 'P8_41', 'pin_B': 'P8_42', 111 | 'sys_path': os.path.join(_OCP_PATH, '48304000.epwmss/48304180.eqep')} 112 | ] 113 | 114 | 115 | class _eQEP(object): 116 | '''Enhanced Quadrature Encoder Pulse (eQEP) module class. Abstraction 117 | for either of the three available channels (eQEP0, eQEP1, eQEP2) on 118 | the Beaglebone''' 119 | 120 | @classmethod 121 | def fromdict(cls, d): 122 | '''Creates a class instance from a dictionary''' 123 | 124 | allowed = ('channel', 'pin_A', 'pin_B', 'sys_path') 125 | df = {k: v for k, v in d.items() if k in allowed} 126 | return cls(**df) 127 | 128 | def __init__(self, channel, pin_A, pin_B, sys_path): 129 | '''Initialize the given eQEP channel 130 | 131 | Attributes: 132 | channel (str): eQEP channel name. E.g. "eQEP0", "eQEP1", etc. 133 | Note that "eQEP2" and "eQEP2b" are channel aliases for the 134 | same module, but on different (mutually-exclusive) sets of 135 | pins 136 | pin_A (str): physical input pin for the A signal of the 137 | rotary encoder 138 | pin_B (str): physical input pin for the B signal of the 139 | rotary encoder 140 | sys_path (str): sys filesystem path to access the attributes 141 | of this eQEP module 142 | node (str): sys filesystem device node that contains the 143 | readable or writable attributes to control the QEP channel 144 | 145 | ''' 146 | self.channel = channel 147 | self.pin_A = pin_A 148 | self.pin_B = pin_B 149 | self.sys_path = sys_path 150 | self.node = Node(sys_path) 151 | 152 | 153 | class RotaryEncoder(object): 154 | ''' 155 | Rotary encoder class abstraction to control a given QEP channel. 156 | 157 | Args: 158 | eqep_num (int): determines which eQEP pins are set up. 159 | Allowed values: EQEP0, EQEP1, EQEP2 or EQEP2b, 160 | based on which pins the physical rotary encoder 161 | is connected to. 162 | ''' 163 | 164 | def _run_cmd(self, cmd): 165 | '''Runs a command. If not successful (i.e. error code different than 166 | zero), print the stderr output as a warning. 167 | 168 | ''' 169 | try: 170 | output = check_output(cmd, stderr=STDOUT) 171 | self._logger.info( 172 | "_run_cmd(): cmd='{}' return code={} output={}".format( 173 | " ".join(cmd), 0, output)) 174 | except CalledProcessError as e: 175 | self._logger.warning( 176 | "_run_cmd(): cmd='{}' return code={} output={}".format( 177 | " ".join(cmd), e.returncode, e.output)) 178 | 179 | def _config_pin(self, pin): 180 | '''Configures a pin in QEP mode using the `config-pin` binary''' 181 | 182 | self._run_cmd(["config-pin", pin, "qep"]) 183 | 184 | def __init__(self, eqep_num): 185 | '''Creates an instance of the class RotaryEncoder.''' 186 | 187 | # nanoseconds factor to convert period to frequency and back 188 | self._NS_FACTOR = 1000000000 189 | 190 | # Set up logging at the module level 191 | self._logger = logging.getLogger(__name__) 192 | self._logger.addHandler(logging.NullHandler()) 193 | 194 | # Initialize the eQEP channel structures 195 | self._eqep = _eQEP.fromdict(_eQEP_DEFS[eqep_num]) 196 | self._logger.info( 197 | "Configuring: {}, pin A: {}, pin B: {}, sys path: {}".format( 198 | self._eqep.channel, self._eqep.pin_A, self._eqep.pin_B, 199 | self._eqep.sys_path)) 200 | 201 | # Configure the pins for the given channel 202 | self._config_pin(self._eqep.pin_A) 203 | self._config_pin(self._eqep.pin_B) 204 | 205 | self._logger.debug( 206 | "RotaryEncoder(): sys node: {0}".format(self._eqep.sys_path)) 207 | 208 | # Enable the channel upon initialization 209 | self.enable() 210 | 211 | @property 212 | def enabled(self): 213 | '''Returns the enabled status of the module: 214 | 215 | Returns: 216 | bool: True if the eQEP channel is enabled, False otherwise. 217 | ''' 218 | isEnabled = bool(int(self._eqep.node.enabled)) 219 | 220 | return isEnabled 221 | 222 | def _setEnable(self, enabled): 223 | '''Turns the eQEP hardware ON or OFF 224 | 225 | Args: 226 | enabled (int): enable the module with 1, disable it with 0. 227 | 228 | Raises: 229 | ValueError: if the value for enabled is < 0 or > 1 230 | 231 | ''' 232 | enabled = int(enabled) 233 | if enabled < 0 or enabled > 1: 234 | raise ValueError( 235 | 'The "enabled" attribute can only be set to 0 or 1. ' 236 | 'You attempted to set it to {}.'.format(enabled)) 237 | 238 | self._eqep.node.enabled = str(enabled) 239 | self._logger.info("Channel: {}, enabled: {}".format( 240 | self._eqep.channel, self._eqep.node.enabled)) 241 | 242 | def enable(self): 243 | '''Turns the eQEP hardware ON''' 244 | 245 | self._setEnable(1) 246 | 247 | def disable(self): 248 | '''Turns the eQEP hardware OFF''' 249 | 250 | self._setEnable(0) 251 | 252 | @property 253 | def mode(self): 254 | '''Returns the mode the eQEP hardware is in. 255 | 256 | Returns: 257 | int: 0 if the eQEP channel is configured in absolute mode, 258 | 1 if configured in relative mode. 259 | ''' 260 | mode = int(self._eqep.node.mode) 261 | 262 | if mode == 0: 263 | mode_name = "absolute" 264 | elif mode == 1: 265 | mode_name = "relative" 266 | else: 267 | mode_name = "invalid" 268 | 269 | self._logger.debug("getMode(): Channel {}, mode: {} ({})".format( 270 | self._eqep.channel, mode, mode_name)) 271 | 272 | return mode 273 | 274 | @mode.setter 275 | def mode(self, mode): 276 | '''Sets the eQEP mode as absolute (0) or relative (1). 277 | See the setAbsolute() and setRelative() methods for 278 | more information. 279 | 280 | ''' 281 | mode = int(mode) 282 | if mode < 0 or mode > 1: 283 | raise ValueError( 284 | 'The "mode" attribute can only be set to 0 or 1. ' 285 | 'You attempted to set it to {}.'.format(mode)) 286 | 287 | self._eqep.node.mode = str(mode) 288 | self._logger.debug("Mode set to: {}".format( 289 | self._eqep.node.mode)) 290 | 291 | def setAbsolute(self): 292 | '''Sets the eQEP mode as Absolute: 293 | The position starts at zero and is incremented or 294 | decremented by the encoder's movement 295 | 296 | ''' 297 | self.mode = 0 298 | 299 | def setRelative(self): 300 | '''Sets the eQEP mode as Relative: 301 | The position is reset when the unit timer overflows. 302 | 303 | ''' 304 | self.mode = 1 305 | 306 | @property 307 | def position(self): 308 | '''Returns the current position of the encoder. 309 | In absolute mode, this attribute represents the current position 310 | of the encoder. 311 | In relative mode, this attribute represents the position of the 312 | encoder at the last unit timer overflow. 313 | 314 | ''' 315 | position = self._eqep.node.position 316 | 317 | self._logger.debug("Get position: Channel {}, position: {}".format( 318 | self._eqep.channel, position)) 319 | 320 | return int(position) 321 | 322 | @position.setter 323 | def position(self, position): 324 | '''Sets the current position to a new value''' 325 | 326 | position = int(position) 327 | self._eqep.node.position = str(position) 328 | 329 | self._logger.debug("Set position: Channel {}, position: {}".format( 330 | self._eqep.channel, position)) 331 | 332 | @property 333 | def frequency(self): 334 | '''Sets the frequency in Hz at which the driver reports 335 | new positions. 336 | 337 | ''' 338 | frequency = self._NS_FACTOR / int(self._eqep.node.period) 339 | 340 | self._logger.debug( 341 | "Set frequency(): Channel {}, frequency: {} Hz, " 342 | "period: {} ns".format( 343 | self._eqep.channel, frequency, 344 | self._eqep.node.period)) 345 | 346 | return frequency 347 | 348 | @frequency.setter 349 | def frequency(self, frequency): 350 | '''Sets the frequency in Hz at which the driver reports 351 | new positions. 352 | 353 | ''' 354 | # github issue #299: force period to be an integer 355 | period = int(self._NS_FACTOR / frequency) # Period in nanoseconds 356 | self._eqep.node.period = str(period) 357 | self._logger.debug( 358 | "Set frequency(): Channel {}, frequency: {} Hz, " 359 | "period: {} ns".format( 360 | self._eqep.channel, frequency, period)) 361 | 362 | def zero(self): 363 | '''Resets the current position to 0''' 364 | 365 | self.position = 0 366 | 367 | -------------------------------------------------------------------------------- /Adafruit_BBIO/README.md: -------------------------------------------------------------------------------- 1 | # Adafruit_BBIO.Encoder 2 | 3 | This module enables access to the Beaglebone Black enhanced Quadrature Encoder Pulse (eQEP) modules: eQEP0, eQEP1 and eQEP2/eQEP2b. 4 | 5 | ## Usage 6 | 7 | On a recent Beaglebone Debian image, access to the eQEP0 and eQEP2 channels should work out of the box, at least as root user. To ensure you can run the code as a regular user, read on the prerequisites section below. 8 | 9 | ```python 10 | from Adafruit_BBIO.Encoder import RotaryEncoder, eQEP2 11 | 12 | ''' 13 | Each channel can be accessed and initialized using its corresponding 14 | channel name constants: 15 | 16 | eQEP0 17 | eQEP1 # Pins only available when video is disabled 18 | eQEP2 19 | eQEP2b # Pins only available when video is disabled 20 | ''' 21 | 22 | # Instantiate the class to access channel eQEP2, and only initialize 23 | # that channel 24 | myEncoder = RotaryEncoder(eQEP2) 25 | 26 | # Get the current position 27 | cur_position = myEncoder.position 28 | 29 | # Position can also be set as a property 30 | next_position = 15 31 | myEncoder.position = next_position 32 | 33 | # Reset position to 0 34 | myEncoder.zero() 35 | 36 | # Change mode to relative (default is absolute) 37 | # You can use setAbsolute() to change back to absolute 38 | # Absolute: the position starts at zero and is incremented or 39 | # decremented by the encoder's movement 40 | # Relative: the position is reset when the unit timer overflows. 41 | myEncoder.setRelative() 42 | 43 | # Read the current mode (0: absolute, 1: relative) 44 | # Mode can also be set as a property 45 | mode = myEncoder.mode 46 | 47 | # Read the current frequency of update 48 | # Returned value is in Hz 49 | # If you want to set the frequency, specify it also in Hz 50 | freq = myEncoder.frequency 51 | 52 | # Disable your eQEP channel 53 | myEncoder.disable() 54 | 55 | # Check if the channel is enabled 56 | # The 'enabled' property is read-only 57 | # Use the enable() and disable() methods to 58 | # safely enable or disable the module 59 | isEnabled = myEncoder.enabled 60 | 61 | ``` 62 | 63 | If you need to use further channels, read on the prerequisites in the following section. 64 | 65 | ## Prerequisites 66 | 67 | ### Kernel and packages 68 | 69 | These instructions are based on: 70 | 71 | - Linux kernel: 4.4.x or later 72 | - `bb-cape-overlays` package: version 4.4.20171120.0-0rcnee1~stretch+20171120 or later 73 | - `bb-customizations` package: version 1.20171123-0rcnee0~stretch+20171123 or later 74 | 75 | It's recommended to run the following commands to ensure you have the latest required packages: 76 | 77 | ``` 78 | sudo apt update 79 | sudo apt upgrade bb-cape-overlays bb-customizations 80 | ``` 81 | 82 | ### User permissions 83 | 84 | In order to be able to run code that accesses the eQEP modules as a regular user, as opposed to root, that user must be part of the `eqep` group. 85 | 86 | To check which users are part of the `eqep` group: 87 | 88 | ``` 89 | cat /etc/group | grep eqep 90 | ``` 91 | 92 | To add user `userName` to the `eqep` group (run this command as root): 93 | ``` 94 | usermod -a -G eqep userName 95 | ``` 96 | 97 | Note: you will need to log out and log back in for the group membership change to take effect. 98 | 99 | ### Capes 100 | 101 | In order to use all eQEP pins the BeagleBone must boot with the [cape-universal](https://github.com/beagleboard/bb.org-overlays/tree/master/tools/beaglebone-universal-io) enabled, and load the `cape-universal` overlay. 102 | 103 | This is the default, thus **no further steps are initially required to use eQEP0 and eQEP2**. Simply double-check that the following line is present and not commented out on your `/boot/uEnv.txt` file: 104 | 105 | ``` 106 | enable_uboot_cape_universal=1 107 | ``` 108 | 109 | Note: Some older documentation recommends using the `cmdline` and `cape_enable` options instead. They are meant to load deprecated kernel-based overlays and it's not recommended to use them. Use the new way of [loading overlays via uboot](https://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays) instead, as instructed above. 110 | 111 | #### Enabling additional eQEP modules 112 | 113 | The `cape-universal` overlay will enable access to the eQEP0 and eQEP2 modules. As it does not expose pins that are shared with the HDMI interface, eQEP1 and eQEP2b will **not** be available. 114 | 115 | To disable the HDMI interface and gain access to the pins and peripherals that share its pins, comment out the following line on the `/boot/uEnv.txt` file and reboot: 116 | 117 | ``` 118 | disable_uboot_overlay_video=1 119 | ``` 120 | 121 | ## eQEP configuraton 122 | 123 | Notes: 124 | 125 | - If either eQEP1 or eQEP2b are used on the Beaglebone Black, video must be disabled, as their pins are shared with the LCD_DATAx lines of the HDMI interface. 126 | - eQEP2 and eQEP2b are the same module, but with the alternative of accessing it via two sets of pins. These are mutually exclusive. 127 | 128 | ### eQEP0 129 | 130 | Pins: `P9_27`, `P9_92` 131 | 132 | ``` 133 | $ config-pin P9_27 qep 134 | $ config-pin P9_92 qep # alias for P9_42.1 135 | $ cat /sys/devices/platform/ocp/48300000.epwmss/48300180.eqep/position 136 | ``` 137 | 138 | ### eQEP1 139 | 140 | Pins: `P8.33`, `P8.35` 141 | 142 | ``` 143 | $ config-pin P8.33 qep 144 | $ config-pin P8.35 qep 145 | $ cat /sys/devices/platform/ocp/48302000.epwmss/48302180.eqep/position 146 | ``` 147 | 148 | ### eQEP2 149 | 150 | #### eQEP2 151 | 152 | Pins: `P8.11`, `P8.12` 153 | 154 | ``` 155 | $ config-pin P8.11 qep 156 | $ config-pin P8.12 qep 157 | $ cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position 158 | ``` 159 | 160 | #### eQEP2b 161 | 162 | Note: alternate pins for eQEP2 (mutually exclusive) 163 | 164 | Pins: `P8.41`, `P8.42` 165 | 166 | ``` 167 | $ config-pin P8.41 qep 168 | $ config-pin P8.42 qep 169 | $ cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position 170 | ``` 171 | 172 | ## Credits 173 | 174 | Initially based on the [PyBBIO](https://github.com/graycatlabs/PyBBIO/bbio/libraries/RotaryEncoder/rotary_encoder.py) rotary encoder code. 175 | 176 | ## Further reading 177 | 178 | 1. [Beaglebone encoder inputs](https://github.com/Teknoman117/beaglebot/tree/master/encoders) 179 | 1. [Beaglebone eQEP overlays](https://github.com/Teknoman117/beaglebot/tree/master/encoders/dts) 180 | -------------------------------------------------------------------------------- /Adafruit_BBIO/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/adafruit-beaglebone-io-python/cf306ed7f9f24111d0949dd60ac232e81241bffe/Adafruit_BBIO/__init__.py -------------------------------------------------------------------------------- /Adafruit_BBIO/sysfs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- coding: utf-8 -*- 3 | 4 | # Copyright (c) 2014 MIT OpenCourseWare 5 | # Copyright (c) 2017 Adafruit Industries 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in 15 | # all copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | # Code originally published at http://stackoverflow.com/questions/4648792/ and 26 | # subsequently forked at https://github.com/ponycloud/python-sysfs 27 | # 28 | # Original author: Benedikt Reinartz 29 | # Contributors: 30 | # - Jan Dvořák 31 | # - Jonathon Reinhart https://github.com/JonathonReinhart 32 | # - Ondřej Koch 33 | # - David Planella 34 | 35 | """ 36 | Simplistic Python SysFS interface. It enables access to the sys filesystem device 37 | nodes and to get and set their exposed attributes. 38 | 39 | Usage examples:: 40 | from sysfs import sys 41 | 42 | # Print all block devices in /sys, with their sizes 43 | for block_dev in sys.block: 44 | print(block_dev, str(int(block_dev.size) / 1048576) + ' M') 45 | 46 | >>> import sysfs 47 | >>> # Read/write Beaglebone Black's eQEP module attributes 48 | >>> eqep0 = sysfs.Node("/sys/devices/platform/ocp/48300000.epwmss/48300180.eqep") 49 | >>> # Read eqep attributes 50 | >>> eqep0.enabled 51 | '1' 52 | >>> eqep0.mode 53 | '0' 54 | >>> eqep0.period 55 | '1000000000' 56 | >>> eqep0.position 57 | '0' 58 | >>> # Write eqep attributes. They should be strings. 59 | >>> eqep0.position = str(2) 60 | >>> eqep0.position 61 | '2' 62 | """ 63 | 64 | from os import listdir 65 | from os.path import isdir, isfile, join, realpath, basename 66 | 67 | __all__ = ['sys', 'Node'] 68 | 69 | 70 | class Node(object): 71 | __slots__ = ['_path_', '__dict__'] 72 | 73 | def __init__(self, path='/sys'): 74 | self._path_ = realpath(path) 75 | if not self._path_.startswith('/sys/') and not '/sys' == self._path_: 76 | raise RuntimeError('Using this on non-sysfs files is dangerous!') 77 | 78 | self.__dict__.update(dict.fromkeys(listdir(self._path_))) 79 | 80 | def __repr__(self): 81 | return '' % self._path_ 82 | 83 | def __str__(self): 84 | return basename(self._path_) 85 | 86 | def __setattr__(self, name, val): 87 | if name.startswith('_'): 88 | return object.__setattr__(self, name, val) 89 | 90 | path = realpath(join(self._path_, name)) 91 | if isfile(path): 92 | with open(path, 'w') as fp: 93 | fp.write(val) 94 | else: 95 | raise RuntimeError('Cannot write to non-files.') 96 | 97 | def __getattribute__(self, name): 98 | if name.startswith('_'): 99 | return object.__getattribute__(self, name) 100 | 101 | path = realpath(join(self._path_, name)) 102 | if isfile(path): 103 | with open(path, 'r') as fp: 104 | return fp.read().strip() 105 | elif isdir(path): 106 | return Node(path) 107 | 108 | def __setitem__(self, name, val): 109 | return setattr(self, name, val) 110 | 111 | def __getitem__(self, name): 112 | return getattr(self, name) 113 | 114 | def __iter__(self): 115 | return iter(getattr(self, name) for name in listdir(self._path_)) 116 | 117 | 118 | sys = Node() 119 | -------------------------------------------------------------------------------- /Adafruit_I2C.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | # WARNING: THIS MODULE IS DEPRECATED! 4 | # use Adafruit_GPIO.I2C instead: 5 | # https://github.com/adafruit/Adafruit_Python_GPIO/blob/master/Adafruit_GPIO/I2C.py 6 | 7 | class Adafruit_I2C : 8 | 9 | def __init__(self, address, busnum=-1, debug=False): 10 | print("WARNING: THIS MODULE IS DEPRECATED. Use Adafruit_GPIO.I2C instead.\n"); 11 | 12 | if __name__ == '__main__': 13 | print("WARNING: THIS MODULE IS DEPRECATED. Use Adafruit_GPIO.I2C instead.\n"); 14 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include distribute_setup.py 2 | include README.md 3 | include CHANGELOG.md 4 | recursive-include source *.h 5 | recursive-include overlays *.dts *.py 6 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | all: build3 # build2 build3 3 | 4 | time: 5 | /usr/bin/ntpdate -b -s -u pool.ntp.org 6 | 7 | publish: clean 8 | python setup.py sdist upload 9 | 10 | clean: cpp-clean 11 | rm -rf Adafruit_BBIO.* build dist 12 | rm -f *.pyo 13 | rm -f *.egg 14 | rm -f overlays/*.pyo overlays/*.pyc 15 | 16 | tests: 17 | py.test 18 | 19 | build: 20 | python setup.py build --force 21 | 22 | install: build 23 | python setup.py install --force 24 | 25 | build2: 26 | python2 setup.py build --force 27 | 28 | install2: build2 29 | python2 setup.py install --force 30 | 31 | build3: 32 | python3 setup.py build # --force 33 | 34 | install3: build3 35 | python3 setup.py install # --force 36 | 37 | ################################################################################ 38 | # c++ library 39 | # 40 | # sudo apt-get install automake 41 | # make cpp 42 | # cd build && sudo make install 43 | # 44 | # libgtest-dev is needed for UT 45 | # 46 | # sudo sh -c 'echo cape-universaln > /sys/devices/platform/bone_capemgr/slots' 47 | # sudo sh -c 'echo pwm > /sys/devices/platform/ocp/ocp\:P9_16_pinmux/state' 48 | # sudo sh -c 'echo pwm > /sys/devices/platform/ocp/ocp\:P8_19_pinmux/state' 49 | ################################################################################ 50 | configure: configure.ac 51 | rm -f configure && \ 52 | autoreconf --install -I m4 53 | 54 | build/Makefile: configure 55 | mkdir -p build && \ 56 | cd build && \ 57 | ../configure 58 | 59 | cpp: build/Makefile 60 | cd build && \ 61 | $(MAKE) build 62 | 63 | cpp-check: cpp 64 | cd build && \ 65 | $(MAKE) check 66 | 67 | cpp-install: cpp 68 | cd build && \ 69 | $(MAKE) install 70 | 71 | cpp-clean: 72 | rm -rf \ 73 | Makefile.in \ 74 | aclocal.m4 \ 75 | autom4te.cache/ \ 76 | compile \ 77 | configure \ 78 | config.guess \ 79 | config.h.in \ 80 | config.sub \ 81 | depcomp \ 82 | install-sh \ 83 | ltmain.sh \ 84 | m4/libtool.m4 \ 85 | m4/ltoptions.m4 \ 86 | m4/ltsugar.m4 \ 87 | m4/ltversion.m4 \ 88 | m4/lt~obsolete.m4 \ 89 | missing \ 90 | source/Makefile.in \ 91 | test-driver 92 | 93 | ################################################################################ 94 | 95 | .PHONY: all clean 96 | .PHONY: tests 97 | .PHONY: build install 98 | .PHONY: build2 install2 99 | .PHONY: build3 install3 100 | .PHONY: cpp cpp-install cpp-clean 101 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS = -I m4 2 | SUBDIRS = source -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Adafruit Beaglebone I/O Python API 2 | 3 | [![Documentation Status](https://readthedocs.org/projects/adafruit-beaglebone-io-python/badge/?version=latest)](http://adafruit-beaglebone-io-python.readthedocs.io/en/latest/?badge=latest) 4 | [![PyPI version](https://badge.fury.io/py/Adafruit_BBIO.svg)](https://badge.fury.io/py/Adafruit_BBIO) 5 | [![PyPI pyversions](https://img.shields.io/pypi/pyversions/Adafruit_BBIO.svg)](https://pypi.python.org/pypi/Adafruit_BBIO/) 6 | 7 | Adafruit BBIO is an API to enable [GPIO](README.md#gpio-setup), [PWM](README.md#pwm), [ADC](README.md#adc), [UART](README.md#uart), [SPI](README.md#spi) and [eQEP](README.md#eqep) (Quadrature Encoder) hardware access from Python applications running on the Beaglebone. 8 | 9 | * It is recommended to use an [official BeagleBoard.org Debian image](https://beagleboard.org/latest-images) 10 | * **Currently recommended image: [Debian 10.3 "Buster" IoT (2020-04-06)](http://beagleboard.org/latest-images)** _(default kernel is 4.19.x-ti)_ 11 | 12 | * Adafruit_BBIO supports Linux kernels 3.8 through 4.19 13 | 14 | * New versions of Adafruit_BBIO may break backwards compatibility. Please read the [changelog](CHANGELOG.md). 15 | 16 | * It is recommended to use Python 3 17 | 18 | ## Installation on Debian 19 | 20 | Note: Follow the instructions on BeagleBoard.org to [get connected to the Internet](https://beagleboard.org/upgrade#connect) 21 | 22 | **Easiest:** 23 | ``` 24 | sudo apt-get update 25 | sudo apt-get install build-essential python3-dev python3-pip -y 26 | sudo pip3 install Adafruit_BBIO 27 | ``` 28 | 29 | **Manual:** 30 | ``` 31 | sudo apt-get update 32 | sudo apt-get install build-essential python3-dev python3-pip -y 33 | git clone git://github.com/adafruit/adafruit-beaglebone-io-python.git 34 | cd adafruit-beaglebone-io-python 35 | sudo python3 setup.py install 36 | ``` 37 | 38 | Upgrade Adafruit_BBIO to latest version on [PyPI](https://pypi.python.org/pypi/Adafruit_BBIO): 39 | ``` 40 | sudo pip3 install --upgrade Adafruit_BBIO 41 | ``` 42 | 43 | ## Usage 44 | 45 | Using the library is very similar to the excellent RPi.GPIO library used on the Raspberry Pi. Below are some examples. 46 | 47 | ### Pin Numbers 48 | 49 | Please note that there is no '0' prefix for the pin numbers. For example, pin 7 on header P8 is `P8_7`. 50 | 51 | **Correct:** 52 | ``` 53 | GPIO.setup("P8_7", OUT ) 54 | ``` 55 | 56 | **INCORRECT:** 57 | ``` 58 | GPIO.setup("P8_07", OUT ) 59 | ``` 60 | 61 | Refer to `pins_t table[]` in [common.c](https://github.com/adafruit/adafruit-beaglebone-io-python/blob/master/source/common.c#L73) all the pin labels. 62 | 63 | ### config-pin 64 | 65 | [config-pin](https://github.com/beagleboard/bb.org-overlays/tree/master/tools/beaglebone-universal-io) is now used on the official BeagleBoard.org Debian Jessie and Stretch images to control pin mode (e.g. pin mux). 66 | 67 | ``` 68 | debian@beaglebone:~$ config-pin -q P9_14 69 | P9_14 Mode: pwm 70 | 71 | debian@beaglebone:~$ config-pin -l P9_14 72 | default gpio gpio_pu gpio_pd pwm 73 | 74 | debian@beaglebone:~$ config-pin P9_14 gpio 75 | 76 | debian@beaglebone:~$ config-pin -q P9_14 77 | P9_14 Mode: gpio Direction: in Value: 0 78 | 79 | debian@beaglebone:~$ config-pin P9_14 pwm 80 | 81 | debian@beaglebone:~$ config-pin -q P9_14 82 | P9_14 Mode: pwm 83 | ``` 84 | 85 | ### GPIO Setup 86 | 87 | Import the library, and setup as GPIO.OUT or GPIO.IN:: 88 | 89 | import Adafruit_BBIO.GPIO as GPIO 90 | GPIO.setup("P8_14", GPIO.OUT) 91 | 92 | You can also refer to the pin names:: 93 | 94 | GPIO.setup("GPIO0_26", GPIO.OUT) 95 | 96 | ### GPIO Output 97 | 98 | Setup the pin for output, and write GPIO.HIGH or GPIO.LOW. Or you can use 1 or 0.:: 99 | 100 | import Adafruit_BBIO.GPIO as GPIO 101 | GPIO.setup("P8_14", GPIO.OUT) 102 | GPIO.output("P8_14", GPIO.HIGH) 103 | 104 | ### On-Board LEDs 105 | 106 | On-board LEDs (USR0-USR3) are handled by LED class driver rather than the GPIO pin driver. 107 | 108 | They have a different path in the /sys/ filesystem. 109 | 110 | Setup the pin for output and write GPIO.HIGH or GPIO.LOW:: 111 | 112 | import Adafruit_BBIO.GPIO as GPIO 113 | import time 114 | 115 | for i in range(4): 116 | GPIO.setup("USR%d" % i, GPIO.OUT) 117 | 118 | while True: 119 | for i in range(4): 120 | GPIO.output("USR%d" % i, GPIO.HIGH) 121 | time.sleep(1) 122 | for i in range(4): 123 | GPIO.output("USR%d" % i, GPIO.LOW) 124 | time.sleep(1) 125 | 126 | ### GPIO Input 127 | 128 | Inputs work similarly to outputs.: 129 | 130 | import Adafruit_BBIO.GPIO as GPIO 131 | GPIO.setup("P8_14", GPIO.IN) 132 | 133 | Polling inputs: 134 | 135 | if GPIO.input("P8_14"): 136 | print("HIGH") 137 | else: 138 | print("LOW") 139 | 140 | Waiting for an edge (GPIO.RISING, GPIO.FALLING, or GPIO.BOTH: 141 | 142 | GPIO.wait_for_edge(channel, GPIO.RISING) 143 | 144 | or 145 | 146 | GPIO.wait_for_edge(channel, GPIO.RISING, timeout) 147 | 148 | Detecting events: 149 | 150 | GPIO.add_event_detect("P9_12", GPIO.FALLING) 151 | #your amazing code here 152 | #detect wherever: 153 | if GPIO.event_detected("P9_12"): 154 | print("event detected!") 155 | 156 | ### PWM 157 | **The PWM Duty Cycle range was reversed in 0.0.15 from 100(off)-0(on) to 0(off)-100(on). Please update your code accordingly.** 158 | 159 | import Adafruit_BBIO.PWM as PWM 160 | #PWM.start(channel, duty, freq=2000, polarity=0) 161 | #duty values are valid 0 (off) to 100 (on) 162 | PWM.start("P9_14", 50) 163 | PWM.set_duty_cycle("P9_14", 25.5) 164 | PWM.set_frequency("P9_14", 10) 165 | 166 | PWM.stop("P9_14") 167 | PWM.cleanup() 168 | 169 | #set polarity to 1 on start: 170 | PWM.start("P9_14", 50, 2000, 1) 171 | 172 | ### ADC 173 | 174 | import Adafruit_BBIO.ADC as ADC 175 | ADC.setup() 176 | 177 | #read returns values 0-1.0 178 | value = ADC.read("P9_40") 179 | 180 | #read_raw returns non-normalized value 181 | value = ADC.read_raw("P9_40") 182 | 183 | ### [UART](https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/uart) 184 | * Use [`config-pin` to set pin mode](https://github.com/beagleboard/bb.org-overlays/tree/master/tools/beaglebone-universal-io) for [UART1 and UART2 pins](http://beagleboard.org/static/images/cape-headers-serial.png) 185 | ``` 186 | config-pin P9.21 uart # UART2_TXD 187 | config-pin P9.22 uart # UART2_RXD 188 | config-pin P9.24 uart # UART1_TXD 189 | config-pin P9.26 uart # UART1_RXD 190 | ``` 191 | * [Install pyserial](https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/uart#using-uart-with-python) 192 | ``` 193 | sudo pip install pyserial 194 | ``` 195 | * [Test UART1](https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/uart#using-uart-with-python) 196 | ``` 197 | import Adafruit_BBIO.UART as UART 198 | import serial 199 | 200 | UART.setup("UART1") 201 | 202 | with serial.Serial(port = "/dev/ttyO1", baudrate=9600) as ser: 203 | print("Serial is open!") 204 | ser.write(b"Hello World!") 205 | 206 | ``` 207 | * Available UART names on BeagleBone 208 | * `UART1`: /dev/ttyO1, Rx: P9_26, Tx: P9_24 209 | * `UART2`: /dev/ttyO2, Rx: P9_22, Tx: P9_21 210 | * `UART4`: /dev/ttyO4, Rx: P9_11, Tx: P9_13 211 | * `UART5`: /dev/ttyO5, Rx: P8_38, Tx: P8_37 212 | * note: `UART5` requires `disable_uboot_overlay_video=1` in `/boot/uEnv.txt` 213 | * Available UART names on PocketBeagle 214 | * `PB-UART0`: /dev/ttyO0, Rx: P1_30, Tx: P1_32 215 | * `PB-UART1`: /dev/ttyO1, Rx: P2_11, Tx: P2_09 216 | * `PB-UART2`: /dev/ttyO2, Rx: P1_08, Tx: P1_10 217 | * [Loopback test with UART1 and UART2](https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/uart#testing-and-using-the-uart) 218 | 219 | 220 | ### [SPI](https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/spi) 221 | * Use [`config-pin` to set pin mode](https://github.com/beagleboard/bb.org-overlays/tree/master/tools/beaglebone-universal-io) for [SPI pins](http://beagleboard.org/static/images/cape-headers-spi.png) 222 | * SPI0 223 | * SPI0_CS0: `config-pin p9.17 spi_cs` 224 | * SPI0_D0: `config-pin p9.21 spi` 225 | * SPI0_D1: `config-pin p9.18 spi` 226 | * SPI0_SCLK: `config-pin p9.22 spi_sclk` 227 | * SPI1 228 | * SPI1_CS0: `config-pin p9.20 spi_cs` 229 | * SPI1_CS0: `config-pin p9.28 spi_cs` 230 | * SPI1_CS1: `config-pin p9.19 spi_cs` 231 | * SPI1_CS1: `config-pin p9.42 spi_cs` 232 | * SPI1_D0: `config-pin p9.29 spi` 233 | * SPI1_D1: `config-pin p9.30 spi` 234 | * SPI1_SCLK: `config-pin p9.31 spi_sclk` 235 | * Example: 236 | ``` 237 | from Adafruit_BBIO.SPI import SPI 238 | #spi = SPI(bus, device) #/dev/spidev. 239 | 240 | # /dev/spidev0.0 241 | spi = SPI(1,0) 242 | print(spi.xfer2([32, 11, 110, 22, 220])) 243 | spi.close() 244 | 245 | # /dev/spidev0.1 246 | spi = SPI(1,1) 247 | print(spi.xfer2([32, 11, 110, 22, 220])) 248 | spi.close() 249 | 250 | # /dev/spidev1.0 251 | spi = SPI(2,0) 252 | print(spi.xfer2([32, 11, 110, 22, 220])) 253 | spi.close() 254 | 255 | # /dev/spidev1.1 256 | spi = SPI(2,1) 257 | print(spi.xfer2([32, 11, 110, 22, 220])) 258 | spi.close() 259 | ``` 260 | 261 | ### eQEP 262 | 263 | To use the enhanced Quadrature Encoder Pulse (eQEP) module, please refer to the [`Encoder` module's documentation](https://github.com/adafruit/adafruit-beaglebone-io-python/tree/master/Adafruit_BBIO#usage). 264 | 265 | ## Running tests 266 | 267 | Install py.test to run the tests. You'll also need the python compiler package for pytest: 268 | ``` 269 | sudo pip3 install pytest 270 | ``` 271 | Execute the following in the root of the project: 272 | ``` 273 | pytest 274 | ``` 275 | NOTE: `sudo` should not be required as udev configures group ownership and permission for [GPIO](https://github.com/rcn-ee/repos/blob/master/bb-customizations/suite/stretch/debian/80-gpio-noroot.rules) and [PWM](https://github.com/rcn-ee/repos/blob/master/bb-customizations/suite/stretch/debian/81-pwm-noroot.rules) 276 | 277 | ## Reporting issues 278 | 279 | When reporting issues, plesae run the following script which will print the system configuration: 280 | ``` 281 | sudo /opt/scripts/tools/version.sh 282 | ``` 283 | and paste the output in a reply. 284 | 285 | This script should be present for any Debian or Ubunut image downloaded from: 286 | https://beagleboard.org/ or https://rcn-ee.com/ 287 | 288 | 289 | ## Credits 290 | 291 | The BeagleBone IO Python library was originally forked from the excellent MIT Licensed [RPi.GPIO](https://code.google.com/p/raspberry-gpio-python) library written by Ben Croston. 292 | 293 | ## License 294 | 295 | Written by Justin Cooper, Adafruit Industries. BeagleBone IO Python library is released under the MIT License. 296 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_INIT([Adafruit BeagleBone IO Library], 2 | [1.0.0], 3 | [https://github.com/adafruit/adafruit-beaglebone-io-python/issues], 4 | [adafruit-bbio]) 5 | 6 | AC_PREREQ([2.59]) 7 | #AC_CONFIG_SRCDIR([./LICENSE]) 8 | AC_CONFIG_MACRO_DIR([m4]) 9 | AC_CONFIG_HEADERS([config.h]) 10 | AC_CONFIG_FILES([Makefile source/Makefile]) 11 | 12 | AM_INIT_AUTOMAKE([1.9 dist-bzip2 dist-zip foreign subdir-objects -Wall]) 13 | AM_PROG_AR 14 | 15 | LT_INIT 16 | 17 | AC_PROG_CC 18 | AC_PROG_CXX 19 | AC_LANG([C]) 20 | AC_LANG([C++]) 21 | 22 | CHECK_GTEST 23 | CHECK_KERNEL_RELEASE 24 | 25 | AC_OUTPUT 26 | -------------------------------------------------------------------------------- /docs/ADC.rst: -------------------------------------------------------------------------------- 1 | :mod:`ADC` --- A/D Converter input interface 2 | -------------------------------------------- 3 | 4 | This module enables reading analog input values from the analog to digital 5 | converter (ADC) on the TI AM3358 SoC on the BeagleBone. 6 | 7 | Example:: 8 | 9 | import Adafruit_BBIO.ADC as ADC 10 | 11 | ADC.setup() 12 | 13 | # The read method returns normalized values from 0 to 1.0 14 | value = ADC.read("P9_40") 15 | 16 | # The read_raw returns non-normalized values from 0 to 4095 17 | value = ADC.read_raw("P9_40") 18 | 19 | .. module:: Adafruit_BBIO.ADC 20 | 21 | .. function:: setup_adc() 22 | 23 | Setup and start the ADC hardware. 24 | 25 | .. function:: setup_read(channel) 26 | 27 | Read the normalized analog value for the channel. 28 | 29 | :param str channel: GPIO channel to read the value from (e.g. "P8_16"). 30 | :returns: normalized value reading from 0.0 to 1.0 31 | :rtype: float 32 | 33 | 34 | .. function:: setup_read_raw(channel) 35 | 36 | Read the raw analog value for the channel. 37 | 38 | :note: Kernels older than 4.1.x returned a raw value range 0 - 1800 39 | based on the reference voltage of 1.8 V. 40 | 41 | :param str channel: GPIO channel to read the value from (e.g. "P8_16"). 42 | :returns: raw value reading from 0 to 4095 (12 bits). 43 | :rtype: float 44 | 45 | 46 | -------------------------------------------------------------------------------- /docs/Encoder.rst: -------------------------------------------------------------------------------- 1 | :mod:`Encoder` --- Quadrature Encoder interface (eQEP) 2 | ----------------------------------------------- 3 | 4 | .. automodule:: Adafruit_BBIO.Encoder 5 | :members: 6 | -------------------------------------------------------------------------------- /docs/GPIO.rst: -------------------------------------------------------------------------------- 1 | :mod:`GPIO` --- General Purpose I/O interface 2 | --------------------------------------------- 3 | 4 | This module provides access and control of pins set up as General Purpose 5 | I/O (GPIO). 6 | 7 | .. note:: 8 | 9 | You need to be part of the ``gpio`` group of the OS running on the 10 | Beaglebone to be able to run GPIO code as a non-root user. The default 11 | user created upon the Debian image installation should already be 12 | part of the group. Otherwise, you can use 13 | ``sudo usermod -a -G gpio userName`` to add ``userName`` to the group. 14 | 15 | .. note:: 16 | 17 | When coding with this module, you will be using pin names for 18 | better readability. As such, you can specify them in the header 8 or 9 19 | form (e.g. "P8_16") or in pin name form (e.g. "GPIO1_14"). 20 | For easy reference, you can use the 21 | `Beaglebone pin names table `_ 22 | 23 | 24 | .. note:: 25 | 26 | On-board LEDs (USR0-USR3) are handled by LED class driver rather than the GPIO pin driver. 27 | 28 | They have a different path in the /sys/ filesystem. 29 | 30 | Setup the pin for output and write GPIO.HIGH or GPIO.LOW 31 | 32 | Example:: 33 | 34 | # Use the config-pin command line tool to set a pin's function to GPIO 35 | # Then you can control it with the GPIO module from Python 36 | config-pin P9_14 gpio 37 | 38 | import Adafruit_BBIO.GPIO as GPIO 39 | 40 | # Set up pins as inputs or outputs 41 | GPIO.setup("P8_13", GPIO.IN) 42 | GPIO.setup("P8_14", GPIO.OUT) 43 | GPIO.setup("GPIO0_26", GPIO.OUT) # Alternative: use actual pin names 44 | 45 | # Write a logic high or logic low 46 | GPIO.output("P8_14", GPIO.HIGH) # You can also write '1' instead 47 | GPIO.output("P8_14", GPIO.LOW) # You can also write '0' instead 48 | 49 | 50 | # Blinking onboard led example 51 | import Adafruit_BBIO.GPIO as GPIO 52 | import time 53 | 54 | for i in range(4): 55 | GPIO.setup("USR%d" % i, GPIO.OUT) 56 | 57 | while True: 58 | for i in range(4): 59 | GPIO.output("USR%d" % i, GPIO.HIGH) 60 | time.sleep(1) 61 | for i in range(4): 62 | GPIO.output("USR%d" % i, GPIO.LOW) 63 | time.sleep(1) 64 | 65 | 66 | .. module:: Adafruit_BBIO.GPIO 67 | 68 | .. function:: setup(channel, direction[, pull_up_down=GPIO.PUD_OFF, initial=None, delay=0]) 69 | 70 | Set up the given GPIO channel, its direction and (optional) pull/up down control 71 | 72 | :param str channel: GPIO channel to set up (e.g. "P8_16"). 73 | :param int direction: GPIO channel direction 74 | (:data:`GPIO.IN` or :data:`GPIO.OUT`). 75 | :param int pull_up_down: pull-up/pull-down resistor configuration 76 | (:data:`GPIO.PUD_OFF`, :data:`GPIO.PUD_UP` or :data:`GPIO.PUD_DOWN`). 77 | :param int initial: initial value for an output channel 78 | (:data:`GPIO.LOW`/:data:`GPIO.HIGH`). 79 | :param int delay: time in milliseconds to wait after exporting the GPIO pin. 80 | 81 | .. function:: cleanup() 82 | 83 | Clean up by resetting all GPIO channels that have been used by 84 | the application to :data:`IN` with no pullup/pulldown and no event 85 | detection. 86 | 87 | :note: It's recommended that you call this function upon exiting your 88 | application. 89 | 90 | .. function:: output(channel, value) 91 | 92 | Set the given output channel to the given digital value. 93 | 94 | :param str channel: GPIO channel to output the value to (e.g. "P8_16"). 95 | :param value: value to set the output to-- 0/1 or False/True 96 | or :data:`GPIO.LOW`/:data:`GPIO.HIGH`. 97 | :type value: int or bool 98 | 99 | .. function:: input(channel) 100 | 101 | Get the given input channel's digital value. 102 | 103 | :param str channel: GPIO channel to read the value from (e.g. "P8_16"). 104 | :returns: Channel value–– 0 or 1. 105 | :rtype: int 106 | 107 | .. function:: add_event_detect(channel, edge[, callback=None, bouncetime=0]) 108 | 109 | Enable edge detection events for the given GPIO channel. 110 | 111 | :param str channel: GPIO channel to detect events from (e.g. "P8_16"). 112 | :param int edge: edge to detect–– :data:`GPIO.RISING`, :data:`GPIO.FALLING` 113 | or :data:`GPIO.BOTH` 114 | :param func callback: a function to call once the event has been detected. 115 | :param int bouncetime: switch bounce timeout in ms for the callback. 116 | 117 | .. function:: remove_event_detect(channel) 118 | 119 | Remove edge detection for the given GPIO channel. 120 | 121 | :param str channel: GPIO channel to remove event detection 122 | from (e.g. "P8_16"). 123 | 124 | .. function:: event_detected(channel) 125 | 126 | Checks if an edge event has occured on a given GPIO. 127 | 128 | :note: You need to enable edge detection using :func:`add_event_detect()` first. 129 | 130 | :param str channel: GPIO channel to check for event detection 131 | for (e.g. "P8_16"). 132 | :returns: True if an edge has occured on a given GPIO, False otherwise 133 | :rtype: bool 134 | 135 | .. function:: add_event_callback(channel, callback[, bouncetime=0]) 136 | 137 | Add a callback for an event already defined using :func:`add_event_detect()` 138 | 139 | :param str channel: GPIO channel to add a callback to (e.g. "P8_16"). 140 | :param func callback: a function to call once the event has been detected. 141 | :param int bouncetime: switch bounce timeout in ms for the callback. 142 | 143 | .. function:: wait_for_edge(channel, edge[, timeout=-1]) 144 | 145 | Wait for an edge on the given channel. 146 | 147 | :param str channel: GPIO channel to wait on (e.g. "P8_16"). 148 | :param int edge: edge to detect–– :data:`GPIO.RISING`, :data:`GPIO.FALLING` 149 | or :data:`GPIO.BOTH` 150 | :param int timeout: time to wait for an edge, in milliseconds. 151 | -1 will wait forever. 152 | 153 | .. function:: gpio_function(channel) 154 | 155 | Return the current GPIO function 156 | (:data:`IN`, :data:`IN`, :data:`ALT0`) of the given pin. 157 | 158 | :warning: Currently only returning the direction of the 159 | pin (input or output) is supported. 160 | 161 | :param str channel: GPIO pin to query the status of. 162 | :returns: 0 if :data:`IN`, 1 if :data:`OUT` 163 | :rtype: int 164 | 165 | .. function:: setwarnings(gpio_warnings) 166 | 167 | Enable or disable GPIO warning messages. 168 | 169 | :warning: Currently enabling or disabling warnings 170 | has no effect. 171 | 172 | :param int gpio_warnings: 0–– disable warnings; 1–– enable warnings 173 | 174 | .. attribute:: ALT0 175 | 176 | Pin mode-- alternate function 0. 177 | 178 | .. attribute:: BOTH 179 | 180 | Edge detection-- detect both edges. 181 | 182 | .. attribute:: FALLING 183 | 184 | Edge detection-- detect falling edge. 185 | 186 | .. attribute:: HIGH 187 | 188 | Pin status-- logic low. 189 | 190 | .. attribute:: IN 191 | 192 | Pin mode-- input. 193 | 194 | .. attribute:: LOW 195 | 196 | Pin status-- logic low. 197 | 198 | .. attribute:: OUT 199 | 200 | Pin mode-- output. 201 | 202 | .. attribute:: PUD_OFF 203 | 204 | Pull-up/pull-down resistor type-- no pull-up/pull-down. 205 | 206 | .. attribute:: PUD_DOWN 207 | 208 | Pull-up/pull-down resistor type-- pull-down. 209 | 210 | .. attribute:: PUD_UP 211 | 212 | Pull-up/pull-down resistor type-- pull-up. 213 | 214 | .. attribute:: RISING 215 | 216 | Edge detection-- detect rising edge. 217 | 218 | .. attribute:: VERSION 219 | 220 | GPIO module version. Currently unused. 221 | 222 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = Adafruit-BBIO 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/PWM.rst: -------------------------------------------------------------------------------- 1 | :mod:`PWM` --- Pulse Width Modulation interface 2 | ----------------------------------------------- 3 | 4 | Enables access to the Pulse Width Modulation (PWM) module, to easily and 5 | accurately generate a PWM output signal of a given duty cycle and 6 | frequency. 7 | 8 | .. note:: 9 | 10 | You need to be part of the ``pwm`` group of the OS running on the 11 | Beaglebone to be able to run PWM code as a non-root user. The default 12 | user created upon the Debian image installation should already be 13 | part of the group. Otherwise, you can use 14 | ``sudo usermod -a -G pwm userName`` to add ``userName`` to the group. 15 | 16 | .. module:: Adafruit_BBIO.PWM 17 | 18 | .. function:: start(channel, duty_cycle[, frequency=2000, polarity=0]) 19 | 20 | Set up and start the given PWM channel. 21 | 22 | :param str channel: PWM channel. It can be specified in the form 23 | of of 'P8_10', or 'EHRPWM2A'. 24 | :param int duty_cycle: PWM duty cycle. It must have a value from 0 to 100. 25 | :param int frequency: PWM frequency, in Hz. It must be greater than 0. 26 | :param int polarity: defines whether the value for ``duty_cycle`` affects the 27 | rising edge or the falling edge of the waveform. Allowed values -- 0 28 | (rising edge, default) or 1 (falling edge). 29 | 30 | .. function:: stop(channel) 31 | 32 | Stop the given PWM channel. 33 | 34 | :param str channel: PWM channel. It can be specified in the form 35 | of of 'P8_10', or 'EHRPWM2A'. 36 | 37 | .. function:: set_duty_cycle(channel, duty_cycle) 38 | 39 | Change the duty cycle of the given PWM channel. 40 | 41 | :note: You must have started the PWM channel with :func:`start()` 42 | once, before changing the duty cycle. 43 | 44 | :param str channel: PWM channel. It can be specified in the form 45 | of of 'P8_10', or 'EHRPWM2A'. 46 | :param int duty_cycle: PWM duty cycle. It must have a value from 0 to 100. 47 | 48 | .. function:: set_frequency(channel, frequency) 49 | 50 | Change the frequency of the given PWM channel. 51 | 52 | :note: You must have started the PWM channel with :func:`start()` 53 | once, before changing the frequency. 54 | 55 | :param str channel: PWM channel. It can be specified in the form 56 | of of 'P8_10', or 'EHRPWM2A'. 57 | :param int frequency: PWM frequency. It must be greater than 0. 58 | 59 | .. function:: cleanup() 60 | 61 | Clean up by resetting all GPIO channels that have been used by this 62 | program to INPUT, with no pullup/pulldown and no event detection. 63 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Generating API documentation 2 | 3 | This folder contains the required files to automatically generate the Adafruit Beaglebone I/O Python API documentation, partly from the code docstrings and partly from files in reStructuredText format. 4 | 5 | ``` 6 | ├── conf.py <- Sphinx configuration file 7 | ├── index.rst <- Documentation will be generated based on the master index 8 | └── Makefile <- Auxiliary Makefile to build documentation 9 | ``` 10 | 11 | The tools used are [Sphinx](http://www.sphinx-doc.org) to extract the documentation and publish it in HTML format for online viewing, in combination with [Readthedocs](http://readthedocs.io). Readthedocs automatically executes Sphinx via webhooks triggered by Github commits, and publishes the resulting docs for all tracked branches or tags. Generally Readthedocs will be set up to track stable release tags and the master branch. 12 | 13 | ## Building the documentation 14 | 15 | The documentation can also be built on a local checkout of the project: 16 | 17 | First ensure you've got sphinx installed: 18 | 19 | ``` 20 | sudo pip install sphinx 21 | ``` 22 | 23 | Then you can build the HTML docs: 24 | 25 | ``` 26 | cd docs 27 | make html 28 | ``` 29 | 30 | Once Sphinx has built the documentation, you can open the main index file with your browser: `_build/html/index.html` 31 | 32 | Notes: 33 | 34 | - The build process will create three additional temporary directories: `_build`, `_static` and `_templates` that will not be version-controlled. You can use `make clean` to remove their contents if you wish to do so. 35 | - The html theme from files built locally is different from the online readthedocs theme. See the `docs/config.py` `html_theme` variable. The main reason is not to introduce another dependency to install the readthedocs theme, but as a side effect, it also helps visually distinguishing the locally-built documentation from the online version. 36 | 37 | ## Readthedocs maintenance 38 | 39 | At every release that includes documenation (most probably 1.0.10 will be the first one), the release's branch or tag needs to be selected in the web UI and marked as active. 40 | 41 | After this, documentation will automatically be generated and published for that release. It will be available at the same URL as the main documentation, and a link with the version number will be shown, where it can be accessed from. 42 | 43 | Optionally, the 'stable' URL slug can be pointed to that release branch. Otherwise, the 'stable' slug can also be deactivated for less maintenance overhead. 44 | 45 | The 'latest' URL slug will always be pointing at the repo's master branch. 46 | 47 | ## Notes 48 | 49 | Ideally, all API documentation would be written in the source files as Python docstrings, and sphinx would simply extract it. This is actually the case with the `Encoder` module, which is pure Python. 50 | 51 | However, most of the code is written as C extensions. While they do provide docstrings once they are built, Sphinx does not natively support extracting them. There is [a workaround](https://stackoverflow.com/a/30110104/9022675) to do this, but it involves first building the extensions, installing them and hardcoding a path. While it might work for locally-built documentation, it's unlikely that readthedocs support this option. 52 | 53 | For the sake of keeping things simple and with less maintenance, the approach of documenting the C-generated API in separate `.rst` files (one for each Python module) has been taken. 54 | 55 | This has the advantage of having a definition of the API in one place, but it also poses the disadvantage of some duplication, as the C modules do define some docstrings for their objects. Then again, the API itself has hardly changed in the last few years, and the Beaglebone is a mature platform, so it's unlikely that this will add a significant maintenance overhead. 56 | 57 | - The documentation in the `.rst` files is written in [reStructuredText](http://docutils.sourceforge.net/rst.html), extended with Sphinx markup for defining the objects. 58 | - The documentation in Python modules follows the Google readable docstring markup, which also builds upon reStructuredText and is fully supported by Sphinx. 59 | 60 | ## Further reference 61 | 62 | - [Google readable docstring markup](https://google.github.io/styleguide/pyguide.html?showone=Comments#Comments) 63 | - [Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) 64 | - [More Google docstring examples](http://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_google.html) 65 | - [Sphinx docstring markup](http://www.sphinx-doc.org/en/stable/domains.html#the-python-domain) 66 | - [reStructuredText primer](http://www.sphinx-doc.org/en/stable/rest.html#rst-primer) 67 | 68 | 69 | -------------------------------------------------------------------------------- /docs/SPI.rst: -------------------------------------------------------------------------------- 1 | :mod:`SPI` --- Serial Peripheral Interface 2 | ------------------------------------------ 3 | 4 | This module defines an object type that allows Serial Peripheral Interface 5 | (SPI) bus transactions on hosts running the Linux kernel. The host kernel 6 | must have SPI support and SPI device interface support. 7 | 8 | Because the SPI device interface is opened R/W, users of this module 9 | usually must have root permissions or be members of a group with granted 10 | access rights. 11 | 12 | Pins used for SPI0 and SPI1 13 | +++++++++++++++++++++++++++ 14 | 15 | ==== ===== ===== ===== ===== 16 | PORT CS0 DO DI SCLK 17 | ==== ===== ===== ===== ===== 18 | SPI0 P9_17 P9_21 P9_18 P9_22 19 | SPI1 P9_28 P9_29 P9_30 P9_31 20 | ==== ===== ===== ===== ===== 21 | 22 | Example:: 23 | 24 | import Adafruit_BBIO.SPI as SPI 25 | 26 | from Adafruit_BBIO.SPI import SPI 27 | # spi = SPI(bus, device) #/dev/spidev. 28 | 29 | # /dev/spidev0.0 30 | spi = SPI(0, 0) 31 | print(spi.xfer2([32, 11, 110, 22, 220])) 32 | spi.close() 33 | 34 | # /dev/spidev0.1 35 | spi = SPI(0, 1) 36 | print(spi.xfer2([32, 11, 110, 22, 220])) 37 | spi.close() 38 | 39 | # /dev/spidev1.0 40 | spi = SPI(1, 0) 41 | print(spi.xfer2([32, 11, 110, 22, 220])) 42 | spi.close() 43 | 44 | # /dev/spidev1.1 45 | spi = SPI(1, 1) 46 | print(spi.xfer2([32, 11, 110, 22, 220])) 47 | spi.close() 48 | 49 | .. module:: Adafruit_BBIO.SPI 50 | 51 | .. class:: SPI(bus, client) 52 | 53 | :param bus: bus number. 54 | :param client: client device number. 55 | :returns: a new SPI object, optionally connected to the specified SPI 56 | device interface. 57 | :rtype: :class:`SPI` 58 | 59 | .. attribute:: bpw 60 | 61 | Bits per word. 62 | 63 | .. attribute:: cshigh 64 | 65 | Chip Select (CS or Slave Select, SS) active high. 66 | 67 | .. attribute:: loop 68 | 69 | Loopback configuration. 70 | 71 | .. attribute:: lsbfirst 72 | 73 | Least Significant Bit (LSB) first. 74 | 75 | .. attribute:: mode 76 | 77 | SPI mode as two bit pattern of Clock Polarity and Phase [CPOL|CPHA]; min-- 0b00 = 0, max-- 0b11 = 3. 78 | 79 | .. attribute:: msh 80 | 81 | Maximum speed in Hz. 82 | 83 | .. attribute:: threewire 84 | 85 | SI/SO signals are shared. 86 | 87 | .. method:: open(bus, device) 88 | 89 | Connects the object to the specified SPI device. `open(X, Y)` will open 90 | `/dev/spidev-X.Y` 91 | 92 | :param int bus: bus number 93 | :param str device: device number 94 | 95 | .. method:: close() 96 | 97 | Disconnects the object from the interface. 98 | 99 | .. method:: readbytes(len) 100 | 101 | Read the specified length of bytes from the SPI device. 102 | 103 | :param int len: length of bytes to read, 1024 maximum. 104 | :returns: values read 105 | :rtype: list[int] 106 | 107 | .. method:: writebytes(values) 108 | 109 | Write bytes to the SPI device. 110 | 111 | :param values: list of values to write, with a maximum length of 1024. 112 | :type values: list[int] 113 | 114 | .. method:: xfer(values[,delay=0]) 115 | 116 | Perform an SPI transaction of values. Slave Select (SS or CS) will be 117 | released and reactivated between blocks. 118 | 119 | :param values: list of values to transfer, with a maximum length of 1024. 120 | :type values: list[int] 121 | :param delay: delay in microseconds between blocks. 122 | :returns: values transferred 123 | :rtype: list[int] 124 | 125 | .. method:: xfer2(values) 126 | 127 | Perform an SPI transaction of values. Slave Select (SS or CS) will be 128 | held active between blocks. 129 | 130 | :param values: list of values to transfer, with a maximum length of 1024. 131 | :type values: list[int] 132 | :returns: values transferred 133 | :rtype: list[int] 134 | 135 | -------------------------------------------------------------------------------- /docs/UART.rst: -------------------------------------------------------------------------------- 1 | :mod:`UART` --- UART communications interface 2 | --------------------------------------------- 3 | 4 | UART functionality of a BeagleBone using Python. Generally used to set up 5 | and grant access to a given UART device, which will then be accessed by 6 | other software or modules (e.g. `pyserial`):: 7 | 8 | sudo pip install pyserial 9 | 10 | Example:: 11 | 12 | import Adafruit_BBIO.UART as UART 13 | import serial 14 | 15 | UART.setup("UART1") 16 | 17 | with serial.Serial(port = "/dev/ttyO1", baudrate=9600) as ser: 18 | print("Serial is open!") 19 | ser.write(b"Hello World!") 20 | 21 | .. module:: Adafruit_BBIO.UART 22 | 23 | .. function:: setup_uart(channel) 24 | 25 | Set up and start the UART channel. This function will effectively export 26 | the given UART so that it can be accessed by other software that controls 27 | its serial lines. 28 | 29 | :param str channel: UART channel to set up. One of "UART1", "UART2", 30 | "UART4" or "UART5" 31 | 32 | .. function:: cleanup() 33 | 34 | Cleans up the UART. 35 | 36 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # 3 | # Adafruit-BBIO documentation build configuration file, created by 4 | # sphinx-quickstart on Fri Dec 1 12:56:03 2017. 5 | # 6 | # This file is execfile()d with the current directory set to its 7 | # containing dir. 8 | # 9 | # Note that not all possible configuration values are present in this 10 | # autogenerated file. 11 | # 12 | # All configuration values have a default; values that are commented out 13 | # serve to show the default. 14 | 15 | # If extensions (or modules to document with autodoc) are in another directory, 16 | # add these directories to sys.path here. If the directory is relative to the 17 | # documentation root, use os.path.abspath to make it absolute, like shown here. 18 | # 19 | import os 20 | import sys 21 | sys.path.insert(0, os.path.abspath('../')) 22 | 23 | 24 | # -- General configuration ------------------------------------------------ 25 | 26 | # If your documentation needs a minimal Sphinx version, state it here. 27 | # 28 | # needs_sphinx = '1.0' 29 | 30 | # Add any Sphinx extension module names here, as strings. They can be 31 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 32 | # ones. 33 | extensions = ['sphinx.ext.autodoc', 'sphinx.ext.napoleon'] 34 | 35 | # Add any paths that contain templates here, relative to this directory. 36 | templates_path = ['_templates'] 37 | 38 | # The suffix(es) of source filenames. 39 | # You can specify multiple suffix as a list of string: 40 | # 41 | # source_suffix = ['.rst', '.md'] 42 | source_suffix = '.rst' 43 | 44 | # The master toctree document. 45 | master_doc = 'index' 46 | 47 | # General information about the project. 48 | project = u'Adafruit-BBIO' 49 | copyright = u'2017, Adafruit Industries and contributors' 50 | author = u'Justin Cooper and contributors' 51 | 52 | # The version info for the project you're documenting, acts as replacement for 53 | # |version| and |release|, also used in various other places throughout the 54 | # built documents. 55 | # 56 | # The short X.Y version. 57 | version = u'1.0' 58 | # The full version, including alpha/beta/rc tags. 59 | release = u'' 60 | 61 | # The language for content autogenerated by Sphinx. Refer to documentation 62 | # for a list of supported languages. 63 | # 64 | # This is also used if you do content translation via gettext catalogs. 65 | # Usually you set "language" from the command line for these cases. 66 | language = None 67 | 68 | # List of patterns, relative to source directory, that match files and 69 | # directories to ignore when looking for source files. 70 | # This patterns also effect to html_static_path and html_extra_path 71 | exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] 72 | 73 | # The name of the Pygments (syntax highlighting) style to use. 74 | pygments_style = 'sphinx' 75 | 76 | # If true, `todo` and `todoList` produce output, else they produce nothing. 77 | todo_include_todos = False 78 | 79 | 80 | # -- Options for HTML output ---------------------------------------------- 81 | 82 | # The theme to use for HTML and HTML Help pages. See the documentation for 83 | # a list of builtin themes. 84 | # 85 | # html_theme = 'alabaster' 86 | 87 | # Theme options are theme-specific and customize the look and feel of a theme 88 | # further. For a list of options available for each theme, see the 89 | # documentation. 90 | # 91 | # html_theme_options = {} 92 | 93 | # Add any paths that contain custom static files (such as style sheets) here, 94 | # relative to this directory. They are copied after the builtin static files, 95 | # so a file named "default.css" will overwrite the builtin "default.css". 96 | html_static_path = ['_static'] 97 | 98 | # Custom sidebar templates, must be a dictionary that maps document names 99 | # to template names. 100 | # 101 | # This is required for the alabaster theme 102 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars 103 | 104 | # Use the readthedocs theme if the documentation is being built there, or 105 | # use a Sphinx theme if the documentation is being built locally 106 | on_rtd = os.environ.get('READTHEDOCS') == 'True' 107 | if on_rtd: 108 | html_theme = 'default' 109 | html_theme_options = { 110 | 'collapse_navigation': False, 111 | } 112 | else: 113 | html_theme = 'alabaster' 114 | html_sidebars = { 115 | '**': [ 116 | 'searchbox.html', 117 | 'localtoc.html' 118 | ] 119 | } 120 | # If you want to use the same theme as readthedocs, uncomment the lines 121 | # below and install the readthedocs theme (pip install sphinx_rtd_theme) 122 | # before doing a new build: 123 | #html_theme = 'sphinx_rtd_theme' 124 | #html_theme_options = { 125 | # 'collapse_navigation': False, 126 | #} 127 | 128 | # Do not show the "View source" link that shows the .rst files 129 | html_copy_source = False 130 | html_show_sourcelink = False 131 | 132 | # -- Options for HTMLHelp output ------------------------------------------ 133 | 134 | # Output file base name for HTML help builder. 135 | htmlhelp_basename = 'Adafruit-BBIOdoc' 136 | 137 | 138 | # -- Options for LaTeX output --------------------------------------------- 139 | 140 | latex_elements = { 141 | # The paper size ('letterpaper' or 'a4paper'). 142 | # 143 | # 'papersize': 'letterpaper', 144 | 145 | # The font size ('10pt', '11pt' or '12pt'). 146 | # 147 | # 'pointsize': '10pt', 148 | 149 | # Additional stuff for the LaTeX preamble. 150 | # 151 | # 'preamble': '', 152 | 153 | # Latex figure (float) alignment 154 | # 155 | # 'figure_align': 'htbp', 156 | } 157 | 158 | # Grouping the document tree into LaTeX files. List of tuples 159 | # (source start file, target name, title, 160 | # author, documentclass [howto, manual, or own class]). 161 | latex_documents = [ 162 | (master_doc, 'Adafruit-BBIO.tex', u'Adafruit-BBIO Documentation', 163 | u'Justin Cooper', 'manual'), 164 | ] 165 | 166 | 167 | # -- Options for manual page output --------------------------------------- 168 | 169 | # One entry per manual page. List of tuples 170 | # (source start file, name, description, authors, manual section). 171 | man_pages = [ 172 | (master_doc, 'adafruit-bbio', u'Adafruit-BBIO Documentation', 173 | [author], 1) 174 | ] 175 | 176 | 177 | # -- Options for Texinfo output ------------------------------------------- 178 | 179 | # Grouping the document tree into Texinfo files. List of tuples 180 | # (source start file, target name, title, author, 181 | # dir menu entry, description, category) 182 | texinfo_documents = [ 183 | (master_doc, 'Adafruit-BBIO', u'Adafruit-BBIO Documentation', 184 | author, 'Adafruit-BBIO', 'One line description of project.', 185 | 'Miscellaneous'), 186 | ] 187 | 188 | autodoc_member_order = 'groupwise' 189 | #autoclass_content = 'both' 190 | 191 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. Adafruit-BBIO documentation master file, created by 2 | sphinx-quickstart on Fri Dec 1 12:56:03 2017. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | Adafruit Beaglebone IO Python API 7 | ================================= 8 | 9 | The Adafruit Beaglebone IO API enables access to the Beaglebone's GPIO, PWM, 10 | ADC, UART, SPI and eQEP hardware modules from Python programs. 11 | 12 | .. toctree:: 13 | :maxdepth: 4 14 | :caption: Contents 15 | 16 | ADC 17 | Encoder 18 | GPIO 19 | PWM 20 | SPI 21 | UART 22 | 23 | Indices and tables 24 | ================== 25 | 26 | * :ref:`genindex` 27 | * :ref:`modindex` 28 | 29 | 30 | -------------------------------------------------------------------------------- /fix_py_compile.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | # Some Angstrom images are missing the py_compile module; get it if not 3 | # present: 4 | # Fix credit:https://github.com/alexanderhiam/PyBBIO/blob/master/setup.py 5 | import random, os 6 | python_lib_path = random.__file__.split('random')[0] 7 | if not os.path.exists(python_lib_path + 'py_compile.py'): 8 | print "py_compile module missing; installing to %spy_compile.py" %\ 9 | python_lib_path 10 | import urllib2 11 | url = "http://hg.python.org/cpython/raw-file/4ebe1ede981e/Lib/py_compile.py" 12 | py_compile = urllib2.urlopen(url) 13 | with open(python_lib_path+'py_compile.py', 'w') as f: 14 | f.write(py_compile.read()) 15 | print "testing py_compile..." 16 | try: 17 | import py_compile 18 | print "py_compile installed successfully" 19 | except Exception, e: 20 | print "*py_compile install failed, could not import" 21 | print "*Exception raised:" 22 | raise e 23 | -------------------------------------------------------------------------------- /install_all_python_versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # useful for testing changes against all versions of python 3 | make clean 4 | echo "Install Python 2" 5 | python2 ./setup.py install 6 | echo "Install Python 3" 7 | python3 ./setup.py install 8 | -------------------------------------------------------------------------------- /m4/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/adafruit-beaglebone-io-python/cf306ed7f9f24111d0949dd60ac232e81241bffe/m4/.gitkeep -------------------------------------------------------------------------------- /m4/gtest.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([CHECK_GTEST], 2 | [ 3 | AC_MSG_CHECKING([for google test]) 4 | 5 | AC_LANG_PUSH([C++]) 6 | AC_CHECK_HEADER([gtest/gtest.h],[gtest_found=yes]) 7 | AC_LANG_POP 8 | 9 | #if test "x$gtest_found" = "xyes"; then 10 | # GTEST_CPPFLAGS= 11 | # AC_SUBST(GTEST_CPPFLAGS) 12 | #fi 13 | 14 | AC_SUBST(HAVE_GTEST) 15 | AM_CONDITIONAL([HAVE_GTEST], [test "x$gtest_found" = "xyes"]) 16 | ]) 17 | -------------------------------------------------------------------------------- /m4/kernel-release.m4: -------------------------------------------------------------------------------- 1 | AC_DEFUN([CHECK_KERNEL_RELEASE], 2 | [ 3 | AC_MSG_CHECKING([if kernel release >= 4.1]) 4 | 5 | kernel_ge_41=$(python -c 'import platform; print("yes" if platform.release() >= "4.1.0" else "no")') 6 | 7 | if test "x$kernel_ge_41" = "xyes"; then 8 | CPPFLAGS="$CPPFLAGS -DBBBVERSION41" 9 | AC_SUBST(CPPFLAGS) 10 | AC_MSG_RESULT(yes) 11 | else 12 | AC_MSG_RESULT(no) 13 | fi 14 | ]) 15 | -------------------------------------------------------------------------------- /overlays/ADAFRUIT-SPI0-00A0.dts: -------------------------------------------------------------------------------- 1 | /dts-v1/; 2 | /plugin/; 3 | 4 | / { 5 | compatible = "ti,beaglebone", "ti,beaglebone-black"; 6 | 7 | /* identification */ 8 | part-number = "ADAFRUIT-SPI0"; 9 | 10 | /* version */ 11 | version = "00A0"; 12 | 13 | exclusive-use = 14 | /* the pin header uses */ 15 | "P9.17", 16 | "P9.18", 17 | "P9.21", 18 | "P9.22", 19 | "spi0"; 20 | 21 | fragment@0 { 22 | target = <&am33xx_pinmux>; 23 | __overlay__ { 24 | spi0_pins_s0: spi0_pins_s0 { 25 | pinctrl-single,pins = < 26 | 0x150 0x30 /* spi0_sclk, INPUT_PULLUP | MODE0 */ 27 | 0x154 0x30 /* spi0_d0, INPUT_PULLUP | MODE0 */ 28 | 0x158 0x10 /* spi0_d1, OUTPUT_PULLUP | MODE0 */ 29 | 0x15c 0x10 /* spi0_cs0, OUTPUT_PULLUP | MODE0 */ 30 | >; 31 | }; 32 | }; 33 | }; 34 | 35 | fragment@1 { 36 | target = <&spi0>; 37 | __overlay__ { 38 | #address-cells = <1>; 39 | #size-cells = <0>; 40 | 41 | status = "okay"; 42 | pinctrl-names = "default"; 43 | pinctrl-0 = <&spi0_pins_s0>; 44 | 45 | spidev@0 { 46 | spi-max-frequency = <24000000>; 47 | reg = <0>; 48 | compatible = "spidev"; 49 | }; 50 | spidev@1 { 51 | spi-max-frequency = <24000000>; 52 | reg = <1>; 53 | compatible = "spidev"; 54 | }; 55 | }; 56 | }; 57 | }; 58 | -------------------------------------------------------------------------------- /overlays/ADAFRUIT-SPI1-00A0.dts: -------------------------------------------------------------------------------- 1 | /* DTS File modified from http://hipstercircuits.com/enable-spi-with-device-tree-on-beaglebone-black-copy-paste/ */ 2 | /dts-v1/; 3 | /plugin/; 4 | 5 | / { 6 | compatible = "ti,beaglebone", "ti,beaglebone-black"; 7 | 8 | /* identification */ 9 | part-number = "ADAFRUIT-SPI1"; 10 | 11 | /* version */ 12 | version = "00A0"; 13 | 14 | /* state the resources this cape uses */ 15 | exclusive-use = 16 | /* the pin header uses */ 17 | "P9.31", 18 | "P9.29", 19 | "P9.30", 20 | "P9.28", 21 | "spi1"; 22 | 23 | fragment@0 { 24 | target = <&am33xx_pinmux>; 25 | __overlay__ { 26 | pinctrl_spi1: pinctrl_spi1_pins { 27 | pinctrl-single,pins = < 28 | 0x190 0x33 /* P9_31 = mcasp0_aclkx.spi1_sclk , INPUT_PULLUP | MODE3 */ 29 | 0x194 0x33 /* P9_29 = mcasp0_fsx.spi1_d0 , INPUT_PULLUP | MODE3 */ 30 | 0x198 0x13 /* P9_30 = mcasp0_axr0.spi1_d1 , OUTPUT_PULLUP | MODE3 */ 31 | 0x19c 0x13 /* P9_28 = mcasp0_ahclkr.spi1_cs0 , OUTPUT_PULLUP | MODE3 */ 32 | >; 33 | }; 34 | }; 35 | }; 36 | 37 | fragment@1 { 38 | target = <&spi1>; 39 | __overlay__ { 40 | #address-cells = <1>; 41 | #size-cells = <0>; 42 | status = "okay"; 43 | pinctrl-names = "default"; 44 | pinctrl-0 = <&pinctrl_spi1>; 45 | 46 | spidev@0{ 47 | compatible = "spidev"; 48 | reg = <0>; 49 | spi-max-frequency = <24000000>; 50 | }; 51 | spidev@1{ 52 | compatible = "spidev"; 53 | reg = <1>; 54 | spi-max-frequency = <24000000>; 55 | }; 56 | }; 57 | }; 58 | }; 59 | -------------------------------------------------------------------------------- /overlays/ADAFRUIT-UART1-00A0.dts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 CircuitCo 3 | * 4 | * Virtual cape for UART1 on connector pins P9.24 P9.26 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation. 9 | */ 10 | /dts-v1/; 11 | /plugin/; 12 | 13 | / { 14 | compatible = "ti,beaglebone", "ti,beaglebone-black"; 15 | 16 | /* identification */ 17 | part-number = "ADAFRUIT-UART1"; 18 | version = "00A0"; 19 | 20 | /* state the resources this cape uses */ 21 | exclusive-use = 22 | /* the pin header uses */ 23 | "P9.24", /* uart1_txd */ 24 | "P9.26", /* uart1_rxd */ 25 | /* the hardware ip uses */ 26 | "uart1"; 27 | 28 | fragment@0 { 29 | target = <&am33xx_pinmux>; 30 | __overlay__ { 31 | bb_uart1_pins: pinmux_bb_uart1_pins { 32 | pinctrl-single,pins = < 33 | 0x184 0x20 /* P9.24 uart1_txd.uart1_txd OUTPUT */ 34 | 0x180 0x20 /* P9.26 uart1_rxd.uart1_rxd INPUT */ 35 | >; 36 | }; 37 | }; 38 | }; 39 | 40 | fragment@1 { 41 | target = <&uart2>; /* really uart1 */ 42 | __overlay__ { 43 | status = "okay"; 44 | pinctrl-names = "default"; 45 | pinctrl-0 = <&bb_uart1_pins>; 46 | }; 47 | }; 48 | }; 49 | -------------------------------------------------------------------------------- /overlays/ADAFRUIT-UART2-00A0.dts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 CircuitCo 3 | * 4 | * Virtual cape for UART2 on connector pins P9.21 P9.22 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation. 9 | */ 10 | /dts-v1/; 11 | /plugin/; 12 | 13 | / { 14 | compatible = "ti,beaglebone", "ti,beaglebone-black"; 15 | 16 | /* identification */ 17 | part-number = "ADAFRUIT-UART2"; 18 | version = "00A0"; 19 | 20 | /* state the resources this cape uses */ 21 | exclusive-use = 22 | /* the pin header uses */ 23 | "P9.21", /* uart2_txd */ 24 | "P9.22", /* uart2_rxd */ 25 | /* the hardware ip uses */ 26 | "uart2"; 27 | 28 | fragment@0 { 29 | target = <&am33xx_pinmux>; 30 | __overlay__ { 31 | bb_uart2_pins: pinmux_bb_uart2_pins { 32 | pinctrl-single,pins = < 33 | 0x150 0x21 /* spi0_sclk.uart2_rxd | MODE1 */ 34 | 0x154 0x01 /* spi0_d0.uart2_txd | MODE1 */ 35 | >; 36 | }; 37 | }; 38 | }; 39 | 40 | fragment@1 { 41 | target = <&uart3>; /* really uart2 */ 42 | __overlay__ { 43 | status = "okay"; 44 | pinctrl-names = "default"; 45 | pinctrl-0 = <&bb_uart2_pins>; 46 | }; 47 | }; 48 | }; 49 | -------------------------------------------------------------------------------- /overlays/ADAFRUIT-UART4-00A0.dts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 CircuitCo 3 | * 4 | * Virtual cape for UART4 on connector pins P9.13 P9.11 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation. 9 | */ 10 | /dts-v1/; 11 | /plugin/; 12 | 13 | / { 14 | compatible = "ti,beaglebone", "ti,beaglebone-black"; 15 | 16 | /* identification */ 17 | part-number = "ADAFRUIT-UART4"; 18 | version = "00A0"; 19 | 20 | /* state the resources this cape uses */ 21 | exclusive-use = 22 | /* the pin header uses */ 23 | "P9.13", /* uart4_txd */ 24 | "P9.11", /* uart4_rxd */ 25 | /* the hardware ip uses */ 26 | "uart4"; 27 | 28 | fragment@0 { 29 | target = <&am33xx_pinmux>; 30 | __overlay__ { 31 | bb_uart4_pins: pinmux_bb_uart4_pins { 32 | pinctrl-single,pins = < 33 | 0x070 0x26 /* gpmc_wait0.uart4_rxd | MODE6 */ 34 | 0x074 0x06 /* gpmc_wpn.uart4_txd | MODE6 */ 35 | >; 36 | }; 37 | }; 38 | }; 39 | 40 | fragment@1 { 41 | target = <&uart5>; /* really uart4 */ 42 | __overlay__ { 43 | status = "okay"; 44 | pinctrl-names = "default"; 45 | pinctrl-0 = <&bb_uart4_pins>; 46 | }; 47 | }; 48 | }; 49 | -------------------------------------------------------------------------------- /overlays/ADAFRUIT-UART5-00A0.dts: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013 CircuitCo 3 | * 4 | * Virtual cape for UART5 on connector pins P9.37 P8.38 5 | * 6 | * This program is free software; you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License version 2 as 8 | * published by the Free Software Foundation. 9 | */ 10 | /dts-v1/; 11 | /plugin/; 12 | 13 | / { 14 | compatible = "ti,beaglebone", "ti,beaglebone-black"; 15 | 16 | /* identification */ 17 | part-number = "ADAFRUIT-UART5"; 18 | version = "00A0"; 19 | 20 | /* state the resources this cape uses */ 21 | exclusive-use = 22 | /* the pin header uses */ 23 | "P8.37", /* uart5_txd */ 24 | "P8.38", /* uart5_rxd */ 25 | /* the hardware ip uses */ 26 | "uart5"; 27 | 28 | fragment@0 { 29 | target = <&am33xx_pinmux>; 30 | __overlay__ { 31 | bb_uart5_pins: pinmux_bb_uart5_pins { 32 | pinctrl-single,pins = < 33 | /* the uart pins */ 34 | 0x0C4 0x24 /* lcd_data9.uart5_rxd | MODE4 */ 35 | 0x0C0 0x04 /* lcd_data8.uart5_txd | MODE4 */ 36 | >; 37 | }; 38 | }; 39 | }; 40 | 41 | fragment@1 { 42 | target = <&uart6>; /* really uart5 */ 43 | __overlay__ { 44 | status = "okay"; 45 | pinctrl-names = "default"; 46 | pinctrl-0 = <&bb_uart5_pins>; 47 | }; 48 | }; 49 | }; 50 | -------------------------------------------------------------------------------- /overlays/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adafruit/adafruit-beaglebone-io-python/cf306ed7f9f24111d0949dd60ac232e81241bffe/overlays/__init__.py -------------------------------------------------------------------------------- /overlays/builder.py: -------------------------------------------------------------------------------- 1 | from subprocess import call 2 | import os 3 | import shutil 4 | import glob 5 | 6 | def compile(): 7 | #SPI Overlays 8 | call(["dtc", "-Wno-unit_address_vs_reg", "-O", "dtb", "-o", "overlays/ADAFRUIT-SPI0-00A0.dtbo", "-b", "o", "-@", "overlays/ADAFRUIT-SPI0-00A0.dts"]) 9 | call(["dtc", "-Wno-unit_address_vs_reg", "-O", "dtb", "-o", "overlays/ADAFRUIT-SPI1-00A0.dtbo", "-b", "o", "-@", "overlays/ADAFRUIT-SPI1-00A0.dts"]) 10 | #UART Overlayss 11 | call(["dtc", "-Wno-unit_address_vs_reg", "-O", "dtb", "-o", "overlays/ADAFRUIT-UART1-00A0.dtbo", "-b", "o", "-@", "overlays/ADAFRUIT-UART1-00A0.dts"]) 12 | call(["dtc", "-Wno-unit_address_vs_reg", "-O", "dtb", "-o", "overlays/ADAFRUIT-UART2-00A0.dtbo", "-b", "o", "-@", "overlays/ADAFRUIT-UART2-00A0.dts"]) 13 | call(["dtc", "-Wno-unit_address_vs_reg", "-O", "dtb", "-o", "overlays/ADAFRUIT-UART4-00A0.dtbo", "-b", "o", "-@", "overlays/ADAFRUIT-UART4-00A0.dts"]) 14 | call(["dtc", "-Wno-unit_address_vs_reg", "-O", "dtb", "-o", "overlays/ADAFRUIT-UART5-00A0.dtbo", "-b", "o", "-@", "overlays/ADAFRUIT-UART5-00A0.dts"]) 15 | def copy(): 16 | for fl in glob.glob("/lib/firmware/ADAFRUIT-SPI*-00A0.dtbo"): 17 | os.remove(fl) 18 | for fl in glob.glob("/lib/firmware/ADAFRUIT-UART*-00A0.dtbo"): 19 | os.remove(fl) 20 | #SPI Overlays 21 | shutil.move("overlays/ADAFRUIT-SPI0-00A0.dtbo", "/lib/firmware/ADAFRUIT-SPI0-00A0.dtbo") 22 | shutil.move("overlays/ADAFRUIT-SPI1-00A0.dtbo", "/lib/firmware/ADAFRUIT-SPI1-00A0.dtbo") 23 | #UART Overlays 24 | shutil.move("overlays/ADAFRUIT-UART1-00A0.dtbo", "/lib/firmware/ADAFRUIT-UART1-00A0.dtbo") 25 | shutil.move("overlays/ADAFRUIT-UART2-00A0.dtbo", "/lib/firmware/ADAFRUIT-UART2-00A0.dtbo") 26 | shutil.move("overlays/ADAFRUIT-UART4-00A0.dtbo", "/lib/firmware/ADAFRUIT-UART4-00A0.dtbo") 27 | shutil.move("overlays/ADAFRUIT-UART5-00A0.dtbo", "/lib/firmware/ADAFRUIT-UART5-00A0.dtbo") 28 | -------------------------------------------------------------------------------- /pytest_all_versions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # useful for testing changes against all versions of python 3 | 4 | cd test 5 | echo "Testing Python 2" 6 | python2 -mpytest 7 | echo "Testing Python 3" 8 | python3 -mpytest 9 | cd .. 10 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | try: 2 | from overlays import builder 3 | builder.compile() 4 | builder.copy() 5 | except: 6 | pass 7 | 8 | import distribute_setup 9 | import io 10 | import sys 11 | import platform 12 | distribute_setup.use_setuptools() 13 | from setuptools import setup, Extension, find_packages 14 | 15 | open_as_utf8 = lambda x: io.open(x, encoding='utf-8') 16 | 17 | kernel = platform.release() 18 | 19 | if kernel >= '4.1.0': 20 | kernel41 = [('BBBVERSION41', None)] 21 | else: 22 | kernel41 = None 23 | 24 | CFLAGS = ['-Wall'] 25 | 26 | classifiers = ['Development Status :: 3 - Alpha', 27 | 'Operating System :: POSIX :: Linux', 28 | 'License :: OSI Approved :: MIT License', 29 | 'Intended Audience :: Developers', 30 | 'Programming Language :: Python :: 2.7', 31 | 'Programming Language :: Python :: 3', 32 | 'Topic :: Software Development', 33 | 'Topic :: Home Automation', 34 | 'Topic :: System :: Hardware'] 35 | 36 | extension_args = { 37 | 'include_dirs': ['source/include/'], 38 | 'extra_compile_args': CFLAGS, 39 | 'define_macros': kernel41 40 | } 41 | 42 | setup(name = 'Adafruit_BBIO', 43 | version = '1.2.0', 44 | author = 'Justin Cooper', 45 | author_email = 'justin@adafruit.com', 46 | description = 'A module to control BeagleBone IO channels', 47 | long_description = open_as_utf8('README.md').read() + open_as_utf8('CHANGELOG.md').read(), 48 | long_description_content_type = 'text/markdown', 49 | license = 'MIT', 50 | keywords = 'Adafruit BeagleBone IO GPIO PWM ADC', 51 | url = 'https://github.com/adafruit/adafruit-beaglebone-io-python/', 52 | classifiers = classifiers, 53 | packages = find_packages(), 54 | py_modules = ['Adafruit_I2C'], 55 | ext_modules = [Extension('Adafruit_BBIO.GPIO', ['source/py_gpio.c', 'source/event_gpio.c', 'source/c_pinmux.c', 'source/constants.c', 'source/common.c'], **extension_args), 56 | Extension('Adafruit_BBIO.PWM', ['source/py_pwm.c', 'source/c_pwm.c', 'source/c_pinmux.c', 'source/constants.c', 'source/common.c'], **extension_args), 57 | Extension('Adafruit_BBIO.ADC', ['source/py_adc.c', 'source/c_adc.c', 'source/constants.c', 'source/common.c'], **extension_args), 58 | Extension('Adafruit_BBIO.SPI', ['source/spimodule.c', 'source/c_pinmux.c', 'source/constants.c', 'source/common.c'], **extension_args), 59 | Extension('Adafruit_BBIO.UART', ['source/py_uart.c', 'source/c_pinmux.c', 'source/c_uart.c', 'source/constants.c', 'source/common.c'], **extension_args)] ) 60 | 61 | -------------------------------------------------------------------------------- /source/Makefile.am: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Copyright (c) 2017 Adafruit 3 | # Copyright (c) 2017 Nikolay Semenov 4 | ################################################################################ 5 | 6 | ################################################################################ 7 | # Global flags 8 | ################################################################################ 9 | AM_CPPFLAGS = 10 | 11 | AM_CPPFLAGS += \ 12 | -DNDEBUG \ 13 | -g -O2 \ 14 | -fstack-protector-strong \ 15 | -fPIC 16 | 17 | AM_CPPFLAGS += \ 18 | -Wall \ 19 | -Wextra \ 20 | -Werror 21 | 22 | AM_CPPFLAGS += \ 23 | -DNO_PYTHON 24 | 25 | AM_CPPFLAGS += \ 26 | -I$(srcdir)/include/ 27 | 28 | AM_CXXFLAGS = \ 29 | -std=c++11 30 | 31 | ################################################################################ 32 | # AdafruitBBIO library 33 | ################################################################################ 34 | # libadafruit-bbio1 - c++11 ABI 35 | # libadafruit-bbio0 - c++98 ABI 36 | lib_LTLIBRARIES = \ 37 | libadafruit-bbio1.la \ 38 | libadafruit-bbio0.la 39 | 40 | adafruitdir = $(includedir)/adafruit 41 | adafruit_HEADERS = \ 42 | include/adafruit/bbio.h 43 | 44 | adafruit_bbiodir = $(adafruitdir)/bbio 45 | adafruit_bbio_HEADERS = \ 46 | include/adafruit/bbio/error.h \ 47 | include/adafruit/bbio/gpio.h \ 48 | include/adafruit/bbio/pwm.h 49 | 50 | LIBSOURCES = \ 51 | c_adc.c \ 52 | c_pinmux.c \ 53 | c_pwm.c \ 54 | c_uart.c \ 55 | common.c \ 56 | event_gpio.c \ 57 | library/bbio.cpp \ 58 | library/gpio.cpp \ 59 | library/pwm.cpp 60 | 61 | libadafruit_bbio1_la_SOURCES = $(LIBSOURCES) 62 | libadafruit_bbio0_la_SOURCES = $(LIBSOURCES) 63 | 64 | libadafruit_bbio1_la_CXXFLAGS = $(AM_CXXFLAGS) -D_GLIBCXX_USE_CXX11_ABI=1 65 | libadafruit_bbio0_la_CXXFLAGS = $(AM_CXXFLAGS) -D_GLIBCXX_USE_CXX11_ABI=0 66 | 67 | libadafruit_bbio1_la_LDFLAGS = $(AM_LDFLAGS) -shared 68 | libadafruit_bbio0_la_LDFLAGS = $(AM_LDFLAGS) -shared 69 | 70 | ################################################################################ 71 | # Examples 72 | ################################################################################ 73 | noinst_PROGRAMS = examples/cpp/pwm 74 | 75 | examples_cpp_pwm_SOURCES = examples/cpp/pwm.cpp 76 | examples_cpp_pwm_LDADD = libadafruit-bbio1.la 77 | examples_cpp_pwm_LDFLAGS = $(AM_LDFLAGS) -lpthread -static 78 | 79 | noinst_PROGRAMS += examples/cpp/gpio 80 | 81 | examples_cpp_gpio_SOURCES = examples/cpp/gpio.cpp 82 | examples_cpp_gpio_LDADD = libadafruit-bbio1.la 83 | examples_cpp_gpio_LDFLAGS = $(AM_LDFLAGS) -lpthread -static 84 | 85 | ################################################################################ 86 | # Tests 87 | ################################################################################ 88 | check_PROGRAMS = 89 | TESTS = $(check_PROGRAMS) 90 | 91 | check_PROGRAMS += test/cpp/abi-old 92 | 93 | test_cpp_abi_old_SOURCES = test/cpp/abi.cpp 94 | test_cpp_abi_old_CXXFLAGS = $(AM_CXXFLAGS) -pthread -D_GLIBCXX_USE_CXX11_ABI=0 95 | test_cpp_abi_old_LDADD = libadafruit-bbio0.la 96 | test_cpp_abi_old_LDFLAGS = $(AM_LDFLAGS) -lpthread -static 97 | 98 | check_PROGRAMS += test/cpp/abi-new 99 | 100 | test_cpp_abi_new_SOURCES = test/cpp/abi.cpp 101 | test_cpp_abi_new_CXXFLAGS = $(AM_CXXFLAGS) -pthread -D_GLIBCXX_USE_CXX11_ABI=1 102 | test_cpp_abi_new_LDADD = libadafruit-bbio1.la 103 | test_cpp_abi_new_LDFLAGS = $(AM_LDFLAGS) -lpthread -static 104 | 105 | if HAVE_GTEST 106 | 107 | check_PROGRAMS += test/cpp/unittest 108 | 109 | gtest/src/gtest-all.cc: /usr/src/gtest/src 110 | mkdir -p gtest && cp -Rvf $< gtest 111 | 112 | gtest/src/gtest_main.cc: gtest/src/gtest-all.cc 113 | 114 | BUILT_SOURCES = \ 115 | gtest/src/gtest-all.cc \ 116 | gtest/src/gtest_main.cc 117 | 118 | test_cpp_unittest_SOURCES = \ 119 | test/cpp/pwm.cpp \ 120 | gtest/src/gtest-all.cc \ 121 | gtest/src/gtest_main.cc 122 | 123 | test_cpp_unittest_CPPFLAGS = $(AM_CPPFLAGS) $(GTEST_CPPFLAGS) -isystem gtest 124 | test_cpp_unittest_CXXFLAGS = $(AM_CXXFLAGS) -pthread -D_GLIBCXX_USE_CXX11_ABI=1 125 | test_cpp_unittest_LDADD = libadafruit-bbio1.la 126 | test_cpp_unittest_LDFLAGS = $(AM_LDFLAGS) -lpthread -static 127 | 128 | endif # HAVE_GTEST 129 | -------------------------------------------------------------------------------- /source/c_adc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | Author: Justin Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "c_adc.h" 31 | #include "common.h" 32 | 33 | #ifdef BBBVERSION41 34 | char adc_prefix_dir[49]; 35 | #else 36 | char adc_prefix_dir[40]; 37 | #endif 38 | 39 | int adc_initialized = 0; 40 | 41 | BBIO_err initialize_adc(void) 42 | { 43 | #ifdef BBBVERSION41 44 | char test_path[149]; 45 | #else 46 | char test_path[140]; 47 | #endif 48 | FILE *fh; 49 | BBIO_err err; 50 | 51 | if (adc_initialized) { 52 | return BBIO_OK; 53 | } 54 | 55 | #ifdef BBBVERSION41 56 | err = load_device_tree("BB-ADC"); 57 | if (err == BBIO_OK) { 58 | strncat(adc_prefix_dir, "/sys/bus/iio/devices/iio:device0/in_voltage", sizeof(adc_prefix_dir)); 59 | snprintf(test_path, sizeof(test_path), "%s%d_raw", adc_prefix_dir, 1); 60 | sleep(1); 61 | fh = fopen(test_path, "r"); 62 | 63 | if (!fh) { 64 | return BBIO_SYSFS; 65 | } 66 | fclose(fh); 67 | 68 | adc_initialized = 1; 69 | return BBIO_OK; 70 | } 71 | #else 72 | err = load_device_tree("cape-bone-iio"); 73 | if (err == BBIO_OK) { 74 | build_path("/sys/devices", "ocp.", ocp_dir, sizeof(ocp_dir)); 75 | build_path(ocp_dir, "helper.", adc_prefix_dir, sizeof(adc_prefix_dir)); 76 | strncat(adc_prefix_dir, "/AIN", sizeof(adc_prefix_dir)); 77 | snprintf(test_path, sizeof(test_path), "%s%d", adc_prefix_dir, 0); 78 | fh = fopen(test_path, "r"); 79 | 80 | if (!fh) { 81 | return BBIO_SYSFS; 82 | } 83 | fclose(fh); 84 | 85 | adc_initialized = 1; 86 | return BBIO_OK; 87 | } 88 | #endif 89 | 90 | return BBIO_GEN; 91 | } 92 | 93 | BBIO_err read_value(unsigned int ain, float *value) 94 | { 95 | FILE * fh; 96 | #ifdef BBBVERSION41 97 | char ain_path[149]; 98 | snprintf(ain_path, sizeof(ain_path), "%s%d_raw", adc_prefix_dir, ain); 99 | #else 100 | char ain_path[140]; 101 | snprintf(ain_path, sizeof(ain_path), "%s%d", adc_prefix_dir, ain); 102 | #endif 103 | 104 | int err, try_count=0; 105 | int read_successful; 106 | 107 | read_successful = 0; 108 | 109 | // Workaround to AIN bug where reading from more than one AIN would cause access failures 110 | while (!read_successful && try_count < 3) 111 | { 112 | fh = fopen(ain_path, "r"); 113 | 114 | // Likely a bad path to the ocp device driver 115 | if (!fh) { 116 | return BBIO_SYSFS; 117 | } 118 | 119 | fseek(fh, 0, SEEK_SET); 120 | err = fscanf(fh, "%f", value); 121 | 122 | if (err != EOF) read_successful = 1; 123 | fclose(fh); 124 | 125 | try_count++; 126 | } 127 | 128 | if (read_successful) return BBIO_OK; 129 | 130 | // Fall through and fail 131 | return BBIO_GEN; 132 | } 133 | 134 | BBIO_err adc_setup(void) 135 | { 136 | return initialize_adc(); 137 | } 138 | 139 | BBIO_err adc_cleanup(void) 140 | { 141 | #ifdef BBBVERSION41 142 | return unload_device_tree("BB-ADC"); 143 | #else 144 | return unload_device_tree("cape-bone-iio"); 145 | #endif 146 | } 147 | -------------------------------------------------------------------------------- /source/c_adc.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | Author: Justin Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #ifndef BBIO_C_ADC_H 25 | #define BBIO_C_ADC_H 26 | #include "common.h" 27 | 28 | extern int adc_initialized; 29 | 30 | BBIO_err adc_setup(void); 31 | BBIO_err read_value(unsigned int ain, float *value); 32 | BBIO_err adc_cleanup(void); 33 | #endif 34 | -------------------------------------------------------------------------------- /source/c_pinmux.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "c_pinmux.h" 6 | #include "common.h" 7 | 8 | 9 | BBIO_err set_pin_mode(const char *key, const char *mode) 10 | { 11 | // char ocp_dir[] defined in common.h 12 | char path[100]; // "/sys/devices/platform/ocp/ocp:P#_##_pinmux/state" 13 | char pinmux_dir[20]; // "ocp:P#_##_pinmux" 14 | char pin[6]; //"P#_##" 15 | FILE *f = NULL; 16 | 17 | // pin mode can not be set for the built-in USRn LEDs 18 | if (strncmp(key, "USR", 3) == 0) { 19 | return BBIO_OK; 20 | } 21 | 22 | if (strlen(key) == 4) // Key P#_# format, must inject '0' to be P#_0# 23 | snprintf(pin, sizeof(pin), "%.3s0%c", key,key[3]); 24 | else //copy string 25 | snprintf(pin, sizeof(pin), "%s", key); 26 | 27 | #ifndef BBBVERSION41 28 | BBIO_err err; 29 | err = build_path("/sys/devices/platform", "ocp", ocp_dir, sizeof(ocp_dir)); 30 | if (err != BBIO_OK) { 31 | return err; 32 | } 33 | #else 34 | strncpy(ocp_dir, "/sys/devices/platform/ocp", sizeof(ocp_dir)); 35 | #endif 36 | 37 | snprintf(pinmux_dir, sizeof(pinmux_dir), "ocp:%s_pinmux", pin); 38 | snprintf(path, sizeof(path), "%s/%s/state", ocp_dir, pinmux_dir); 39 | 40 | /* beaglebone blue has complete dtb file and does not need overlays */ 41 | if(beaglebone_blue()) { 42 | fprintf(stderr, "DEBUG: Adafruit_BBIO: set_pin_mode() :: Pinmux file: %s, mode: %s", path, mode); 43 | fprintf(stderr, "DEBUG: Adafruit_BBIO: set_pin_mode(): beaglebone_blue() is TRUE; return BBIO_OK\n"); 44 | return BBIO_OK; 45 | } 46 | 47 | 48 | f = fopen(path, "w"); 49 | if (NULL == f) { 50 | return BBIO_ACCESS; 51 | } 52 | syslog(LOG_DEBUG, "Adafruit_BBIO: set_pin_mode() :: Pinmux file %s access OK", path); 53 | fprintf(f, "%s", mode); 54 | fclose(f); 55 | syslog(LOG_DEBUG, "Adafruit_BBIO: set_pin_mode() :: Set pinmux mode to %s for %s", mode, pin); 56 | return BBIO_OK; 57 | } 58 | -------------------------------------------------------------------------------- /source/c_pinmux.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016 Adafruit 3 | Author: Matthew West 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #ifndef C_PINMUX_H 25 | #define C_PINMUX_H 26 | 27 | #include "common.h" 28 | 29 | BBIO_err set_pin_mode(const char *key, const char *mode); 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /source/c_pwm.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | Author: Justin Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | #ifndef C_PWM_H 24 | #define C_PWM_H 25 | 26 | #include "common.h" 27 | 28 | BBIO_err initialize_pwm(void); 29 | BBIO_err pwm_start(const char *key, float duty, float freq, int polarity); 30 | BBIO_err pwm_disable(const char *key); 31 | BBIO_err pwm_set_frequency(const char *key, float freq); 32 | BBIO_err pwm_set_duty_cycle(const char *key, float duty); 33 | BBIO_err pwm_set_polarity(const char *key, int polarity); 34 | void pwm_cleanup(void); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /source/c_uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | Author: Justin Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "c_uart.h" 31 | #include "common.h" 32 | 33 | BBIO_err uart_setup(const char *dt) 34 | { 35 | return load_device_tree(dt); 36 | } 37 | 38 | BBIO_err uart_cleanup(void) 39 | { 40 | BBIO_err e1, e2, e3, e4, e5; 41 | e1 = unload_device_tree("ADAFRUIT-UART1"); 42 | e2 = unload_device_tree("ADAFRUIT-UART2"); 43 | e3 = unload_device_tree("ADAFRUIT-UART3"); 44 | e4 = unload_device_tree("ADAFRUIT-UART4"); 45 | e5 = unload_device_tree("ADAFRUIT-UART5"); 46 | if (e1 != BBIO_OK) 47 | return e1; 48 | if (e2 != BBIO_OK) 49 | return e2; 50 | if (e3 != BBIO_OK) 51 | return e3; 52 | if (e4 != BBIO_OK) 53 | return e4; 54 | if (e5 != BBIO_OK) 55 | return e5; 56 | 57 | return BBIO_OK; 58 | } 59 | -------------------------------------------------------------------------------- /source/c_uart.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | Author: Justin Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | #ifndef C_UART_H 24 | #define C_UART_H 25 | #include "common.h" 26 | 27 | BBIO_err uart_setup(const char *dt); 28 | BBIO_err uart_cleanup(void); 29 | #endif 30 | -------------------------------------------------------------------------------- /source/common.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | 4 | Original RPi.GPIO Author Ben Croston 5 | Modified for BBIO Author Justin Cooper 6 | 7 | This file incorporates work covered by the following copyright and 8 | permission notice, all modified code adopts the original license: 9 | 10 | Copyright (c) 2013 Ben Croston 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of 13 | this software and associated documentation files (the "Software"), to deal in 14 | the Software without restriction, including without limitation the rights to 15 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 16 | of the Software, and to permit persons to whom the Software is furnished to do 17 | so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | 31 | #ifndef COMMON_H 32 | #define COMMON_H 33 | 34 | #include 35 | 36 | #include "adafruit/bbio/error.h" 37 | #ifdef __cplusplus 38 | using adafruit::bbio::BBIO_err; 39 | #endif 40 | 41 | #define MODE_UNKNOWN -1 42 | #define BOARD 10 43 | #define BCM 11 44 | 45 | #define CTRL_DIR_MAX 50 46 | #define OCP_DIR_MAX 50 47 | 48 | #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) 49 | 50 | #define FILENAME_BUFFER_SIZE 128 51 | #define MAX_PATH 256 52 | 53 | // Modeled after "pwm": submap in bone.js from bonescript 54 | // https://github.com/jadonk/bonescript/blob/master/src/bone.js#L680 55 | typedef struct pwm_t { 56 | const char *module; 57 | const int sysfs; 58 | const int index; 59 | const int muxmode; 60 | const char *path; 61 | const char *name; 62 | const char *chip; 63 | const char *addr; 64 | const char *key; // Pin name eg P9_21 65 | } pwm_t; 66 | 67 | 68 | typedef struct uart_t { 69 | const char *name; 70 | const char *path; 71 | const char *dt; 72 | const char *rx; 73 | const char *tx; 74 | } uart_t; 75 | 76 | extern uart_t uart_table[]; 77 | 78 | extern int gpio_mode; 79 | extern int gpio_direction[120]; 80 | 81 | extern char ctrl_dir[CTRL_DIR_MAX]; 82 | extern char ocp_dir[OCP_DIR_MAX]; 83 | 84 | BBIO_err get_gpio_number(const char *key, unsigned int *gpio); 85 | BBIO_err get_pwm_key(const char *input, char *key); 86 | BBIO_err get_adc_ain(const char *key, int *ain); 87 | BBIO_err get_uart_device_tree_name(const char *name, char *dt); 88 | BBIO_err build_path(const char *partial_path, const char *prefix, char *full_path, size_t full_path_len); 89 | int get_spi_bus_path_number(unsigned int spi); 90 | BBIO_err load_device_tree(const char *name); 91 | BBIO_err unload_device_tree(const char *name); 92 | int device_tree_loaded(const char *name); 93 | BBIO_err get_pwm_by_key(const char *key, pwm_t **pwm); 94 | int uboot_overlay_enabled(void); 95 | int beaglebone_blue(void); 96 | int pocketbeagle(void); 97 | 98 | #define BBIO_LOG_OPTION LOG_CONS | LOG_PID | LOG_NDELAY 99 | void initlog(int level, const char* ident, int option); 100 | 101 | extern int setup_error; 102 | extern int module_setup; 103 | 104 | #endif 105 | -------------------------------------------------------------------------------- /source/constants.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | 4 | Original RPi.GPIO Author Ben Croston 5 | Modified for BBIO Author Justin Cooper 6 | 7 | This file incorporates work covered by the following copyright and 8 | permission notice, all modified code adopts the original license: 9 | 10 | Copyright (c) 2013 Ben Croston 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of 13 | this software and associated documentation files (the "Software"), to deal in 14 | the Software without restriction, including without limitation the rights to 15 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 16 | of the Software, and to permit persons to whom the Software is furnished to do 17 | so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | 31 | #include "Python.h" 32 | #include "constants.h" 33 | #include "event_gpio.h" 34 | #include "common.h" 35 | 36 | void define_constants(PyObject *module) 37 | { 38 | PyObject *object; 39 | 40 | object = Py_BuildValue("i", HIGH); 41 | PyModule_AddObject(module, "HIGH", object); 42 | 43 | object = Py_BuildValue("i", LOW); 44 | PyModule_AddObject(module, "LOW", object); 45 | 46 | object = Py_BuildValue("i", OUTPUT); 47 | PyModule_AddObject(module, "OUT", object); 48 | 49 | object = Py_BuildValue("i", INPUT); 50 | PyModule_AddObject(module, "IN", object); 51 | 52 | object = Py_BuildValue("i", ALT0); 53 | PyModule_AddObject(module, "ALT0", object); 54 | 55 | object = Py_BuildValue("i", PUD_OFF); 56 | PyModule_AddObject(module, "PUD_OFF", object); 57 | 58 | object = Py_BuildValue("i", PUD_UP); 59 | PyModule_AddObject(module, "PUD_UP", object); 60 | 61 | object = Py_BuildValue("i", PUD_DOWN); 62 | PyModule_AddObject(module, "PUD_DOWN", object); 63 | 64 | object = Py_BuildValue("i", RISING_EDGE); 65 | PyModule_AddObject(module, "RISING", object); 66 | 67 | object = Py_BuildValue("i", FALLING_EDGE); 68 | PyModule_AddObject(module, "FALLING", object); 69 | 70 | object = Py_BuildValue("i", BOTH_EDGE); 71 | PyModule_AddObject(module, "BOTH", object); 72 | 73 | object = Py_BuildValue("s", "0.0.20"); 74 | PyModule_AddObject(module, "VERSION", object); 75 | } 76 | -------------------------------------------------------------------------------- /source/constants.h: -------------------------------------------------------------------------------- 1 | #ifndef CONSTANTS_H 2 | #define CONSTANTS_H 3 | 4 | void define_constants(PyObject *module); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /source/event_gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | 4 | Original RPi.GPIO Author Ben Croston 5 | Modified for BBIO Author Justin Cooper 6 | 7 | This file incorporates work covered by the following copyright and 8 | permission notice, all modified code adopts the original license: 9 | 10 | Copyright (c) 2013 Ben Croston 11 | 12 | Permission is hereby granted, free of charge, to any person obtaining a copy of 13 | this software and associated documentation files (the "Software"), to deal in 14 | the Software without restriction, including without limitation the rights to 15 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 16 | of the Software, and to permit persons to whom the Software is furnished to do 17 | so, subject to the following conditions: 18 | 19 | The above copyright notice and this permission notice shall be included in all 20 | copies or substantial portions of the Software. 21 | 22 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 23 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 24 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 25 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 26 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 27 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 28 | SOFTWARE. 29 | */ 30 | #ifndef EVENT_GPIO_H 31 | #define EVENT_GPIO_H 32 | 33 | #include "adafruit/bbio/error.h" 34 | 35 | #define NO_EDGE 0 36 | #define RISING_EDGE 1 37 | #define FALLING_EDGE 2 38 | #define BOTH_EDGE 3 39 | 40 | #define INPUT 0 41 | #define OUTPUT 1 42 | #define ALT0 4 43 | 44 | #define HIGH 1 45 | #define LOW 0 46 | 47 | #define MAX_FILENAME 60 48 | 49 | #define USR_LED_GPIO_MIN 53 50 | #define USR_LED_GPIO_MAX 56 51 | #define USR_LED_RED 66 52 | #define USR_LED_GREEN 67 53 | #define BAT25 27 54 | #define BAT50 11 55 | #define BAT75 61 56 | #define BAT100 10000 // Placeholder until I find the real number 57 | #define WIFI 10001 // Ditto 58 | 59 | #define PUD_OFF 0 60 | #define PUD_DOWN 1 61 | #define PUD_UP 2 62 | 63 | BBIO_err gpio_export(unsigned int gpio); 64 | BBIO_err gpio_unexport(unsigned int gpio); 65 | void exports_cleanup(void); 66 | BBIO_err gpio_set_direction(unsigned int gpio, unsigned int in_flag); 67 | BBIO_err gpio_get_direction(unsigned int gpio, unsigned int *value); 68 | BBIO_err gpio_set_value(unsigned int gpio, unsigned int value); 69 | BBIO_err gpio_get_value(unsigned int gpio, unsigned int *value); 70 | 71 | int add_edge_detect(unsigned int gpio, unsigned int edge); 72 | void remove_edge_detect(unsigned int gpio); 73 | int add_edge_callback(unsigned int gpio, void (*func)(unsigned int gpio)); 74 | int event_detected(unsigned int gpio); 75 | int gpio_initial(unsigned int gpio); 76 | int gpio_event_add(unsigned int gpio); 77 | int gpio_event_remove(unsigned int gpio); 78 | int gpio_is_evented(unsigned int gpio); 79 | int event_initialise(void); 80 | void event_cleanup(void); 81 | int blocking_wait_for_edge(unsigned int gpio, unsigned int edge, int timeout); 82 | 83 | #endif 84 | -------------------------------------------------------------------------------- /source/examples/cpp/gpio.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "adafruit/bbio.h" 25 | 26 | #include 27 | #include 28 | 29 | int main(int /*argc*/, char** /*argv*/) 30 | { 31 | using adafruit::bbio::lib_options; 32 | using adafruit::bbio::Gpio; 33 | 34 | adafruit::bbio::init(lib_options(LOG_DEBUG, nullptr, LOG_PERROR)); 35 | 36 | Gpio gpio("P8_10", Gpio::Direction::Output); 37 | 38 | for (int i = 0; i < 100; ++i) { 39 | gpio.set_value((i % 2 == 1) ? Gpio::Value::High : Gpio::Value::Low); 40 | std::this_thread::sleep_for(std::chrono::seconds(1)); 41 | } 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /source/examples/cpp/pwm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "adafruit/bbio.h" 25 | 26 | #include 27 | #include 28 | 29 | int main(int /*argc*/, char** /*argv*/) 30 | { 31 | using adafruit::bbio::Pwm; 32 | 33 | adafruit::bbio::init({LOG_DEBUG, nullptr, LOG_PERROR}); 34 | 35 | Pwm pwm("P8_19"); 36 | pwm.start(0., 1e9 / (1 * 1000 * 1000), Pwm::Polarity::Normal); 37 | 38 | for (int i = 0; i < 1000; ++i) { 39 | pwm.set_duty_cycle(i / 10.0); 40 | std::this_thread::sleep_for(std::chrono::milliseconds(500)); 41 | } 42 | 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /source/examples/python/blinkLEDs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import Adafruit_BBIO.GPIO as GPIO 3 | import time 4 | 5 | LEDs = ["USR0", "USR1", "USR2", "USR3", 6 | "GP0_3", "GP0_5", "GP0_6", 7 | "GP1_3", "GP1_4", 8 | "RED", "GREEN", 9 | "BAT25", "BAT50", "BAT75", "BAT100", 10 | "WIFI" 11 | ] 12 | delay = 0.25 13 | 14 | for LED in LEDs: 15 | print(LED) 16 | GPIO.setup(LED, GPIO.OUT) 17 | 18 | while True: 19 | for LED in LEDs: 20 | GPIO.output(LED, 1) 21 | time.sleep(delay) 22 | for LED in LEDs: 23 | GPIO.output(LED, 0) 24 | time.sleep(delay) -------------------------------------------------------------------------------- /source/examples/python/button.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Reads the PAUSE button using interupts and sets the LED 3 | # Pin table at https://github.com/beagleboard/beaglebone-blue/blob/master/BeagleBone_Blue_Pin_Table.csv 4 | 5 | # Import PyBBIO library: 6 | import Adafruit_BBIO.GPIO as GPIO 7 | import time 8 | 9 | button= "PAUSE" # PAUSE=P8_9, MODE=P8_10 10 | LED1 = "RED" 11 | LED2 = "WIFI" 12 | 13 | # Set the GPIO pins: 14 | GPIO.setup(LED1, GPIO.OUT) 15 | GPIO.setup(LED2, GPIO.OUT) 16 | GPIO.setup(button, GPIO.IN) 17 | 18 | print("Running...") 19 | 20 | while True: 21 | state = GPIO.input(button) 22 | GPIO.output(LED1, state) 23 | GPIO.output(LED2, state) 24 | 25 | GPIO.wait_for_edge(button, GPIO.BOTH) 26 | print("Pressed") -------------------------------------------------------------------------------- /source/examples/python/gpio.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Blinks some gpio pins on the Blue 3 | import Adafruit_BBIO.GPIO as GPIO 4 | import time 5 | 6 | LEDs = ["GP0_3", "GP0_4", "GP0_5", "GP0_6", "GP1_3", "GP1_4", 7 | "RED_LED", "GREEN_LED"] 8 | for LED in LEDs: 9 | print(LED) 10 | GPIO.setup(LED, GPIO.OUT) 11 | 12 | while True: 13 | for LED in LEDs: 14 | GPIO.output(LED, GPIO.HIGH) 15 | time.sleep(0.1) 16 | GPIO.output(LED, GPIO.LOW) 17 | -------------------------------------------------------------------------------- /source/examples/python/i2cmatrix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Write an 8x8 Red/Green LED matrix 3 | # https://www.adafruit.com/product/902 4 | 5 | import smbus 6 | import time 7 | bus = smbus.SMBus(1) 8 | matrix = 0x70 9 | 10 | delay = 1; # Delay between images in s 11 | 12 | bus.write_byte_data(matrix, 0x21, 0) # Start oscillator (p10) 13 | bus.write_byte_data(matrix, 0x81, 0) # Disp on, blink off (p11) 14 | bus.write_byte_data(matrix, 0xe7, 0) # Full brightness (page 15) 15 | 16 | # The first byte is GREEN, the second is RED. 17 | smile = [0x00, 0x3c, 0x00, 0x42, 0x28, 0x89, 0x04, 0x85, 18 | 0x04, 0x85, 0x28, 0x89, 0x00, 0x42, 0x00, 0x3c 19 | ] 20 | frown = [0x3c, 0x00, 0x42, 0x00, 0x85, 0x20, 0x89, 0x00, 21 | 0x89, 0x00, 0x85, 0x20, 0x42, 0x00, 0x3c, 0x00 22 | ] 23 | neutral = [0x3c, 0x3c, 0x42, 0x42, 0xa9, 0xa9, 0x89, 0x89, 24 | 0x89, 0x89, 0xa9, 0xa9, 0x42, 0x42, 0x3c, 0x3c 25 | ] 26 | 27 | bus.write_i2c_block_data(matrix, 0, frown) 28 | for fade in range(0xef, 0xe0, -1): 29 | bus.write_byte_data(matrix, fade, 0) 30 | time.sleep(delay/10) 31 | 32 | bus.write_i2c_block_data(matrix, 0, neutral) 33 | for fade in range(0xe0, 0xef, 1): 34 | bus.write_byte_data(matrix, fade, 0) 35 | time.sleep(delay/10) 36 | 37 | bus.write_i2c_block_data(matrix, 0, smile) 38 | -------------------------------------------------------------------------------- /source/examples/python/i2ctmp101.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Read a TMP101 sensor 3 | 4 | import smbus 5 | import time 6 | bus = smbus.SMBus(1) 7 | address = 0x49 8 | 9 | while True: 10 | temp = bus.read_byte_data(address, 0) 11 | print(temp, end="\r") 12 | time.sleep(0.25) 13 | -------------------------------------------------------------------------------- /source/examples/python/install.sh: -------------------------------------------------------------------------------- 1 | # Here's what you need to install to run these. 2 | 3 | sudo apt install python3-smbus 4 | -------------------------------------------------------------------------------- /source/examples/python/leds.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Blinks some gpio pins on the Blue 3 | import Adafruit_BBIO.GPIO as GPIO 4 | import time 5 | 6 | LEDs = ["RED", "GREEN"] 7 | 8 | for LED in LEDs: 9 | GPIO.setup(LED, GPIO.OUT) 10 | 11 | while True: 12 | for LED in LEDs: 13 | GPIO.output(LED, GPIO.HIGH) 14 | time.sleep(0.1) 15 | GPIO.output(LED, GPIO.LOW) 16 | time.sleep(0.1) -------------------------------------------------------------------------------- /source/examples/python/pwm.old.py: -------------------------------------------------------------------------------- 1 | import Adafruit_BBIO.PWM as PWM 2 | 3 | #set polarity to 1 on start: 4 | #PWM.start("P9_14", 50, 2000, 1) 5 | 6 | #PWM.start(channel, duty, freq=2000, polarity=0) 7 | #duty values are valid 0 (off) to 100 (on) 8 | 9 | PWM.start("P9_14", 50) 10 | PWM.set_duty_cycle("P9_14", 25.5) 11 | PWM.set_frequency("P9_14", 10) 12 | 13 | PWM.stop("P9_14") 14 | PWM.cleanup() 15 | -------------------------------------------------------------------------------- /source/examples/python/pwm.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import Adafruit_BBIO.PWM as PWM 3 | 4 | #set polarity to 1 on start: 5 | #PWM.start("P9_14", 50, 2000, 1) 6 | 7 | #PWM.start(channel, duty, freq=2000, polarity=0) 8 | #duty values are valid 0 (off) to 100 (on) 9 | 10 | SERVO="P9_14" 11 | PWM.start(SERVO, 50) 12 | PWM.set_duty_cycle(SERVO, 25.5) 13 | PWM.set_frequency(SERVO, 10) 14 | 15 | PWM.stop(SERVO) 16 | PWM.cleanup() 17 | -------------------------------------------------------------------------------- /source/include/adafruit/bbio.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | #pragma once 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | namespace adafruit { 32 | namespace bbio { 33 | 34 | struct lib_options 35 | { 36 | int syslog_level; 37 | 38 | // If NULL then syslog uses process name. 39 | char const* syslog_identifier; 40 | 41 | // Add LOG_PERROR to print to console 42 | int syslog_option; 43 | 44 | lib_options(int syslog_level = LOG_INFO, 45 | char const* syslog_identifier = nullptr, 46 | int syslog_option = LOG_CONS | LOG_PID | LOG_NDELAY) 47 | : syslog_level(syslog_level) 48 | , syslog_identifier(syslog_identifier) 49 | , syslog_option(syslog_option) 50 | {} 51 | }; 52 | 53 | /* 54 | * Initialize the library. 55 | */ 56 | void init(lib_options = lib_options()); 57 | 58 | } // namespace bbio 59 | } // namespace adafruit 60 | -------------------------------------------------------------------------------- /source/include/adafruit/bbio/error.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | #pragma once 24 | 25 | #ifdef __cplusplus 26 | 27 | #include 28 | 29 | namespace adafruit { 30 | namespace bbio { 31 | 32 | #endif // __cplusplus 33 | 34 | typedef enum { 35 | BBIO_OK, // No error 36 | BBIO_ACCESS, // Error accessing a file 37 | BBIO_SYSFS, // Some error with Sysfs files 38 | BBIO_CAPE, // some error with capes 39 | BBIO_INVARG, // Invalid argument 40 | BBIO_MEM, 41 | BBIO_GEN // General error 42 | } BBIO_err; 43 | 44 | #ifdef __cplusplus 45 | 46 | class BBIOError : public std::runtime_error 47 | { 48 | public: 49 | BBIOError(BBIO_err code, std::string const& message = "") 50 | : std::runtime_error( 51 | std::to_string(code) + "-" + to_c_str(code) + " " + message) 52 | {} 53 | 54 | static char const* to_c_str(BBIO_err err) 55 | { 56 | switch (err) { 57 | case BBIO_OK: return "OK"; 58 | case BBIO_ACCESS: return "ACCESS"; 59 | case BBIO_SYSFS: return "SYSFS"; 60 | case BBIO_CAPE: return "CAPE"; 61 | case BBIO_INVARG: return "INVARG"; 62 | case BBIO_MEM: return "MEMORY"; 63 | case BBIO_GEN: return "GENERAL"; 64 | default: return ""; 65 | } 66 | } 67 | }; 68 | 69 | class CheckError 70 | { 71 | public: 72 | CheckError(BBIO_err code) 73 | { 74 | if (code != BBIO_OK) { 75 | throw BBIOError(code); 76 | } 77 | } 78 | CheckError(int code) 79 | { 80 | if (code != BBIO_OK) { 81 | throw BBIOError((BBIO_err)code); 82 | } 83 | } 84 | }; 85 | 86 | } // namespace bbio 87 | } // namespace adafruit 88 | 89 | #endif // __cplusplus 90 | -------------------------------------------------------------------------------- /source/include/adafruit/bbio/gpio.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | #pragma once 24 | 25 | #include 26 | 27 | namespace adafruit { 28 | namespace bbio { 29 | 30 | class Gpio 31 | { 32 | public: 33 | enum class Direction 34 | { 35 | Input = 0, 36 | Output = 1 37 | }; 38 | 39 | enum class Value 40 | { 41 | Low = 0, 42 | High = 1 43 | }; 44 | 45 | enum class Resistor 46 | { 47 | None = 0, 48 | PullDown = 1, 49 | PullUp = 2 50 | }; 51 | 52 | Gpio(std::string const& key, Direction, Resistor = Resistor::None); 53 | ~Gpio(); 54 | 55 | void set_direction(Direction, Resistor = Resistor::None); 56 | void set_value(Value); 57 | Value get_value() const; 58 | 59 | private: 60 | std::string key_; 61 | uint32_t pin_; 62 | Direction direction_; 63 | }; 64 | 65 | } // namespace bbio 66 | } // namespace adafruit 67 | -------------------------------------------------------------------------------- /source/include/adafruit/bbio/pwm.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | #pragma once 24 | 25 | #include 26 | 27 | namespace adafruit { 28 | namespace bbio { 29 | 30 | class Pwm 31 | { 32 | public: 33 | enum class Polarity 34 | { 35 | Normal = 0, 36 | Inversed = 1, 37 | }; 38 | 39 | Pwm(std::string const& key); 40 | ~Pwm(); 41 | 42 | void start(float duty_cycle = 0.0, float frequency = 2000.0, Polarity = Polarity::Normal); 43 | void stop(); 44 | 45 | // 0.0 <= duty_cycle <= 100.0 46 | void set_duty_cycle(float); 47 | void set_frequency(float); 48 | void set_polarity(Polarity); 49 | 50 | private: 51 | std::string key_; 52 | }; 53 | 54 | } // namespace bbio 55 | } // namespace adafruit 56 | -------------------------------------------------------------------------------- /source/library/bbio.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "adafruit/bbio.h" 25 | #include "adafruit/bbio/error.h" 26 | 27 | extern "C" { 28 | #include "common.h" 29 | #include "c_pwm.h" 30 | } 31 | 32 | namespace adafruit { 33 | namespace bbio { 34 | 35 | void init(lib_options lib_options) 36 | { 37 | initlog(lib_options.syslog_level, 38 | lib_options.syslog_identifier, 39 | lib_options.syslog_option); 40 | initialize_pwm(); 41 | } 42 | 43 | } // namespace bbio 44 | } // namespace adafruit 45 | -------------------------------------------------------------------------------- /source/library/gpio.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "adafruit/bbio/gpio.h" 25 | 26 | #include "adafruit/bbio/error.h" 27 | 28 | extern "C" { 29 | #include "common.h" 30 | #include "c_pinmux.h" 31 | #include "event_gpio.h" 32 | } 33 | 34 | namespace adafruit { 35 | namespace bbio { 36 | 37 | /* 38 | * Gpio 39 | */ 40 | Gpio::Gpio(std::string const& key, Direction direction, Resistor resistor) 41 | : key_(key) 42 | , pin_(0) 43 | { 44 | (CheckError)get_gpio_number(key_.c_str(), &pin_); 45 | (CheckError)gpio_export(pin_); 46 | 47 | timespec ts[] = {{0, 1 * 1000000}}; 48 | nanosleep(ts, NULL); 49 | 50 | set_direction(direction, resistor); 51 | } 52 | 53 | Gpio::~Gpio() 54 | { 55 | if (pin_) { 56 | gpio_unexport(pin_); 57 | } 58 | } 59 | 60 | void Gpio::set_direction(Direction direction, Resistor resistor) 61 | { 62 | (CheckError)gpio_set_direction(pin_, (uint32_t)direction); 63 | direction_ = direction; 64 | 65 | if (direction == Direction::Output) { 66 | // TODO: default value 67 | // (CheckError)gpio_set_value(pin_, (uint32_t)Value::Low); 68 | } 69 | else { 70 | switch (resistor) { 71 | case Resistor::None: 72 | (CheckError)set_pin_mode(key_.c_str(), "gpio"); 73 | break; 74 | case Resistor::PullDown: 75 | (CheckError)set_pin_mode(key_.c_str(), "gpio_pd"); 76 | break; 77 | case Resistor::PullUp: 78 | (CheckError)set_pin_mode(key_.c_str(), "gpio_pu"); 79 | break; 80 | } 81 | } 82 | } 83 | 84 | void Gpio::set_value(Value value) 85 | { 86 | if (direction_ != Direction::Output) { 87 | throw BBIOError(BBIO_INVARG, "Gpio: can't set value when direction is not Output!"); 88 | } 89 | 90 | (CheckError)gpio_set_value(pin_, (uint32_t)value); 91 | } 92 | 93 | Gpio::Value Gpio::get_value() const 94 | { 95 | if (direction_ != Direction::Input) { 96 | throw BBIOError(BBIO_INVARG, "Gpio: can't get value when direction is not Input!"); 97 | } 98 | 99 | uint32_t value; 100 | (CheckError)gpio_get_value(pin_, &value); 101 | return (Value)value; 102 | } 103 | 104 | } // namespace bbio 105 | } // namespace adafruit 106 | -------------------------------------------------------------------------------- /source/library/pwm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "adafruit/bbio/pwm.h" 25 | 26 | extern "C" { 27 | #include "c_pwm.h" 28 | } 29 | 30 | namespace adafruit { 31 | namespace bbio { 32 | 33 | /* 34 | * Pwm 35 | */ 36 | Pwm::Pwm(std::string const& key) 37 | : key_(key) 38 | {} 39 | 40 | Pwm::~Pwm() 41 | { 42 | stop(); 43 | } 44 | 45 | void Pwm::start(float duty_cycle, float frequency, Polarity polarity) 46 | { 47 | (CheckError)pwm_start(key_.c_str(), duty_cycle, frequency, (int)polarity); 48 | } 49 | 50 | void Pwm::stop() 51 | { 52 | (CheckError)pwm_disable(key_.c_str()); 53 | } 54 | 55 | void Pwm::set_duty_cycle(float duty_cycle) 56 | { 57 | (CheckError)pwm_set_duty_cycle(key_.c_str(), duty_cycle); 58 | } 59 | 60 | void Pwm::set_frequency(float frequency) 61 | { 62 | (CheckError)pwm_set_frequency(key_.c_str(), frequency); 63 | } 64 | 65 | void Pwm::set_polarity(Polarity polarity) 66 | { 67 | (CheckError)pwm_set_polarity(key_.c_str(), (int)polarity); 68 | } 69 | 70 | } // namespace bbio 71 | } // namespace adafruit 72 | 73 | -------------------------------------------------------------------------------- /source/py_adc.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | Author: Justin Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "Python.h" 25 | #include "constants.h" 26 | #include "common.h" 27 | #include "c_adc.h" 28 | 29 | // Cleanup function commented out because it is currently disabled and this 30 | // generates unused method warnings. See adc_methods[] definition further 31 | // below for reason for disabling the cleanup function. 32 | // python function cleanup() 33 | //static PyObject *py_cleanup(PyObject *self, PyObject *args) 34 | //{ 35 | // // unexport the ADC 36 | // adc_cleanup(); 37 | // 38 | // Py_RETURN_NONE; 39 | //} 40 | 41 | // python function setup() 42 | static PyObject *py_setup_adc(__attribute__ ((unused)) PyObject *self, __attribute__ ((unused)) PyObject *args) 43 | { 44 | BBIO_err err; 45 | 46 | err = adc_setup(); 47 | if (err != BBIO_OK) { 48 | PyErr_SetString(PyExc_RuntimeError, "Unable to setup ADC system. Possible causes are: \n" 49 | " - A cape with a conflicting pin mapping is loaded \n" 50 | " - A device tree object is loaded that uses the same name for a fragment: helper"); 51 | return NULL; 52 | } 53 | 54 | Py_RETURN_NONE; 55 | } 56 | 57 | // python function read(channel) 58 | static PyObject *py_read(__attribute__ ((unused)) PyObject *self, PyObject *args) 59 | { 60 | int ain; 61 | float value; 62 | char *channel; 63 | PyObject *py_value; 64 | BBIO_err err; 65 | 66 | if (!PyArg_ParseTuple(args, "s", &channel)) 67 | return NULL; 68 | 69 | // check setup was called prior 70 | if (!adc_initialized) 71 | { 72 | PyErr_SetString(PyExc_RuntimeError, "You must setup() ADC prior to calling read."); 73 | return NULL; 74 | } 75 | 76 | err = get_adc_ain(channel, &ain); 77 | if (err != BBIO_OK) { 78 | PyErr_SetString(PyExc_ValueError, "Invalid AIN key or name."); 79 | return NULL; 80 | } 81 | 82 | err = read_value(ain, &value); 83 | if (err != BBIO_OK) { 84 | PyErr_SetFromErrnoWithFilename(PyExc_IOError, "Error while reading AIN port. Invalid or locked AIN file."); 85 | return NULL; 86 | } 87 | 88 | //scale modifier 89 | #ifdef BBBVERSION41 90 | value = value / 4095.0; 91 | #else 92 | value = value / 1800.0; 93 | #endif 94 | 95 | py_value = Py_BuildValue("f", value); 96 | 97 | return py_value; 98 | } 99 | 100 | // python function read(channel) 101 | static PyObject *py_read_raw(__attribute__ ((unused)) PyObject *self, PyObject *args) 102 | { 103 | int ain; 104 | float value; 105 | char *channel; 106 | PyObject *py_value; 107 | BBIO_err err; 108 | 109 | if (!PyArg_ParseTuple(args, "s", &channel)) 110 | return NULL; 111 | 112 | // check setup was called prior 113 | if (!adc_initialized) 114 | { 115 | PyErr_SetString(PyExc_RuntimeError, "You must setup() ADC prior to calling read."); 116 | return NULL; 117 | } 118 | 119 | err = get_adc_ain(channel, &ain); 120 | if (err != BBIO_OK) { 121 | PyErr_SetString(PyExc_ValueError, "Invalid AIN key or name."); 122 | return NULL; 123 | } 124 | 125 | err = read_value(ain, &value); 126 | 127 | if (err != BBIO_OK) { 128 | PyErr_SetFromErrnoWithFilename(PyExc_IOError, "Error while reading AIN port. Invalid or locked AIN file."); 129 | return NULL; 130 | } 131 | 132 | py_value = Py_BuildValue("f", value); 133 | 134 | return py_value; 135 | } 136 | 137 | static const char moduledocstring[] = "ADC functionality of a BeagleBone using Python"; 138 | 139 | PyMethodDef adc_methods[] = { 140 | {"setup", py_setup_adc, METH_VARARGS, "Set up and start the ADC channel."}, 141 | {"read", (PyCFunction)py_read, METH_VARARGS, "Read the normalized 0-1.0 analog value for the channel" }, 142 | {"read_raw", (PyCFunction)py_read_raw, METH_VARARGS, "Read the raw analog value for the channel" }, 143 | //disable cleanup for now, as unloading the driver locks up the system 144 | //{"cleanup", py_cleanup, METH_VARARGS, "Clean up ADC."}, 145 | //{"setwarnings", py_setwarnings, METH_VARARGS, "Enable or disable warning messages"}, 146 | {NULL, NULL, 0, NULL} 147 | }; 148 | 149 | #if PY_MAJOR_VERSION > 2 150 | static struct PyModuleDef bbadcmodule = { 151 | PyModuleDef_HEAD_INIT, 152 | "ADC", // name of module 153 | moduledocstring, // module documentation, may be NULL 154 | -1, // size of per-interpreter state of the module, or -1 if the module keeps state in global variables. 155 | adc_methods 156 | }; 157 | #endif 158 | 159 | #if PY_MAJOR_VERSION > 2 160 | PyMODINIT_FUNC PyInit_ADC(void) 161 | #else 162 | PyMODINIT_FUNC initADC(void) 163 | #endif 164 | { 165 | PyObject *module = NULL; 166 | 167 | #if PY_MAJOR_VERSION > 2 168 | if ((module = PyModule_Create(&bbadcmodule)) == NULL) 169 | return NULL; 170 | #else 171 | if ((module = Py_InitModule3("ADC", adc_methods, moduledocstring)) == NULL) 172 | return; 173 | #endif 174 | 175 | define_constants(module); 176 | 177 | 178 | #if PY_MAJOR_VERSION > 2 179 | return module; 180 | #else 181 | return; 182 | #endif 183 | } 184 | -------------------------------------------------------------------------------- /source/py_pwm.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | Author: Justin Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "Python.h" 25 | #include "constants.h" 26 | #include "common.h" 27 | #include "c_pwm.h" 28 | #include 29 | 30 | // python function cleanup() 31 | static PyObject *py_cleanup(__attribute__ ((unused)) PyObject *self, __attribute__ ((unused)) PyObject *args) 32 | { 33 | // unexport the PWM 34 | pwm_cleanup(); 35 | 36 | Py_RETURN_NONE; 37 | } 38 | 39 | // python function start(channel, duty_cycle, freq) 40 | static PyObject *py_start_channel(__attribute__ ((unused)) PyObject *self, PyObject *args, PyObject *kwargs) 41 | { 42 | char key[8]; 43 | char *channel; 44 | float frequency = 2000.0; 45 | float duty_cycle = 0.0; 46 | int polarity = 0; 47 | BBIO_err err; 48 | static char *kwlist[] = {"channel", "duty_cycle", "frequency", "polarity", NULL}; 49 | 50 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|ffi", kwlist, &channel, &duty_cycle, &frequency, &polarity)) { 51 | return NULL; 52 | } 53 | 54 | err = get_pwm_key(channel, key); 55 | if (err != BBIO_OK) { 56 | PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name."); 57 | return NULL; 58 | } 59 | 60 | if (duty_cycle < 0.0 || duty_cycle > 100.0) 61 | { 62 | PyErr_SetString(PyExc_ValueError, "duty_cycle must have a value from 0.0 to 100.0"); 63 | return NULL; 64 | } 65 | 66 | if (frequency <= 0.0) 67 | { 68 | PyErr_SetString(PyExc_ValueError, "frequency must be greater than 0.0"); 69 | return NULL; 70 | } 71 | 72 | if (polarity < 0 || polarity > 1) { 73 | PyErr_SetString(PyExc_ValueError, "polarity must be either 0 or 1"); 74 | return NULL; 75 | } 76 | 77 | err = pwm_start(key, duty_cycle, frequency, polarity); 78 | switch (err) { 79 | case BBIO_OK: 80 | break; 81 | 82 | case BBIO_ACCESS: 83 | PyErr_SetString(PyExc_IOError, "could not access a necessary file"); 84 | return NULL; 85 | 86 | case BBIO_SYSFS: 87 | PyErr_SetString(PyExc_RuntimeError, "Problem with a sysfs file"); 88 | return NULL; 89 | 90 | case BBIO_CAPE: 91 | PyErr_SetString(PyExc_RuntimeError, "Problem with the cape manager"); 92 | return NULL; 93 | 94 | case BBIO_INVARG: 95 | PyErr_SetString(PyExc_ValueError, "Invalid argument"); 96 | return NULL; 97 | 98 | case BBIO_MEM: 99 | PyErr_SetString(PyExc_RuntimeError, "Out of memory"); 100 | return NULL; 101 | 102 | case BBIO_GEN: 103 | PyErr_SetString(PyExc_RuntimeError, "Unknown error"); 104 | return NULL; 105 | } 106 | Py_RETURN_NONE; 107 | } 108 | 109 | // python function stop(channel) 110 | static PyObject *py_stop_channel(__attribute__ ((unused)) PyObject *self, PyObject *args, __attribute__ ((unused)) PyObject *kwargs) 111 | { 112 | char key[8]; 113 | char *channel; 114 | BBIO_err err; 115 | 116 | if (!PyArg_ParseTuple(args, "s", &channel)) 117 | return NULL; 118 | 119 | err = get_pwm_key(channel, key); 120 | if (err == BBIO_INVARG) { 121 | PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name."); 122 | return NULL; 123 | } 124 | 125 | err = pwm_disable(key); 126 | switch (err) { 127 | case BBIO_OK: 128 | Py_RETURN_NONE; 129 | break; 130 | 131 | case BBIO_SYSFS: 132 | PyErr_SetString(PyExc_RuntimeError, "Problem with sysfs files"); 133 | return NULL; 134 | 135 | default: 136 | PyErr_SetString(PyExc_RuntimeError, "Unknown error"); 137 | return NULL; 138 | } 139 | } 140 | 141 | // python method PWM.set_duty_cycle(channel, duty_cycle) 142 | static PyObject *py_set_duty_cycle(__attribute__ ((unused)) PyObject *self, PyObject *args, PyObject *kwargs) 143 | { 144 | char key[8]; 145 | char *channel; 146 | float duty_cycle = 0.0; 147 | BBIO_err err; 148 | 149 | static char *kwlist[] = {"channel", "duty_cycle", NULL}; 150 | 151 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|f", kwlist, &channel, &duty_cycle)) 152 | return NULL; 153 | 154 | if (duty_cycle < 0.0 || duty_cycle > 100.0) 155 | { 156 | PyErr_SetString(PyExc_ValueError, "duty_cycle must have a value from 0.0 to 100.0"); 157 | return NULL; 158 | } 159 | 160 | err = get_pwm_key(channel, key); 161 | if (err != BBIO_OK) { 162 | PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name."); 163 | return NULL; 164 | } 165 | 166 | err = pwm_set_duty_cycle(key, duty_cycle); 167 | if (err != BBIO_OK) { 168 | PyErr_SetString(PyExc_RuntimeError, "You must start() the PWM channel first"); 169 | return NULL; 170 | } 171 | 172 | Py_RETURN_NONE; 173 | } 174 | 175 | // python method PWM.set_frequency(channel, frequency) 176 | static PyObject *py_set_frequency(__attribute__ ((unused)) PyObject *self, PyObject *args, PyObject *kwargs) 177 | { 178 | char key[8]; 179 | char *channel; 180 | float frequency = 1.0; 181 | static char *kwlist[] = {"channel", "frequency", NULL}; 182 | BBIO_err err; 183 | 184 | if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|f", kwlist, &channel, &frequency)) 185 | return NULL; 186 | 187 | if (frequency <= 0.0) 188 | { 189 | PyErr_SetString(PyExc_ValueError, "frequency must be greater than 0.0"); 190 | return NULL; 191 | } 192 | 193 | err = get_pwm_key(channel, key); 194 | if (err != BBIO_OK) { 195 | PyErr_SetString(PyExc_ValueError, "Invalid PWM key or name."); 196 | return NULL; 197 | } 198 | 199 | err = pwm_set_frequency(key, frequency); 200 | if (err == BBIO_GEN) { 201 | PyErr_SetString(PyExc_RuntimeError, "You must start() the PWM channel first."); 202 | return NULL; 203 | } else if (err == BBIO_SYSFS) { 204 | PyErr_SetString(PyExc_RuntimeError, "Could not write to the frequency file"); 205 | return NULL; 206 | } else if (err != BBIO_OK) { 207 | PyErr_SetString(PyExc_RuntimeError, "Other error"); 208 | return NULL; 209 | } 210 | 211 | Py_RETURN_NONE; 212 | } 213 | 214 | 215 | static const char moduledocstring[] = "PWM functionality of a BeagleBone using Python"; 216 | 217 | PyMethodDef pwm_methods[] = { 218 | {"start", (PyCFunction)(void *)py_start_channel, METH_VARARGS | METH_KEYWORDS, "Set up and start the PWM channel. channel can be in the form of 'P8_10', or 'EHRPWM2A'"}, 219 | {"stop", (PyCFunction)(void *)py_stop_channel, METH_VARARGS | METH_KEYWORDS, "Stop the PWM channel. channel can be in the form of 'P8_10', or 'EHRPWM2A'"}, 220 | { "set_duty_cycle", (PyCFunction)(void *)py_set_duty_cycle, METH_VARARGS | METH_KEYWORDS, "Change the duty cycle\ndutycycle - between 0.0 and 100.0" }, 221 | { "set_frequency", (PyCFunction)(void *)py_set_frequency, METH_VARARGS | METH_KEYWORDS, "Change the frequency\nfrequency - frequency in Hz (freq > 0.0)" }, 222 | {"cleanup", py_cleanup, METH_VARARGS, "Clean up by resetting all GPIO channels that have been used by this program to INPUT with no pullup/pulldown and no event detection"}, 223 | //{"setwarnings", py_setwarnings, METH_VARARGS, "Enable or disable warning messages"}, 224 | {NULL, NULL, 0, NULL} 225 | }; 226 | 227 | #if PY_MAJOR_VERSION > 2 228 | static struct PyModuleDef bbpwmmodule = { 229 | PyModuleDef_HEAD_INIT, 230 | "PWM", // name of module 231 | moduledocstring, // module documentation, may be NULL 232 | -1, // size of per-interpreter state of the module, or -1 if the module keeps state in global variables. 233 | pwm_methods 234 | }; 235 | #endif 236 | 237 | #if PY_MAJOR_VERSION > 2 238 | PyMODINIT_FUNC PyInit_PWM(void) 239 | #else 240 | PyMODINIT_FUNC initPWM(void) 241 | #endif 242 | { 243 | PyObject *module = NULL; 244 | 245 | #if PY_MAJOR_VERSION > 2 246 | if ((module = PyModule_Create(&bbpwmmodule)) == NULL) 247 | return NULL; 248 | #else 249 | if ((module = Py_InitModule3("PWM", pwm_methods, moduledocstring)) == NULL) 250 | return; 251 | #endif 252 | 253 | define_constants(module); 254 | 255 | initlog(LOG_INFO, NULL, BBIO_LOG_OPTION); 256 | 257 | #if PY_MAJOR_VERSION > 2 258 | return module; 259 | #else 260 | return; 261 | #endif 262 | } 263 | -------------------------------------------------------------------------------- /source/py_uart.c: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013 Adafruit 3 | Author: Justin Cooper 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "Python.h" 25 | #include "constants.h" 26 | #include "common.h" 27 | #include "c_uart.h" 28 | #include "c_pinmux.h" 29 | 30 | const char *valid_uarts[4] = {"UART1", "UART2", "UART4", "UART5"}; 31 | 32 | // python function cleanup() 33 | static PyObject *py_cleanup(__attribute__ ((unused)) PyObject *self, __attribute__ ((unused)) PyObject *args) 34 | { 35 | // unexport the UART 36 | uart_cleanup(); 37 | 38 | Py_RETURN_NONE; 39 | } 40 | 41 | // python function setup() 42 | static PyObject *py_setup_uart(__attribute__ ((unused)) PyObject *self, PyObject *args) 43 | { 44 | char dt[FILENAME_BUFFER_SIZE]; 45 | char *channel; 46 | BBIO_err err; 47 | 48 | if (!PyArg_ParseTuple(args, "s", &channel)) { 49 | PyErr_SetString(PyExc_ValueError, "Invalid UART channel."); 50 | return NULL; 51 | } 52 | 53 | err = get_uart_device_tree_name(channel, dt); 54 | if (err != BBIO_OK) { 55 | PyErr_SetString(PyExc_ValueError, "Invalid UART channel."); 56 | return NULL; 57 | } 58 | 59 | err = uart_setup(dt); 60 | if (err != BBIO_OK) { 61 | PyErr_SetString(PyExc_RuntimeError, "Unable to export UART channel."); 62 | return NULL; 63 | } 64 | 65 | #ifdef BBBVERSION41 66 | uart_t *p; 67 | for (p = uart_table; p->name != NULL; ++p) { 68 | if (strcmp(p->name, channel) == 0) { 69 | err = set_pin_mode(p->rx, "uart"); 70 | //Check if set_pin_mode() returned no error 71 | if (err != BBIO_OK) { 72 | fprintf(stderr, "py_setup_uart(%s): set_pin_mode() failed for pin=%s", channel, p->rx); 73 | PyErr_SetString(PyExc_ValueError, "Set pin mode failed for uart channel."); 74 | return NULL; 75 | } 76 | 77 | err = set_pin_mode(p->tx, "uart"); 78 | //Check if set_pin_mode() returned no error 79 | if (err != BBIO_OK) { 80 | fprintf(stderr, "py_setup_uart(%s): set_pin_mode() failed for pin=%s", channel, p->tx); 81 | PyErr_SetString(PyExc_ValueError, "Set pin mode failed for uart channel."); 82 | return NULL; 83 | } 84 | } 85 | } 86 | #endif 87 | 88 | Py_RETURN_NONE; 89 | } 90 | 91 | static const char moduledocstring[] = "UART functionality of a BeagleBone using Python"; 92 | 93 | PyMethodDef uart_methods[] = { 94 | {"setup", py_setup_uart, METH_VARARGS, "Set up and start the UART channel."}, 95 | {"cleanup", py_cleanup, METH_VARARGS, "Clean up UART."}, 96 | //{"setwarnings", py_setwarnings, METH_VARARGS, "Enable or disable warning messages"}, 97 | {NULL, NULL, 0, NULL} 98 | }; 99 | 100 | #if PY_MAJOR_VERSION > 2 101 | static struct PyModuleDef bbuartmodule = { 102 | PyModuleDef_HEAD_INIT, 103 | "UART", // name of module 104 | moduledocstring, // module documentation, may be NULL 105 | -1, // size of per-interpreter state of the module, or -1 if the module keeps state in global variables. 106 | uart_methods 107 | }; 108 | #endif 109 | 110 | #if PY_MAJOR_VERSION > 2 111 | PyMODINIT_FUNC PyInit_UART(void) 112 | #else 113 | PyMODINIT_FUNC initUART(void) 114 | #endif 115 | { 116 | PyObject *module = NULL; 117 | 118 | #if PY_MAJOR_VERSION > 2 119 | if ((module = PyModule_Create(&bbuartmodule)) == NULL) 120 | return NULL; 121 | #else 122 | if ((module = Py_InitModule3("UART", uart_methods, moduledocstring)) == NULL) 123 | return; 124 | #endif 125 | 126 | define_constants(module); 127 | 128 | 129 | #if PY_MAJOR_VERSION > 2 130 | return module; 131 | #else 132 | return; 133 | #endif 134 | } 135 | -------------------------------------------------------------------------------- /source/test/cpp/abi.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "adafruit/bbio.h" 25 | 26 | int main(int /*argc*/, char** /*argv*/) 27 | { 28 | adafruit::bbio::init({LOG_DEBUG, nullptr, LOG_PERROR}); 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /source/test/cpp/pwm.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017 Adafruit 3 | Copyright (c) 2017 Nikolay Semenov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 9 | of the Software, and to permit persons to whom the Software is furnished to do 10 | so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | */ 23 | 24 | #include "adafruit/bbio.h" 25 | 26 | #include 27 | 28 | #include 29 | 30 | #include 31 | 32 | #include 33 | #if LINUX_VERSION_CODE >= KERNEL_VERSION(4,1,0) 34 | # ifndef BBBVERSION41 35 | # define BBBVERSION41 36 | # endif 37 | #endif 38 | 39 | using adafruit::bbio::Pwm; 40 | using adafruit::bbio::BBIOError; 41 | 42 | class PwmTest : public testing::Test 43 | { 44 | public: 45 | PwmTest() 46 | { 47 | adafruit::bbio::init({ LOG_DEBUG, nullptr, LOG_PERROR }); 48 | } 49 | 50 | void SetUp() override {} 51 | void TearDown() override {} 52 | 53 | static std::string get_pwm_dir() 54 | { 55 | struct auto_glob 56 | { 57 | glob_t value; 58 | ~auto_glob() 59 | { 60 | globfree(&value); 61 | } 62 | }; 63 | 64 | #ifdef BBBVERSION41 65 | // On 4.1+, the pwm subdirectory sometimes takes different names: 66 | // .pwm or .ehrpwm, etc. 67 | 68 | std::string pattern = "/sys/devices/platform/ocp/48302000.*/" 69 | "48302200.*/pwm/pwmchip?/pwm0"; 70 | #else 71 | std::string pattern = "/sys/devices/ocp.*/pwm_test_P9_14*"; 72 | #endif 73 | 74 | auto_glob results; 75 | int err = glob(pattern.c_str(), 0, NULL, &results.value); 76 | if (err) { 77 | return NULL; 78 | } 79 | 80 | // We will return the first match 81 | return results.value.gl_pathv[0]; 82 | } 83 | 84 | static std::string read_file(std::string const& path) 85 | { 86 | std::ifstream fstream(path); 87 | std::stringstream buffer; 88 | buffer << fstream.rdbuf(); 89 | std::string str = buffer.str(); 90 | if (!str.empty() && str.back() == '\n') { 91 | str.resize(str.length()-1); 92 | } 93 | return str; 94 | } 95 | 96 | static std::string read_duty_cycle(std::string const& pwm_dir) 97 | { 98 | #ifdef BBBVERSION41 99 | return read_file(pwm_dir + "/duty_cycle"); 100 | #else 101 | return read_file(pwm_dir + "/duty"); 102 | #endif 103 | } 104 | 105 | static std::string read_period(std::string const& pwm_dir) 106 | { 107 | return read_file(pwm_dir + "/period"); 108 | } 109 | 110 | static std::string read_polarity(std::string const& pwm_dir) 111 | { 112 | return read_file(pwm_dir + "/polarity"); 113 | } 114 | 115 | static char const* polarity_str(Pwm::Polarity value) 116 | { 117 | #ifdef BBBVERSION41 118 | return value == Pwm::Polarity::Normal ? "normal" : "inversed"; 119 | #else 120 | return value == Pwm::Polarity::Normal ? "0" : "1"; 121 | #endif 122 | } 123 | }; 124 | 125 | TEST_F(PwmTest, start_pwm) 126 | { 127 | Pwm pwm("P9_14"); 128 | pwm.start(); 129 | 130 | auto pwm_dir = get_pwm_dir(); 131 | ASSERT_FALSE(pwm_dir.empty()); 132 | 133 | auto duty = read_duty_cycle(pwm_dir); 134 | auto period = read_period(pwm_dir); 135 | ASSERT_EQ(duty, "0"); 136 | ASSERT_EQ(period, "500000"); 137 | } 138 | 139 | TEST_F(PwmTest, start_pwm_ecap0) 140 | { 141 | Pwm pwm("P9_42"); 142 | pwm.start(0); 143 | 144 | auto pwm_dir = get_pwm_dir(); 145 | ASSERT_FALSE(pwm_dir.empty()); 146 | 147 | auto duty = read_duty_cycle(pwm_dir); 148 | auto period = read_period(pwm_dir); 149 | 150 | ASSERT_EQ(duty, "0"); 151 | ASSERT_EQ(period, "500000"); 152 | } 153 | 154 | TEST_F(PwmTest, start_pwm_with_polarity_one) 155 | { 156 | Pwm pwm("P9_14"); 157 | pwm.start(0, 2000, Pwm::Polarity::Inversed); 158 | 159 | auto pwm_dir = get_pwm_dir(); 160 | ASSERT_FALSE(pwm_dir.empty()); 161 | 162 | auto duty = read_duty_cycle(pwm_dir); 163 | auto period = read_period(pwm_dir); 164 | auto polarity = read_polarity(pwm_dir); 165 | 166 | ASSERT_EQ(duty, "0"); 167 | ASSERT_EQ(period, "500000"); 168 | ASSERT_EQ(polarity, polarity_str(Pwm::Polarity::Inversed)); 169 | } 170 | 171 | TEST_F(PwmTest, start_pwm_with_polarity_default) 172 | { 173 | Pwm pwm("P9_14"); 174 | pwm.start(0, 2000); 175 | 176 | auto pwm_dir = get_pwm_dir(); 177 | ASSERT_FALSE(pwm_dir.empty()); 178 | 179 | auto duty = read_duty_cycle(pwm_dir); 180 | auto period = read_period(pwm_dir); 181 | auto polarity = read_polarity(pwm_dir); 182 | 183 | ASSERT_EQ(duty, "0"); 184 | ASSERT_EQ(period, "500000"); 185 | ASSERT_EQ(polarity, polarity_str(Pwm::Polarity::Normal)); 186 | } 187 | 188 | TEST_F(PwmTest, start_pwm_with_polarity_zero) 189 | { 190 | Pwm pwm("P9_14"); 191 | pwm.start(0, 2000, Pwm::Polarity::Normal); 192 | 193 | auto pwm_dir = get_pwm_dir(); 194 | ASSERT_FALSE(pwm_dir.empty()); 195 | 196 | auto duty = read_duty_cycle(pwm_dir); 197 | auto period = read_period(pwm_dir); 198 | auto polarity = read_polarity(pwm_dir); 199 | 200 | ASSERT_EQ(duty, "0"); 201 | ASSERT_EQ(period, "500000"); 202 | ASSERT_EQ(polarity, polarity_str(Pwm::Polarity::Normal)); 203 | } 204 | 205 | TEST_F(PwmTest, pwm_start_invalid_pwm_key) 206 | { 207 | Pwm pwm("P8_25"); 208 | ASSERT_THROW(pwm.start(), BBIOError); 209 | } 210 | 211 | TEST_F(PwmTest, pwm_start_invalid_duty_cycle_negative) 212 | { 213 | Pwm pwm("P9_14"); 214 | ASSERT_THROW(pwm.start(-1), BBIOError); 215 | } 216 | 217 | TEST_F(PwmTest, pwm_start_valid_duty_cycle_min) 218 | { 219 | // testing an exception isn't thrown 220 | Pwm pwm("P9_14"); 221 | pwm.start(0); 222 | } 223 | 224 | TEST_F(PwmTest, pwm_start_valid_duty_cycle_max) 225 | { 226 | // testing an exception isn't thrown 227 | Pwm pwm("P9_14"); 228 | pwm.start(100); 229 | } 230 | 231 | TEST_F(PwmTest, pwm_start_invalid_duty_cycle_high) 232 | { 233 | Pwm pwm("P9_14"); 234 | ASSERT_THROW(pwm.start(101), BBIOError); 235 | } 236 | 237 | TEST_F(PwmTest, pwm_start_invalid_frequency_negative) 238 | { 239 | Pwm pwm("P9_14"); 240 | ASSERT_THROW(pwm.start(0, -1), BBIOError); 241 | } 242 | 243 | TEST_F(PwmTest, pwm_start_negative_polarity) 244 | { 245 | Pwm pwm("P9_14"); 246 | ASSERT_THROW(pwm.start(0, 100, static_cast(-1)), BBIOError); 247 | } 248 | 249 | TEST_F(PwmTest, pwm_start_invalid_positive_polarity) 250 | { 251 | Pwm pwm("P9_14"); 252 | ASSERT_THROW(pwm.start(0, 100, static_cast(2)), BBIOError); 253 | } 254 | 255 | TEST_F(PwmTest, pwm_duty_modified) 256 | { 257 | Pwm pwm("P9_14"); 258 | pwm.start(0); 259 | 260 | auto pwm_dir = get_pwm_dir(); 261 | ASSERT_FALSE(pwm_dir.empty()); 262 | 263 | { 264 | auto duty = read_duty_cycle(pwm_dir); 265 | auto period = read_period(pwm_dir); 266 | ASSERT_EQ(duty, "0"); 267 | ASSERT_EQ(period, "500000"); 268 | } 269 | { 270 | pwm.set_duty_cycle(100); 271 | auto duty = read_duty_cycle(pwm_dir); 272 | auto period = read_period(pwm_dir); 273 | ASSERT_EQ(duty, "500000"); 274 | ASSERT_EQ(period, "500000"); 275 | } 276 | } 277 | 278 | TEST_F(PwmTest, pwm_duty_cycle_non_setup_key) 279 | { 280 | Pwm pwm("P9_14"); 281 | ASSERT_THROW(pwm.set_duty_cycle(100), BBIOError); 282 | } 283 | 284 | TEST_F(PwmTest, pwm_duty_cycle_invalid_key) 285 | { 286 | Pwm pwm("P9_15"); 287 | ASSERT_THROW(pwm.set_duty_cycle(100), BBIOError); 288 | } 289 | 290 | TEST_F(PwmTest, pwm_duty_cycle_invalid_value_high) 291 | { 292 | Pwm pwm("P9_14"); 293 | pwm.start(0); 294 | ASSERT_THROW(pwm.set_duty_cycle(101), BBIOError); 295 | } 296 | 297 | TEST_F(PwmTest, pwm_duty_cycle_invalid_value_negative) 298 | { 299 | Pwm pwm("P9_14"); 300 | pwm.start(0); 301 | ASSERT_THROW(pwm.set_duty_cycle(-1), BBIOError); 302 | } 303 | 304 | TEST_F(PwmTest, pwm_frequency_invalid_value_negative) 305 | { 306 | Pwm pwm("P9_14"); 307 | pwm.start(0); 308 | ASSERT_THROW(pwm.set_frequency(-1), BBIOError); 309 | } 310 | 311 | TEST_F(PwmTest, pwm_freq_non_setup_key) 312 | { 313 | Pwm pwm("P9_14"); 314 | ASSERT_THROW(pwm.set_frequency(100), BBIOError); 315 | } 316 | 317 | TEST_F(PwmTest, pwm_freq_non_setup_invalid_key) 318 | { 319 | Pwm pwm("P9_15"); 320 | ASSERT_THROW(pwm.set_frequency(100), BBIOError); 321 | } 322 | -------------------------------------------------------------------------------- /test/issue170-pwm.py: -------------------------------------------------------------------------------- 1 | import Adafruit_BBIO.PWM as PWM 2 | PWM.start("P9_14", 50, 2000, 1) 3 | PWM.cleanup() 4 | PWM.start("P9_14", 50, 2000, 0) 5 | PWM.cleanup() 6 | -------------------------------------------------------------------------------- /test/issue178.py: -------------------------------------------------------------------------------- 1 | # These are all the LEDs defined in source/event_gpio.h: 2 | # #define USR_LED_GPIO_MIN 53 3 | # #define USR_LED_GPIO_MAX 56 4 | # #define USR_LED_RED 66 5 | # #define USR_LED_GREEN 67 6 | # #define BAT25 27 7 | # #define BAT50 11 8 | # #define BAT75 61 9 | # #define BAT100 10000 // Placeholder until I find the real number 10 | # #define WIFI 10001 // Ditto 11 | # 12 | # which map to entries in pins_t table[] in source/common.c 13 | # 14 | # 66 15 | # BeagleBone (not Blue): { "TIMER4", "P8_7", 66, -1, -1}, 16 | # BeagleBone Blue: { "RED_LED", "RED", 66, -1, -1}, // LEDs 17 | # 18 | # 67 19 | # BeagleBone (not Blue): { "TIMER7", "P8_8", 67, -1, -1}, 20 | # BeagleBone Blue: { "GREEN_LED", "GREEN", 67, -1, -1}, 21 | # 22 | # 27 23 | # BeagleBone (not Blue): { "GPIO0_27", "P8_17", 27, -1, -1}, 24 | # BeagleBone Blue: { "BAT25", "BAT25", 27, -1, -1}, 25 | # PocketBeagle: { "GPIO0_27", "P2_19", 27, -1, -1}, 26 | # 27 | # 11 28 | # BeagleBone (not Blue): { "UART5_RTSN", "P8_32", 11, -1, -1}, 29 | # BeagleBone Blue: { "BAT50", "BAT50", 11, -1, -1}, 30 | # 31 | # 61 32 | # BeagleBone (not Blue): { "GPIO1_29", "P8_26", 61, -1, -1}, 33 | # BeagleBone Blue: { "BAT75", "BAT75", 61, -1, -1}, 34 | # 35 | 36 | import Adafruit_BBIO.GPIO as GPIO 37 | 38 | test_pins = [ 39 | "USR0", "USR1", "USR2", "USR3", 40 | "RED_LED", "GREEN_LED", "BAT25", "BAT50", "BAT75", 41 | "P8_7", "P8_8", "P8_17", "P8_32", "P8_26" 42 | ] 43 | 44 | for pin in test_pins: 45 | print("========================") 46 | print("test GPIO.setup(): {0}".format(pin)) 47 | GPIO.setup(pin, GPIO.OUT) 48 | print("test GPIO.output(): {0}".format(pin)) 49 | GPIO.output(pin, GPIO.HIGH) 50 | value = GPIO.input(pin); 51 | print("test GPIO.input(): {0}={1}".format(pin, value)); 52 | 53 | GPIO.cleanup() 54 | -------------------------------------------------------------------------------- /test/notes/rotary-encoder-eqep-test.md: -------------------------------------------------------------------------------- 1 | I have documented how-to to enable all the eqep pins: 2 | https://github.com/adafruit/adafruit-beaglebone-io-python/commit/c418cdae9a2a2c0d52412561c0125b0d227af4eb 3 | 4 | BeagleBone must boot with cape-universal enabled and load the `cape-universala` overlay in order to 5 | use all the eQEP pins: 6 | 7 | ### Install the latest Device Tree overlays: 8 | ``` 9 | sudo apt-get upgrade bb-cape-overlays 10 | ``` 11 | 12 | ### File: /boot/uEnv.txt 13 | ``` 14 | uname_r=4.4.62-ti-r99 15 | cmdline=coherent_pool=1M quiet cape_universal=enable 16 | cape_enable=bone_capemgr.enable_partno=cape-universala 17 | ``` 18 | 19 | ### File: /sys/devices/platform/bone_capemgr/slots 20 | ``` 21 | 0: PF---- -1 22 | 1: PF---- -1 23 | 2: PF---- -1 24 | 3: PF---- -1 25 | 4: P-O-L- 0 Override Board Name,00A0,Override Manuf,cape-universala 26 | ``` 27 | 28 | ### eqep0: P9_27, P9_92 29 | ``` 30 | config-pin P9_27 qep 31 | config-pin P9_92 qep # alias for P9_42.1 32 | cat /sys/devices/platform/ocp/48300000.epwmss/48300180.eqep/position 33 | ``` 34 | 35 | ### eqep1: P8.33, P8.35 36 | ``` 37 | config-pin P8.33 qep 38 | config-pin P8.35 qep 39 | cat /sys/devices/platform/ocp/48302000.epwmss/48302180.eqep/position 40 | ``` 41 | 42 | ### eqep2: P8.11, P8.12 43 | ``` 44 | config-pin P8.11 qep 45 | config-pin P8.12 qep 46 | cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position 47 | ``` 48 | 49 | ### eqep2b: P8.41, P8.42 50 | _alternate pins for eqep2 (mutually exclusive)_ 51 | ``` 52 | config-pin P8.41 qep 53 | config-pin P8.42 qep 54 | cat /sys/devices/platform/ocp/48304000.epwmss/48304180.eqep/position 55 | ``` 56 | 57 | ### TODO: implement in corresponding methods in `Encoder.py` 58 | 59 | 60 | ## Read QEP1 61 | * Updated: 2017-08-31 62 | * I was able to enable QEP1 with the following: 63 | 64 | #### /boot/uEnv.txt 65 | ``` 66 | uname_r=4.9.35-ti-r44 67 | enable_uboot_overlays=1 68 | disable_uboot_overlay_video=1 69 | cmdline=coherent_pool=1M net.ifnames=0 cape_universal=enable 70 | cape_enable=bone_capemgr.enable_partno=cape-universala 71 | ``` 72 | 73 | #### Read QEP1: 74 | ``` 75 | $ config-pin P8.33 qep 76 | $ config-pin P8.35 qep 77 | $ cat /sys/devices/platform/ocp/ocp\:P8_33_pinmux/state 78 | qep 79 | $ cat /sys/devices/platform/ocp/ocp\:P8_35_pinmux/state 80 | qep 81 | $ cat /sys/devices/platform/ocp/48302000.epwmss/48302180.eqep/position 82 | 0 83 | ``` 84 | 85 | #### Version info: 86 | ``` 87 | $ sudo /opt/scripts/tools/version.sh 88 | git:/opt/scripts/:[2ce750d881941c5189db9e189af90517e11c079f] 89 | eeprom:[A335BNLT000C3014BBBK1316] 90 | dogtag:[BeagleBoard.org Debian Image 2017-06-18] 91 | bootloader:[microSD-(push-button)]:[/dev/mmcblk0]:[U-Boot 92 | 2017.09-rc2-00002-g7c9353] 93 | bootloader:[eMMC-(default)]:[/dev/mmcblk1]:[U-Boot 2017.09-rc2-00002-g84a7f2] 94 | kernel:[4.9.35-ti-r44] 95 | nodejs:[v4.8.4] 96 | uboot_overlay_options:[enable_uboot_overlays=1] 97 | uboot_overlay_options:[disable_uboot_overlay_video=1] 98 | pkg:[bb-cape-overlays]:[4.4.20170728.0-0rcnee1~jessie+20170728] 99 | pkg:[bb-wl18xx-firmware]:[1.20170612-0rcnee0~jessie+20170612] 100 | WARNING:pkg:[firmware-ti-connectivity]:[NOT_INSTALLED] 101 | ``` 102 | -------------------------------------------------------------------------------- /test/notes/run_config-pin_during_startup.md: -------------------------------------------------------------------------------- 1 | ## Create file `/usr/bin/enable-i2c-pins.sh` 2 | **sudo vi /usr/bin/enable-i2c-pins.sh** 3 | ``` 4 | #!/bin/bash 5 | 6 | config-pin p9.17 i2c 7 | config-pin p9.18 i2c 8 | ``` 9 | **sudo chmod 755 /usr/bin/enable-i2c-pins.sh** 10 | 11 | ## Create file `/lib/systemd/system/enable-i2c-pins.service` 12 | **sudo vi /lib/systemd/system/enable-i2c-pins.service** 13 | ``` 14 | [Unit] 15 | Description=Enable I2C pins 16 | After=generic-board-startup.service 17 | 18 | [Service] 19 | Type=simple 20 | ExecStart=/usr/bin/enable-i2c-pins.sh 21 | 22 | [Install] 23 | WantedBy=multi-user.target 24 | ``` 25 | ## Enable the new systemd service 26 | **sudo systemctl daemon-reload** 27 | **sudo systemctl enable enable-i2c-pins.service** 28 | ``` 29 | Created symlink /etc/systemd/system/multi-user.target.wants/enable-i2c-pins.service → /lib/systemd/system/enable-i2c-pins.service. 30 | ``` 31 | 32 | ## Reboot and test 33 | **sudo systemctl status enable-i2c-pins.service** 34 | ``` 35 | debian@beaglebone:~$ sudo systemctl status enable-i2c-pins.service 36 | ● enable-i2c-pins.service - Enable I2C pins 37 | Loaded: loaded (/lib/systemd/system/enable-i2c-pins.service; enabled) 38 | Active: inactive (dead) since Wed 2017-04-19 06:35:06 UTC; 48s ago 39 | Process: 649 ExecStart=/usr/bin/enable-i2c-pins.sh (code=exited, status=0/SUCCESS) 40 | Main PID: 649 (code=exited, status=0/SUCCESS) 41 | 42 | Apr 19 06:35:05 beaglebone sudo[664]: root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/bin/bash -c echo i2c > /sys/devices/platform/ocp/ocp:P9_17_pinmux/state 43 | Apr 19 06:35:05 beaglebone sudo[664]: pam_unix(sudo:session): session opened for user root by (uid=0) 44 | Apr 19 06:35:05 beaglebone sudo[664]: pam_unix(sudo:session): session closed for user root 45 | Apr 19 06:35:06 beaglebone sudo[677]: root : TTY=unknown ; PWD=/ ; USER=root ; COMMAND=/bin/bash -c echo i2c > /sys/devices/platform/ocp/ocp:P9_18_pinmux/state 46 | Apr 19 06:35:06 beaglebone sudo[677]: pam_unix(sudo:session): session opened for user root by (uid=0) 47 | Apr 19 06:35:06 beaglebone sudo[677]: pam_unix(sudo:session): session closed for user root 48 | ``` 49 | 50 | **config-pin -q p9.17 && config-pin -q p9.18** 51 | ``` 52 | debian@beaglebone:~$ config-pin -q p9.17 && config-pin -q p9.18 53 | P9_17 Mode: i2c 54 | P9_18 Mode: i2c 55 | ``` 56 | -------------------------------------------------------------------------------- /test/notes/spi_loopback_test.md: -------------------------------------------------------------------------------- 1 | # Adafruit_BBIO SPI test 2 | 3 | ## Loopback test with SPI0 4 | * Connect wire from P9_18 [SPI0_D1] and P9_21 [SPI0_D0] 5 | * Reference: [P9 header pins](http://beagleboard.org/static/images/cape-headers-spi.png) 6 | 7 | ## System Info 8 | ### uname -r 9 | `4.4.39-ti-r79` 10 | ### /etc/debian_version 11 | `8.6` 12 | ### /etc/dogtag 13 | `BeagleBoard.org Debian Image 2016-11-27` 14 | ### /boot/uEnv.txt 15 | ``` 16 | uname_r=4.4.39-ti-r79 17 | cmdline=coherent_pool=1M quiet cape_universal=enable 18 | ``` 19 | ### /sys/devices/platform/bone_capemgr/slots 20 | ``` 21 | 0: PF---- -1 22 | 1: PF---- -1 23 | 2: PF---- -1 24 | 3: PF---- -1 25 | 4: P-O-L- 0 Override Board Name,00A0,Override Manuf,cape-universaln 26 | ``` 27 | 28 | ### config-pin 29 | ``` 30 | config-pin P9_17 spi 31 | config-pin P9_18 spi 32 | config-pin P9_21 spi 33 | config-pin P9_22 spi 34 | ``` 35 | 36 | ## test-spi.py 37 | ``` 38 | from Adafruit_BBIO.SPI import SPI 39 | 40 | # From Adafruit Learning System: 41 | # https://learn.adafruit.com/setting-up-io-python-library-on-beaglebone-black/spi 42 | #spi = SPI(bus, device) #/dev/spidev. 43 | #spi = SPI(0,0) #/dev/spidev1.0 44 | #spi = SPI(0,1) #/dev/spidev1.1 45 | #spi = SPI(1,0) #/dev/spidev2.0 46 | #spi = SPI(1,1) #/dev/spidev2.1 47 | 48 | spi = SPI(0,0) 49 | print(spi.xfer2([32, 11, 110, 22, 220])) 50 | spi.close() 51 | ``` 52 | 53 | ### output 54 | ``` 55 | debian@beaglebone:~/spi$ sudo python test-spi.py 56 | [32, 11, 110, 22, 220] 57 | ``` 58 | 59 | ### strace 60 | ``` 61 | debian@beaglebone:~/spi$ sudo strace -e open -f python ./test-spi.py 2>&1 |grep /dev/spidev 62 | open("/dev/spidev1.0", O_RDWR|O_LARGEFILE) = 3 63 | ``` 64 | -------------------------------------------------------------------------------- /test/notes/test_read_write_all_gpio_pins.md: -------------------------------------------------------------------------------- 1 | This Python program will open, read and write to all the GPIO pins and the USR LEDs: 2 | ``` 3 | import Adafruit_BBIO.GPIO as GPIO 4 | import time 5 | 6 | for i in range(4): 7 | GPIO.setup("USR%d" % i, GPIO.OUT) 8 | GPIO.output("USR%d" % i, GPIO.HIGH) 9 | GPIO.output("USR%d" % i, GPIO.LOW) 10 | 11 | for i in [3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46]: 12 | GPIO.setup("P8_%d" % i, GPIO.OUT) 13 | GPIO.output("P8_%d" % i, GPIO.HIGH) 14 | GPIO.output("P8_%d" % i, GPIO.LOW) 15 | 16 | for i in [11,12,13,14,15,16,17,18,21,22,23,24,25,26,27,28,29,30,31,41,42]: 17 | GPIO.setup("P9_%d" % i, GPIO.OUT) 18 | GPIO.output("P9_%d" % i, GPIO.HIGH) 19 | GPIO.output("P9_%d" % i, GPIO.LOW) 20 | ``` 21 | 22 | This can be useful when run with strace to verify that the library is operating as expected: 23 | ``` 24 | sudo strace -e file python ~/gpio_output_test.py 2>&1 |grep '/sys/'|less 25 | ``` 26 | 27 | refer to this gist for more info: 28 | https://gist.github.com/pdp7/e7753faff9a9bd27389a0173c71f9312 29 | -------------------------------------------------------------------------------- /test/setup/0001-rename-USR-LED-names-to-test-Adafruit_BBIO-issue-129.patch: -------------------------------------------------------------------------------- 1 | From 88366a61455cbe3e42ab59da939065abeab81597 Mon Sep 17 00:00:00 2001 2 | From: Drew Fustini 3 | Date: Thu, 5 Jan 2017 02:33:58 -0600 4 | Subject: [PATCH] rename USR LED names to test Adafruit_BBIO issue #129 5 | 6 | Patch for ti-linux-4.4.y branch of ti-linux-kernel-dev which renames 7 | the labels of the USR LED nodes 8 | 9 | Related issue: 10 | Doesn't support Ubuntu core beaglebone leds #129 11 | https://github.com/adafruit/adafruit-beaglebone-io-python/issues/129 12 | --- 13 | arch/arm/boot/dts/am335x-bone-common.dtsi | 8 ++++---- 14 | 1 file changed, 4 insertions(+), 4 deletions(-) 15 | 16 | diff --git a/arch/arm/boot/dts/am335x-bone-common.dtsi b/arch/arm/boot/dts/am335x-bone-common.dtsi 17 | index 1f496145..ba95ffc 100644 18 | --- a/arch/arm/boot/dts/am335x-bone-common.dtsi 19 | +++ b/arch/arm/boot/dts/am335x-bone-common.dtsi 20 | @@ -26,28 +26,28 @@ 21 | compatible = "gpio-leds"; 22 | 23 | led@2 { 24 | - label = "beaglebone:green:usr0"; 25 | + label = "beaglebone:green:heartbeat"; 26 | gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>; 27 | linux,default-trigger = "heartbeat"; 28 | default-state = "off"; 29 | }; 30 | 31 | led@3 { 32 | - label = "beaglebone:green:usr1"; 33 | + label = "beaglebone:green:mmc0"; 34 | gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; 35 | linux,default-trigger = "mmc0"; 36 | default-state = "off"; 37 | }; 38 | 39 | led@4 { 40 | - label = "beaglebone:green:usr2"; 41 | + label = "beaglebone:green:cpu0"; 42 | gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; 43 | linux,default-trigger = "cpu0"; 44 | default-state = "off"; 45 | }; 46 | 47 | led@5 { 48 | - label = "beaglebone:green:usr3"; 49 | + label = "beaglebone:green:mmc1"; 50 | gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; 51 | linux,default-trigger = "mmc1"; 52 | default-state = "off"; 53 | -- 54 | 2.9.3 55 | -------------------------------------------------------------------------------- /test/start_all_pwm.py: -------------------------------------------------------------------------------- 1 | import Adafruit_BBIO.PWM as PWM 2 | 3 | pins = [ 4 | "P9_16", #PWM1B 5 | "P9_21", #PWM0B 6 | "P9_22", #PWM0A 7 | "P9_28", #ECAP2 8 | "P9_29", #PWM0B 9 | "P9_31", #PWM0A 10 | "P9_42", #ECAP0 11 | "P8_13", #PWM2B 12 | "P8_19", #PWM2A 13 | "P8_34", #PWM1B 14 | "P8_36", #PWM1A 15 | "P8_45", #PWM2A 16 | "P8_46" #PWM2B 17 | ] 18 | 19 | # /sys/devices/platform/ocp/48300000.epwmss/48300100.ecap/pwm/pwmchip0/pwm-0:0/duty_cycle 20 | # /sys/devices/platform/ocp/48304000.epwmss/48304100.ecap/pwm/pwmchip5/pwm-5:0/duty_cycle 21 | 22 | for pin in pins: 23 | print(pin) 24 | PWM.start(pin, 50, 2000, 1) 25 | PWM.stop(pin) 26 | PWM.cleanup() 27 | 28 | -------------------------------------------------------------------------------- /test/test_adc.py: -------------------------------------------------------------------------------- 1 | #debian@beaglebone:~/adafruit-beaglebone-io-python/test$ cat test_adc.py 2 | import pytest 3 | import os 4 | import platform 5 | import Adafruit_BBIO.ADC as ADC 6 | 7 | 8 | def teardown_module(module): 9 | pass 10 | #ADC.cleanup() 11 | 12 | class TestAdc: 13 | def test_read_adc_no_setup(self): 14 | with pytest.raises(RuntimeError): 15 | ADC.read("P9_40") 16 | 17 | def test_read_raw_adc_no_setup(self): 18 | with pytest.raises(RuntimeError): 19 | ADC.read_raw("P9_40") 20 | 21 | def test_setup_adc(self): 22 | 23 | ADC.setup() 24 | 25 | kernel = platform.release() 26 | if kernel >= '4.1.0': 27 | test_path = "/sys/bus/iio/devices/iio:device0/in_voltage1_raw" 28 | else: 29 | files = os.listdir('/sys/devices') 30 | ocp = '/sys/devices/'+[s for s in files if s.startswith('ocp')][0] 31 | files = os.listdir(ocp) 32 | helper_path = ocp+'/'+[s for s in files if s.startswith('helper')][0] 33 | test_path = helper_path + "/AIN1" 34 | 35 | assert os.path.exists(test_path); 36 | #ADC.cleanup() 37 | 38 | def test_read_adc(self): 39 | ADC.setup() 40 | value = -1 41 | value = ADC.read("P9_40") 42 | 43 | assert value != -1 44 | 45 | def test_read_raw_adc(self): 46 | ADC.setup() 47 | value = -1 48 | value = ADC.read_raw("P9_40") 49 | 50 | assert value != -1 51 | 52 | def test_many_read_adc(self): 53 | import time 54 | 55 | ADC.setup() 56 | 57 | for x in range(0,1000): 58 | start = time.time() 59 | value = -1 60 | value = ADC.read("AIN1") 61 | assert value != -1 62 | -------------------------------------------------------------------------------- /test/test_gpio_input.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import os 3 | 4 | import Adafruit_BBIO.GPIO as GPIO 5 | 6 | def teardown_module(module): 7 | GPIO.cleanup() 8 | 9 | class TestGPIOInput: 10 | def test_input(self): 11 | GPIO.setup("P8_10", GPIO.IN) 12 | #returned as an int type 13 | input_value = GPIO.input("P8_10") 14 | #value read from the file will have a \n new line 15 | value = open('/sys/class/gpio/gpio68/value').read() 16 | assert int(value) == input_value 17 | GPIO.cleanup() 18 | 19 | def test_direction_readback(self): 20 | GPIO.setup("P8_10", GPIO.IN) 21 | direction = GPIO.gpio_function("P8_10") 22 | assert direction == GPIO.IN 23 | -------------------------------------------------------------------------------- /test/test_gpio_output.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import os 3 | 4 | import Adafruit_BBIO.GPIO as GPIO 5 | 6 | def teardown_module(module): 7 | GPIO.cleanup() 8 | 9 | class TestGPIOOutput: 10 | def test_output_high(self): 11 | GPIO.setup("P8_10", GPIO.OUT) 12 | GPIO.output("P8_10", GPIO.HIGH) 13 | value = open('/sys/class/gpio/gpio68/value').read() 14 | assert int(value) 15 | GPIO.cleanup() 16 | 17 | def test_output_low(self): 18 | GPIO.setup("P8_10", GPIO.OUT) 19 | GPIO.output("P8_10", GPIO.LOW) 20 | value = open('/sys/class/gpio/gpio68/value').read() 21 | assert not int(value) 22 | GPIO.cleanup() 23 | 24 | def test_direction_readback(self): 25 | GPIO.setup("P8_10", GPIO.OUT) 26 | direction = GPIO.gpio_function("P8_10") 27 | assert direction == GPIO.OUT 28 | def test_output_greater_than_one(self): 29 | GPIO.setup("P8_10", GPIO.OUT) 30 | GPIO.output("P8_10", 2) 31 | value = open('/sys/class/gpio/gpio68/value').read() 32 | assert int(value) 33 | GPIO.cleanup() 34 | 35 | def test_output_of_pin_not_setup(self): 36 | with pytest.raises(RuntimeError): 37 | GPIO.output("P8_11", GPIO.LOW) 38 | GPIO.cleanup() 39 | 40 | def test_output_setup_as_input(self): 41 | GPIO.setup("P8_10", GPIO.IN) 42 | with pytest.raises(RuntimeError): 43 | GPIO.output("P8_10", GPIO.LOW) 44 | GPIO.cleanup() 45 | -------------------------------------------------------------------------------- /test/test_gpio_setup.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import os 3 | import platform 4 | 5 | import Adafruit_BBIO.GPIO as GPIO 6 | 7 | kernel = platform.release() 8 | 9 | 10 | def teardown_module(module): 11 | GPIO.cleanup() 12 | 13 | 14 | class TestSetup: 15 | def test_setup_output_key(self): 16 | GPIO.setup("P8_10", GPIO.OUT) 17 | assert os.path.exists('/sys/class/gpio/gpio68') 18 | direction = open('/sys/class/gpio/gpio68/direction').read() 19 | assert direction == 'out\n' 20 | GPIO.cleanup() 21 | 22 | def test_setup_output_name(self): 23 | # WARNING: TIMERn syntax is not working on newer kernels 24 | # such as 4.4. Originally discovered while testing 25 | # Pull Request #152. See issue #156 for details. 26 | #GPIO.setup("TIMER6", GPIO.OUT) 27 | GPIO.setup("P8_10", GPIO.OUT) 28 | assert os.path.exists('/sys/class/gpio/gpio68') 29 | direction = open('/sys/class/gpio/gpio68/direction').read() 30 | assert direction == 'out\n' 31 | GPIO.cleanup() 32 | 33 | def test_setup_input_key(self): 34 | GPIO.setup("P8_10", GPIO.IN) 35 | assert os.path.exists('/sys/class/gpio/gpio68') 36 | direction = open('/sys/class/gpio/gpio68/direction').read() 37 | assert direction == 'in\n' 38 | GPIO.cleanup() 39 | 40 | def test_setup_input_name(self): 41 | # WARNING: TIMERn syntax is not working on newer kernels 42 | # such as 4.4. Originally discovered while testing 43 | # Pull Request #152. See issue #156 for details. 44 | #GPIO.setup("TIMER6", GPIO.IN) 45 | GPIO.setup("P8_10", GPIO.IN) 46 | assert os.path.exists('/sys/class/gpio/gpio68') 47 | direction = open('/sys/class/gpio/gpio68/direction').read() 48 | assert direction == 'in\n' 49 | GPIO.cleanup() 50 | 51 | def test_setup_input_pull_up(self): 52 | GPIO.setup("P8_10", GPIO.IN, pull_up_down=GPIO.PUD_UP) 53 | assert os.path.exists('/sys/class/gpio/gpio68') 54 | direction = open('/sys/class/gpio/gpio68/direction').read() 55 | assert direction == 'in\n' 56 | GPIO.cleanup() 57 | 58 | def test_setup_input_pull_down(self): 59 | GPIO.setup("P8_10", GPIO.IN, pull_up_down=GPIO.PUD_DOWN) 60 | assert os.path.exists('/sys/class/gpio/gpio68') 61 | direction = open('/sys/class/gpio/gpio68/direction').read() 62 | assert direction == 'in\n' 63 | GPIO.cleanup() 64 | 65 | def test_setup_cleanup(self): 66 | GPIO.setup("P8_10", GPIO.OUT) 67 | assert os.path.exists('/sys/class/gpio/gpio68') 68 | GPIO.cleanup() 69 | if kernel < '4.1.0': 70 | assert not os.path.exists('/sys/class/gpio/gpio68') 71 | # for later kernels, the universal capemanager always loads the 72 | # UARTs. 73 | 74 | def test_setup_failed_type_error(self): 75 | with pytest.raises(TypeError): 76 | GPIO.setup("P8_10", "WEIRD") 77 | GPIO.cleanup() 78 | 79 | def test_setup_failed_value_error(self): 80 | with pytest.raises(ValueError): 81 | GPIO.setup("P8_10", 3) 82 | GPIO.cleanup() 83 | 84 | def test_setup_three_digit_gpio(self): 85 | GPIO.setup("P9_31", GPIO.OUT) 86 | assert os.path.exists('/sys/class/gpio/gpio110') 87 | GPIO.cleanup() 88 | if kernel < '4.1.0': 89 | assert not os.path.exists('/sys/class/gpio/gpio110') 90 | # for later kernels, the universal capemanager always loads the 91 | # UARTs. 92 | -------------------------------------------------------------------------------- /test/test_led.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import os 3 | import errno 4 | 5 | import Adafruit_BBIO.GPIO as GPIO 6 | 7 | def teardown_module(module): 8 | GPIO.cleanup() 9 | 10 | class TestLED: 11 | def set_brightness(self, state, led, name): 12 | GPIO.setup(led, GPIO.OUT) 13 | GPIO.output(led, state) 14 | prefix = "/sys/class/leds/beaglebone:green:{0}/brightness" 15 | path = prefix.format(led.lower()) 16 | value = self.read_led_file(path) 17 | if value == "": 18 | path = prefix.format(name) 19 | value = self.read_led_file(path) 20 | if state == 1: 21 | assert int(value) > 0 22 | else: 23 | assert int(value) == 0 24 | 25 | def read_led_file(self, path): 26 | try: 27 | return open(path).read() 28 | except (IOError, e): 29 | if e.errno == errno.ENOENT: 30 | return "" 31 | 32 | def set_all_leds(self, state): 33 | test_leds = { "USR0": "heartbeat", \ 34 | "USR1": "mmc0", \ 35 | "USR2": "cpu0", \ 36 | "USR3": "mmc1" } 37 | for led, name in test_leds.items(): 38 | self.set_brightness(state, led, name) 39 | GPIO.cleanup() 40 | 41 | def test_brightness_high(self): 42 | self.set_all_leds(GPIO.HIGH) 43 | 44 | def test_brightness_low(self): 45 | self.set_all_leds(GPIO.LOW) 46 | 47 | 48 | -------------------------------------------------------------------------------- /test/test_pwm_setup.py: -------------------------------------------------------------------------------- 1 | import glob 2 | import os 3 | import platform 4 | 5 | import Adafruit_BBIO.PWM as PWM 6 | import pytest 7 | 8 | kernel = platform.release() 9 | 10 | 11 | def teardown_module(module): 12 | PWM.cleanup() 13 | 14 | 15 | def get_pwm_dir(): 16 | if kernel >= '4.1.0': 17 | # On 4.1+, the pwm subdirectory sometimes takes different names: 18 | # .pwm or .ehrpwm, etc. 19 | results = glob.glob( 20 | "/sys/devices/platform/ocp/48302000.*/" + 21 | "48302200.*/pwm/pwmchip?/pwm*") 22 | # We expect that there will be a result (a directory fitting 23 | # our path exists) so test that with an assertion. 24 | assert len(results) > 0 25 | # Continue with the pwm_dir found 26 | return results[0] 27 | else: 28 | files = os.listdir('/sys/devices') 29 | ocp = '/sys/devices/' + [s for s in files if s.startswith('ocp')][0] 30 | files = os.listdir(ocp) 31 | return ocp + '/' + [s for s in files if s.startswith('pwm_test_P9_14')][0] 32 | 33 | 34 | class TestPwmSetup: 35 | def test_start_pwm(self): 36 | PWM.cleanup() 37 | PWM.start("P9_14", 0) 38 | 39 | pwm_dir = get_pwm_dir() 40 | 41 | assert os.path.exists(pwm_dir) 42 | if kernel >= '4.1.0': 43 | duty = open(pwm_dir + '/duty_cycle').read() 44 | else: 45 | duty = open(pwm_dir + '/duty').read() 46 | period = open(pwm_dir + '/period').read() 47 | assert int(duty) == 0 48 | assert int(period) == 500000 49 | PWM.cleanup() 50 | 51 | def test_start_pwm_ecap0(self): 52 | print("test_start_pwm_ecap0\n"); 53 | PWM.cleanup() 54 | PWM.start("P9_42", 0) 55 | pwm_dir = get_pwm_dir() 56 | assert os.path.exists(pwm_dir) 57 | if kernel >= '4.1.0': 58 | duty = open(pwm_dir + '/duty_cycle').read() 59 | else: 60 | duty = open(pwm_dir + '/duty').read() 61 | period = open(pwm_dir + '/period').read() 62 | assert int(duty) == 0 63 | assert int(period) == 500000 64 | PWM.cleanup() 65 | 66 | # test not enabled as default as 67 | # cape-universala overlay required 68 | #def test_start_pwm_ecap2(self): 69 | #print("test_start_pwm_ecap2\n"); 70 | #PWM.cleanup() 71 | #PWM.start("P9_28", 0) 72 | #pwm_dir = get_pwm_dir() 73 | #assert os.path.exists(pwm_dir) 74 | #if kernel >= '4.1.0': 75 | #duty = open(pwm_dir + '/duty_cycle').read() 76 | #else: 77 | #duty = open(pwm_dir + '/duty').read() 78 | #period = open(pwm_dir + '/period').read() 79 | #assert int(duty) == 0 80 | #assert int(period) == 500000 81 | #PWM.cleanup() 82 | 83 | def test_start_pwm_with_polarity_one(self): 84 | PWM.cleanup() 85 | PWM.start("P9_14", 0, 2000, 1) 86 | 87 | pwm_dir = get_pwm_dir() 88 | 89 | assert os.path.exists(pwm_dir) 90 | if kernel >= '4.1.0': 91 | duty = open(pwm_dir + '/duty_cycle').read() 92 | else: 93 | duty = open(pwm_dir + '/duty').read() 94 | period = open(pwm_dir + '/period').read() 95 | polarity = open(pwm_dir + '/polarity').read() 96 | assert int(duty) == 0 97 | assert int(period) == 500000 98 | 99 | # TEMPORARY FIX: disable polarity check 100 | # due to issue in 4.9.x+ kernels 101 | # refer to issue #170: 102 | # https://github.com/adafruit/adafruit-beaglebone-io-python/issues/170 103 | # and commit c35e4cb from pull request #173: 104 | # "source/c_pwm.c: disable pwm_set_polarity (broken in v4.9.x/v4.14.x)" 105 | # https://github.com/adafruit/adafruit-beaglebone-io-python/pull/173/commits/c35e4cb98a1f14c85aca7259132bcc97e93d78f8 106 | #if kernel >= '4.1.0': 107 | # assert polarity == "inversed\n" 108 | #else: 109 | # assert int(polarity) == 1 110 | PWM.cleanup() 111 | 112 | def test_start_pwm_with_polarity_default(self): 113 | PWM.cleanup() 114 | PWM.start("P9_14", 0, 2000) 115 | 116 | pwm_dir = get_pwm_dir() 117 | 118 | assert os.path.exists(pwm_dir) 119 | if kernel >= '4.1.0': 120 | duty = open(pwm_dir + '/duty_cycle').read() 121 | else: 122 | duty = open(pwm_dir + '/duty').read() 123 | period = open(pwm_dir + '/period').read() 124 | polarity = open(pwm_dir + '/polarity').read() 125 | assert int(duty) == 0 126 | assert int(period) == 500000 127 | 128 | # TEMPORARY FIX: disable polarity check 129 | # due to issue in 4.9.x+ kernels 130 | # refer to issue #170: 131 | # https://github.com/adafruit/adafruit-beaglebone-io-python/issues/170 132 | # and commit c35e4cb from pull request #173: 133 | # "source/c_pwm.c: disable pwm_set_polarity (broken in v4.9.x/v4.14.x)" 134 | # https://github.com/adafruit/adafruit-beaglebone-io-python/pull/173/commits/c35e4cb98a1f14c85aca7259132bcc97e93d78f8 135 | #if kernel >= '4.1.0': 136 | # assert polarity == 'normal\n' 137 | #else: 138 | # assert int(polarity) == 0 139 | PWM.cleanup() 140 | 141 | def test_start_pwm_with_polarity_zero(self): 142 | PWM.cleanup() 143 | PWM.start("P9_14", 0, 2000, 0) 144 | 145 | pwm_dir = get_pwm_dir() 146 | 147 | assert os.path.exists(pwm_dir) 148 | if kernel >= '4.1.0': 149 | duty = open(pwm_dir + '/duty_cycle').read() 150 | else: 151 | duty = open(pwm_dir + '/duty').read() 152 | period = open(pwm_dir + '/period').read() 153 | polarity = open(pwm_dir + '/polarity').read() 154 | assert int(duty) == 0 155 | assert int(period) == 500000 156 | 157 | if kernel >= '4.1.0': 158 | assert polarity == 'normal\n' 159 | else: 160 | assert int(polarity) == 0 161 | PWM.cleanup() 162 | 163 | def test_pwm_start_invalid_pwm_key(self): 164 | PWM.cleanup() 165 | with pytest.raises(ValueError): 166 | PWM.start("P8_25", -1) 167 | 168 | def test_pwm_start_invalid_duty_cycle_negative(self): 169 | PWM.cleanup() 170 | with pytest.raises(ValueError): 171 | PWM.start("P9_14", -1) 172 | 173 | def test_pwm_start_valid_duty_cycle_min(self): 174 | PWM.cleanup() 175 | # testing an exception isn't thrown 176 | PWM.start("P9_14", 0) 177 | PWM.cleanup() 178 | 179 | def test_pwm_start_valid_duty_cycle_max(self): 180 | PWM.cleanup() 181 | # testing an exception isn't thrown 182 | PWM.start("P9_14", 100) 183 | PWM.cleanup() 184 | 185 | def test_pwm_start_invalid_duty_cycle_high(self): 186 | PWM.cleanup() 187 | with pytest.raises(ValueError): 188 | PWM.start("P9_14", 101) 189 | 190 | def test_pwm_start_invalid_duty_cycle_string(self): 191 | PWM.cleanup() 192 | with pytest.raises(TypeError): 193 | PWM.start("P9_14", "1") 194 | 195 | def test_pwm_start_invalid_frequency_negative(self): 196 | PWM.cleanup() 197 | with pytest.raises(ValueError): 198 | PWM.start("P9_14", 0, -1) 199 | 200 | def test_pwm_start_invalid_frequency_string(self): 201 | PWM.cleanup() 202 | with pytest.raises(TypeError): 203 | PWM.start("P9_14", 0, "1") 204 | 205 | def test_pwm_start_negative_polarity(self): 206 | PWM.cleanup() 207 | with pytest.raises(ValueError): 208 | PWM.start("P9_14", 0, 100, -1) 209 | 210 | def test_pwm_start_invalid_positive_polarity(self): 211 | PWM.cleanup() 212 | with pytest.raises(ValueError): 213 | PWM.start("P9_14", 0, 100, 2) 214 | 215 | def test_pwm_start_invalid_polarity_type(self): 216 | PWM.cleanup() 217 | with pytest.raises(TypeError): 218 | PWM.start("P9_14", 0, 100, "1") 219 | 220 | def test_pwm_duty_modified(self): 221 | PWM.cleanup() 222 | PWM.start("P9_14", 0) 223 | 224 | pwm_dir = get_pwm_dir() 225 | 226 | assert os.path.exists(pwm_dir) 227 | if kernel >= '4.1.0': 228 | duty = open(pwm_dir + '/duty_cycle').read() 229 | else: 230 | duty = open(pwm_dir + '/duty').read() 231 | period = open(pwm_dir + '/period').read() 232 | assert int(duty) == 0 233 | assert int(period) == 500000 234 | 235 | PWM.set_duty_cycle("P9_14", 100) 236 | if kernel >= '4.1.0': 237 | duty = open(pwm_dir + '/duty_cycle').read() 238 | else: 239 | duty = open(pwm_dir + '/duty').read() 240 | period = open(pwm_dir + '/period').read() 241 | assert int(duty) == 500000 242 | assert int(period) == 500000 243 | PWM.cleanup() 244 | 245 | def test_pwm_duty_cycle_non_setup_key(self): 246 | PWM.cleanup() 247 | with pytest.raises(RuntimeError): 248 | PWM.set_duty_cycle("P9_14", 100) 249 | PWM.cleanup() 250 | 251 | def test_pwm_duty_cycle_invalid_key(self): 252 | PWM.cleanup() 253 | with pytest.raises(ValueError): 254 | PWM.set_duty_cycle("P9_15", 100) 255 | PWM.cleanup() 256 | 257 | def test_pwm_duty_cycle_invalid_value_high(self): 258 | PWM.cleanup() 259 | PWM.start("P9_14", 0) 260 | with pytest.raises(ValueError): 261 | PWM.set_duty_cycle("P9_14", 101) 262 | PWM.cleanup() 263 | 264 | def test_pwm_duty_cycle_invalid_value_negative(self): 265 | PWM.cleanup() 266 | PWM.start("P9_14", 0) 267 | with pytest.raises(ValueError): 268 | PWM.set_duty_cycle("P9_14", -1) 269 | PWM.cleanup() 270 | 271 | def test_pwm_duty_cycle_invalid_value_string(self): 272 | PWM.cleanup() 273 | PWM.start("P9_14", 0) 274 | with pytest.raises(TypeError): 275 | PWM.set_duty_cycle("P9_14", "a") 276 | PWM.cleanup() 277 | 278 | def test_pwm_frequency_invalid_value_negative(self): 279 | PWM.cleanup() 280 | PWM.start("P9_14", 0) 281 | with pytest.raises(ValueError): 282 | PWM.set_frequency("P9_14", -1) 283 | PWM.cleanup() 284 | 285 | def test_pwm_frequency_invalid_value_string(self): 286 | PWM.cleanup() 287 | PWM.start("P9_14", 0) 288 | with pytest.raises(TypeError): 289 | PWM.set_frequency("P9_14", "11") 290 | PWM.cleanup() 291 | 292 | def test_pwm_freq_non_setup_key(self): 293 | PWM.cleanup() 294 | with pytest.raises(RuntimeError): 295 | PWM.set_frequency("P9_14", 100) 296 | PWM.cleanup() 297 | 298 | def test_pwm_freq_non_setup_invalid_key(self): 299 | PWM.cleanup() 300 | with pytest.raises(ValueError): 301 | PWM.set_frequency("P9_15", 100) 302 | PWM.cleanup() 303 | 304 | def test_stop_pwm(self): 305 | pass 306 | # PWM.start("P9_14", 1) 307 | # PWM.stop("P9_14") 308 | # assert os.path.exists('/sys/class/gpio/gpio68') 309 | # direction = open('/sys/class/gpio/gpio68/direction').read() 310 | # assert direction == 'out\n' 311 | # PWM.cleanup() 312 | -------------------------------------------------------------------------------- /test/test_spi.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import os 3 | 4 | from Adafruit_BBIO.SPI import SPI 5 | 6 | def teardown_module(module): 7 | pass 8 | 9 | class TestAdc: 10 | def test_spi(self): 11 | SPI(1,1) 12 | 13 | def test_setup_spi_wrong_values(self): 14 | with pytest.raises(TypeError): 15 | SPI('x', 'x') -------------------------------------------------------------------------------- /test/test_uart.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | import serial 3 | import platform 4 | 5 | import Adafruit_BBIO.UART as UART 6 | 7 | kernel = platform.release() 8 | 9 | 10 | def teardown_module(module): 11 | pass 12 | # ADC.cleanup() 13 | 14 | 15 | class TestUart: 16 | def test_setup_uart_wrong_name(self): 17 | if kernel >= '4.1.0': 18 | pass 19 | else: 20 | with pytest.raises(ValueError): 21 | UART.setup("UART7") 22 | 23 | def test_setup_adc(self): 24 | if kernel >= '4.1.0': 25 | pass 26 | else: 27 | UART.setup("UART1") 28 | 29 | def test_setup_uart_multiple(self): 30 | if kernel >= '4.1.0': 31 | pass 32 | else: 33 | UART.setup("UART1") 34 | UART.setup("UART1") 35 | 36 | # test UART entries for the PocketBeagle (issue #243) 37 | def test_pocketbeagle(self): 38 | if kernel < '4.1.0': 39 | pass 40 | value = open('/proc/device-tree/model').read() 41 | if(value.startswith("TI AM335x PocketBeagle")): 42 | uarts = { 43 | 'PB-UART0': '/dev/ttyO0', 44 | 'PB-UART1': '/dev/ttyO1', 45 | 'PB-UART2': '/dev/ttyO2', 46 | } 47 | else: 48 | uarts = { 49 | 'UART1': '/dev/ttyO1', 50 | 'UART2': '/dev/ttyO2', 51 | 'UART4': '/dev/ttyO4' 52 | # note: UART5 requires 53 | # "disable_uboot_overlay_video=1" in /boot/uEnv.txt 54 | #'UART5': '/dev/ttyO5' 55 | } 56 | 57 | for name, device in sorted(uarts.items()): 58 | UART.setup(name) 59 | uart = serial.Serial(port = device, baudrate=9600) 60 | uart.close() 61 | uart.open() 62 | if uart.isOpen(): 63 | uart.write("hello world".encode("utf-8")) 64 | uart.close() 65 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # Tox (http://tox.testrun.org/) is a tool for running tests 2 | # in multiple virtualenvs. This configuration file will run the 3 | # test suite on all supported python versions. To use it, "pip install tox" 4 | # and then run "tox" from this directory. 5 | 6 | [tox] 7 | envlist = py27, py36 8 | 9 | [testenv] 10 | commands = echo "run pytest on beaglebone" 11 | deps = 12 | whitelist_externals = echo 13 | -------------------------------------------------------------------------------- /udev/80-non-root-gpio-permissions.rules: -------------------------------------------------------------------------------- 1 | KERNEL=="gpio*", SUBSYSTEM=="gpio", ACTION=="add", PROGRAM="/usr/local/bin/udev-non-root-gpio-permissions.sh" 2 | -------------------------------------------------------------------------------- /udev/udev-non-root-gpio-permissions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Result: chown debian:debian /sys/class/gpio 4 | 5 | chown -R debian:debian /sys/devices/gpio 6 | chown -R debian:debian /sys/class/gpio 7 | chown -R debian:debian /sys/devices/platform/ocp 8 | chown -R debian:debian /sys/class/pwm 9 | 10 | #GPIO ( active_low device direction edge power subsystem uevent value ) 11 | find /sys/class/gpio -type d -exec chmod 2770 {} \; 12 | find /sys/class/gpio -name "direction" -exec chmod 0660 {} \; 13 | find /sys/class/gpio -name "edge" -exec chmod 0660 {} \; 14 | find /sys/class/gpio -name "value" -exec chmod 0660 {} \; 15 | find /sys/class/gpio -name "active_low" -exec chmod 0660 {} \; 16 | find /sys/class/gpio -name "device" -exec chmod 0660 {} \; 17 | find /sys/class/gpio -name "power" -exec chmod 0660 {} \; 18 | find /sys/class/gpio -name "subsystem" -exec chmod 0660 {} \; 19 | 20 | #PWM ( duty_cycle enable period polarity power uevent ) 21 | find /sys/devices/platform/ocp -name "duty_cycle" -exec chmod 0660 {} \; 22 | find /sys/devices/platform/ocp -name "enable" -exec chmod 0660 {} \; 23 | find /sys/devices/platform/ocp -name "period" -exec chmod 0660 {} \; 24 | find /sys/devices/platform/ocp -name "polarity" -exec chmod 0660 {} \; 25 | find /sys/devices/platform/ocp -name "power" -exec chmod 0660 {} \; 26 | find /sys/class/pwm -name "duty_cycle" -exec chmod 0660 {} \; 27 | find /sys/class/pwm -name "enable" -exec chmod 0660 {} \; 28 | find /sys/class/pwm -name "period" -exec chmod 0660 {} \; 29 | find /sys/class/pwm -name "polarity" -exec chmod 0660 {} \; 30 | find /sys/class/pwm -name "power" -exec chmod 0660 {} \; 31 | 32 | chmod 0220 /sys/class/gpio/export 33 | chmod 0220 /sys/class/gpio/unexport 34 | chmod 0220 /sys/class/pwm/export 35 | chmod 0220 /sys/class/pwm/unexport 36 | 37 | find /sys/class/gpio -name "uevent" -exec chmod 0660 {} \; 38 | find /sys/class/gpio -name "autosuspend_delay_ms" -exec chmod 0660 {} \; 39 | find /sys/class/gpio -name "control" -exec chmod 0660 {} \; 40 | find /sys/class/pwm -name "uevent" -exec chmod 0660 {} \; 41 | find /sys/devices/platform/ocp -name "uevent" -exec chmod 0660 {} \; 42 | 43 | # Additional code for getting AIN pins set up 44 | ain_activator=/sys/devices/platform/bone_capemgr/slots 45 | chown -R debian:debian $ain_activator/ 46 | chmod -R 2770 $ain_activator/ 47 | --------------------------------------------------------------------------------