Skip to content

Commit

Permalink
More docs tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
waveform80 committed Oct 14, 2022
1 parent 4cdf5f7 commit c96dc13
Show file tree
Hide file tree
Showing 5 changed files with 141 additions and 16 deletions.
6 changes: 6 additions & 0 deletions RPi/GPIO.py
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,12 @@ def add_event_detect(channel, edge, callback=None, bouncetime=None):
when the specified *edge* is seen on the GPIO *channel*. The callable must
accept a single parameter: the channel on which the edge was detected.
.. note::
Debounce works significantly differently in rpi-lgpio than it does
in rpi-gpio; please see :ref:`debounce` for more information on the
differences.
:param int channel:
The board pin number or BCM number depending on :func:`setmode` to
watch for changes
Expand Down
4 changes: 4 additions & 0 deletions docs/_static/style_override.css
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@
margin-top: 0;
}

.rst-content div.chart pre {
line-height: 1;
}

.rst-content div.code-block-caption + div.highlight-python3 {
margin-top: 0;
}
Expand Down
58 changes: 58 additions & 0 deletions docs/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,61 @@ PWM
===

.. autoclass:: PWM


Constants
=========

.. data:: BOARD

Indicates to :func:`setmode` that physical board numbering is requested

.. data:: BCM

Indicates to :func:`setmode` that GPIO numbering is requested

.. data:: PUD_OFF

Used with :func:`setup` to disable internal pull resistors on an input

.. data:: PUD_DOWN

Used with :func:`setup` to enable the internal pull-down resistor on an
input

.. data:: PUD_UP

Used with :func:`setup` to enable the internal pull-up resistor on an input

.. data:: OUT

Used with :func:`setup` to set a GPIO to an output

.. data:: IN

Used with :func:`setup` to set a GPIO to an input

.. data:: LOW
:value: 0

Used with :func:`output` to turn an output GPIO off

.. data:: HIGH
:value: 1

Used with :func:`output` to turn an output GPIO on

.. data:: RISING

Used with :func:`wait_for_edge` and :func:`add_event_detect` to specify
that rising edges only should be sampled

.. data:: FALLING

Used with :func:`wait_for_edge` and :func:`add_event_detect` to specify
that falling edges only should be sampled

.. data:: BOTH

Used with :func:`wait_for_edge` and :func:`add_event_detect` to specify
that all edges should be sampled
2 changes: 1 addition & 1 deletion docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

# -- Project information -----------------------------------------------------

project = metadata['name'].title()
project = metadata['name']
author = metadata['author']
copyright = '{now:%Y} {author}'.format(now=datetime.now(), author=author)
release = metadata['version']
Expand Down
87 changes: 72 additions & 15 deletions docs/differences.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,31 @@
Differences
=======================

Many of the assumptions underlying RPi.GPIO -- that it has complete access to,
and control over, the registers controlling the GPIO pins -- do not work when
applied to the Linux gpiochip devices. To that end, while the library strives
as far as possible to be "bug compatible" with RPi.GPIO, there *are*
.. currentmodule:: RPi.GPIO

Many of the assumptions underlying `RPi.GPIO`_ -- that it has complete access
to, and control over, the registers controlling the GPIO pins -- do not work
when applied to the Linux gpiochip devices. To that end, while the library
strives as far as possible to be "bug compatible" with RPi.GPIO, there *are*
differences in behaviour that may result in incompatibility.


Bug Compatible?
===============

What does being "bug compatible" mean? Simply put it means it is not enough for
the library to implement the RPi.GPIO API. It must also act, as far as is
reasonable possible, like RPi.GPIO too. Naturally it must export the same
functions and classes as RPi.GPIO. However it must also:
the library to implement the `RPi.GPIO`_ API. It must also:

* Act, as far as possible, in the same way to the same calls with the same
values

* Raise the same exception tyes, with the same messages, in the same
* Raise the same exception types, with the same messages, in the same
circumstances

* Break (i.e. fail to operate correctly) in the same way, as far as possible

This may sound silly, but a library is *always* used in unexpected or
undocumented ways by *some* applications and thus anything that tries to take
This last point may sound silly, but a library is *always* used in unexpected
or undocumented ways by *some* applications. Thus anything that tries to take
the place of that library must do more than simply operate the same as the
"documented surface" would suggest.

Expand Down Expand Up @@ -85,7 +88,7 @@ allocate it:
>>> GPIO.setup(26, GPIO.OUT)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/dave/projects/home/rpi-lgpio/rpi-lgpio/RPi/GPIO.py", line 569, in setup
File "/home/dave/projects/rpi-lgpio/rpi-lgpio/RPi/GPIO.py", line 569, in setup
initial = _check(lgpio.gpio_read(_chip, gpio))
File "/home/dave/envs/rpi-lgpio/lib/python3.10/site-packages/lgpio.py", line 894, in gpio_read
return _u2i(_lgpio._gpio_read(handle&0xffff, gpio))
Expand All @@ -94,7 +97,7 @@ allocate it:
lgpio.error: 'GPIO not allocated'
.. _debounce
.. _debounce:

Debounce
========
Expand All @@ -117,7 +120,10 @@ For some applications, there will be little/no difference other than rpi-lgpio
reporting an edge a few milliseconds later than RPi.GPIO would (specifically,
by the amount of debounce requsted). The following diagram shows the waveform
from a "bouncy" switch, along with the positions in time where RPi.GPIO and
rpi-lgpio would report the rising edge when debounce of 3ms is requested::
rpi-lgpio would report the rising edge when debounce of 3ms is requested:

.. code-block::
:class: chart
0ms 2ms 4ms 6ms 8ms
| | | | |
Expand All @@ -134,7 +140,10 @@ because they are within 3ms of the last edge. By contrast, rpi-lgpio ignores
the first and second rising edges (because they didn't stay stable for 3ms) and
only reports the third edge at 7ms (after it's spent 3ms stable).

However, consider this same scenario if debounce of 2ms is requested::
However, consider this same scenario if debounce of 2ms is requested:

.. code-block::
:class: chart
0ms 2ms 4ms 6ms 8ms
| | | | |
Expand All @@ -157,7 +166,10 @@ with rpi-lgpio, than with RPi.GPIO. They will still debounce effectively, but
will reduce the delay in reporting edges.

One final scenario to consider is a waveform of equally spaced, repeating
pulses (like PWM) every 2ms::
pulses (like PWM) every 2ms:

.. code-block::
:class: chart
0ms 2ms 4ms 6ms 8ms 10ms 12ms
| | | | | | |
Expand All @@ -174,4 +186,49 @@ half of the edges; it's suppressing every other edge as they occur within 3ms
of the edge preceding them. rpi-lgpio, on the other hand, reports *no* edges at
all because none of them stay stable for 3ms.


PWM on inputs
=============

RPi.GPIO permits (probably erroneously), PWM objects to continue operating on
pins that are switched to inputs:

.. code-block:: pycon
>>> from RPi import GPIO
>>> GPIO.setmode(GPIO.BCM)
>>> GPIO.setup(26, GPIO.OUT)
>>> p = GPIO.PWM(26, 1000)
>>> p.start(75)
>>> GPIO.setup(26, GPIO.IN)
>>> p.stop()
>>> p.start(75)
>>> p.stop()
This will not work under rpi-lgpio:

.. code-block:: pycon
>>> from RPi import GPIO
>>> GPIO.setmode(GPIO.BCM)
>>> GPIO.setup(26, GPIO.OUT)
>>> p = GPIO.PWM(26, 1000)
>>> p.start(75)
>>> GPIO.setup(26, GPIO.IN)
>>> p.stop()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/dave/projects/rpi-lgpio/rpi-lgpio/RPi/GPIO.py", line 190, in stop
lgpio.tx_pwm(_chip, self._gpio, 0, 0)
File "/home/dave/envs/rpi-lgpio/lib/python3.10/site-packages/lgpio.py", line 1074, in tx_pwm
return _u2i(_lgpio._tx_pwm(
File "/home/dave/envs/rpi-lgpio/lib/python3.10/site-packages/lgpio.py", line 461, in _u2i
raise error(error_text(v))
lgpio.error: 'bad PWM micros'
Though note that the error occurs when the :class:`PWM` object is *next* acted
upon, rather than at the point when the GPIO is switched to an input.


.. _RPi.GPIO: https://pypi.org/project/RPi.GPIO/
.. _lgpio: https://abyz.me.uk/lg/py_lgpio.html

0 comments on commit c96dc13

Please sign in to comment.