Skip to content

Commit

Permalink
Add a tutorial introduction. (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
corranwebster authored Sep 17, 2024
1 parent 04fbb3b commit 01b3ec8
Show file tree
Hide file tree
Showing 11 changed files with 574 additions and 48 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build_docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Install dependencies and local packages
run: python -m pip install sphinx pydata-sphinx-theme
- name: Build HTML documentation with Sphinx
run: make html
run: make html SPHINXOPTS="-W --keep-going -n"
working-directory: docs
- uses: actions/upload-pages-artifact@v3
with:
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/check_docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ jobs:
- name: Install dependencies and local packages
run: python -m pip install sphinx pydata-sphinx-theme
- name: Build HTML documentation with Sphinx
run: make html
run: |
make html
make html SPHINXOPTS="-W --keep-going -n"
working-directory: docs
- uses: actions/upload-artifact@v4
with:
Expand Down
76 changes: 44 additions & 32 deletions README.rst
Original file line number Diff line number Diff line change
@@ -1,10 +1,23 @@
Ultimo
======

Ultimo is an interface framework for micropython built around asynchronous
Ultimo is an interface framework for Micropython built around asynchronous
iterators.

Ultimo allows you to implement the logic of a micropython application
- `Documentation <https://unital.github.io/ultimo/>`_

- `User Guide <https://unital.github.io/ultimo/user_guide.html>`_

- `Installation <https://unital.github.io/ultimo/user_guide/installation.html>`_
- `Tutorial <https://unital.github.io/ultimo/user_guide/tutorial.html>`_
- `Examples <https://unital.github.io/ultimo/user_guide/examples.html>`_

- `API <https://unital.github.io/ultimo/api.html>`_

Description
-----------

Ultimo allows you to implement the logic of a Micropython application
around a collection of asyncio Tasks that consume asynchronous iterators.
This is compared to the usual synchronous approach of having a single main
loop that mixes together the logic for all the different activities that your
Expand All @@ -16,46 +29,45 @@ activity, so a user interaction, like changing the value of a potentiometer or
polling a button can happen in milliseconds, while a clock or temperature
display can be updated much less frequently.

For example, to make a potentiometer control the duty cycle of an RGB LED
you might do something like::

async def control_brightness(led, adc):
async for value in adc:
led.brightness(value >> 8)

while to output the current time to a 16x2 LCD, you might do::

async def display_time(lcd, clock):
async for dt in clock:
value = b"{4:02d}:{5:02d}".format(dt)
lcd.clear()
lcd.write(value)

You can then combine these into a single application by creating Tasks in
a ``main`` function::

async def main():
led, lcd, adc, clock = initialize()
brightness_task = asyncio.create_task(control_brightness(led, adc))
display_task = asyncio.create_task(display_time(lcd, clock))
# run forever
await asyncio.gather(brightness_task, display_task)

if __name__ == "__main__":
asyncio.run(main())

The ``ultimo`` library provides classes that simplify this paradigm.
There are classes which provide asynchronous iterators based around polling,
interrupts and asynchronous streams, as well as intermediate transforming
iterators that handle common tasks such as smoothing and de-duplication.
The basic Ultimo library is hardware-independent and should work on any
recent micropython version.
recent Micropython version.

The ``ultimo_machine`` library provides hardware support wrapping
the micropython ``machine`` module and other standard library
the Micropython ``machine`` module and other standard library
modules. It provides sources for simple polling of and interrupts from GPIO
pins, polled ADC, polled RTC and interrupt-based timer sources.

For example, you can write code like the following to print temperature and
time asynchronously::

import asyncio
from machine import ADC

from ultimo.pipelines import Dedup
from ultimo_machine.gpio import PollADC
from ultimo_machine.time import PollRTC

async def temperature():
async for value in PollADC(ADC.CORE_TEMP, 10.0):
t = 27 - (3.3 * value / 0xFFFF - 0.706) / 0.001721
print(t)

async def clock():
async for current_time in Dedup(PollRTC(0.1)):
print(current_time)

async def main():
temperature_task = asyncio.create_task(temperature())
clock_task = asyncio.create_task(clock())
await asyncio.gather(temperature_task, clock_task)

if __name__ == '__main__':
asyncio.run(main())

Ultimo also provides convenience decorators and a syntax for building pipelines
from basic building blocks using the bitwise-or (or "pipe" operator)::

Expand Down
2 changes: 1 addition & 1 deletion docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,13 @@
},
],
"icon_links_label": "Quick Links",
"default_mode": "dark",
}
html_context = {
"github_user": "unital",
"github_repo": "ultimo",
"github_version": "main",
"doc_path": "docs",
"default_mode": "dark",
}

# -- Options for autodoc -----------------------------------------------------
Expand Down
12 changes: 6 additions & 6 deletions docs/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
Ultimo documentation
====================

An interface framework for micropython built around asynchronous iterators.
An interface framework for Micropython built around asynchronous iterators.

Ultimo allows you to implement the logic of a micropython application
Ultimo allows you to implement the logic of a Micropython application
around a collection of asyncio Tasks that consume asynchronous iterators.
This is compared to the usual synchronous approach of having a single main
loop that mixes together the logic for all the different activities that your
Expand All @@ -20,15 +20,15 @@ activity, so a user interaction, like changing the value of a potentiometer or
polling a button can happen in milliseconds, while a clock or temperature
display can be updated much less frequently.

The ``ultimo`` library provides classes that simplify this paradigm.
The :py:mod:`ultimo` library provides classes that simplify this paradigm.
There are classes which provide asynchronous iterators based around polling,
interrupts and asynchronous streams, as well as intermediate transforming
iterators that handle common tasks such as smoothing and de-duplication.
The basic Ultimo library is hardware-independent and should work on any
recent micropython version.
recent Micropython version.

The ``ultimo_machine`` library provides hardware support wrapping
the micropython ``machine`` module and other standard library
The :py:mod:`ultimo_machine` library provides hardware support wrapping
the Micropython :py:mod:`machine`` module and other standard library
modules. It provides sources for simple polling of, and interrupts from, GPIO
pins, polled ADC, polled RTC, and interrupt-based timer sources.

Expand Down
3 changes: 2 additions & 1 deletion docs/source/user_guide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Ultimo User Guide

.. currentmodule:: ultimo

Ultimo is an interface framework for micropython built around asynchronous
Ultimo is an interface framework for Micropython built around asynchronous
iterators.

This is the user-guide for Ultimo.
Expand All @@ -15,6 +15,7 @@ This is the user-guide for Ultimo.

user_guide/introduction.rst
user_guide/installation.rst
user_guide/tutorial.rst
user_guide/core_classes.rst
user_guide/machine_classes.rst
user_guide/display_classes.rst
Expand Down
2 changes: 1 addition & 1 deletion docs/source/user_guide/core_classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ For example, the following class provides a class for handling IRQs from a
async def close(self):
self.pin.irq()

As with all interrupt-based code in micropython, care needs to be taken in
As with all interrupt-based code in Micropython, care needs to be taken in
the interrupt handler and the iterator method so that the code is fast,
robust and reentrant. Also note that although interrupt handlers may be
fast, any |EventFlow| instances watching the event will be dispatched by
Expand Down
26 changes: 24 additions & 2 deletions docs/source/user_guide/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,29 @@ we would like to add ``mip`` and better stub file support.
Installation
------------

If you want to experiment with Ultimo on a Raspberry Pi Pico, there is a
Ultimo can be installed from github via :py:mod:`mip`. For most use-cases
you will probably want to install :py:mod:`ultimo_machine` which will also
insatll the core :py:mod:`ultimo` package:

.. code-block:: python-console
>>> mip.install("github:unital/ultimo/src/ultimo_machine/package.json")
or using :py:mod:`mpremote`:

.. code-block:: console
mpremote mip install github:unital/ultimo/src/ultimo_machine/package.json
You can separately install :py:mod:`ultimo_display` from
``github:unital/ultimo/src/ultimo_display/package.json`` and if you just
want the core :py:mod:`ultimo` without any hardware support, you can install
``github:unital/ultimo/src/ultimo/package.json``.

Development Installation
------------------------

To simplify the development work-cycle with actual hardware, there is a
helper script in the ci directory which will download the files onto the
device. You will need an environment with ``mpremote`` and ``click``
installed. For example, on a Mac/Linux machine:
Expand Down Expand Up @@ -55,7 +77,7 @@ serial console support than Thonny provides, and so may need to use
Writing Code Using Ultimo
-------------------------

Althought Ultimo is a micropython library, it provides ``.pyi`` stub files for
Althought Ultimo is a Micropython library, it provides ``.pyi`` stub files for
typing support. If you add the ultimo sources to the paths where tools like
``mypy`` and ``pyright`` look for stubs (in particular, ``pip install -e ...``
will likely work), then you should be able to get type-hints for the code you
Expand Down
6 changes: 3 additions & 3 deletions docs/source/user_guide/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Introduction

.. currentmodule:: ultimo

Ultimo allows you to implement the logic of a micropython application
Ultimo allows you to implement the logic of a Micropython application
around a collection of asyncio Tasks that consume asynchronous iterators.
This is compared to the usual synchronous approach of having a single main
loop that mixes together the logic for all the different activities that your
Expand Down Expand Up @@ -52,10 +52,10 @@ There are classes which provide asynchronous iterators based around polling,
interrupts and asynchronous streams, as well as intermediate transforming
iterators that handle common tasks such as smoothing and de-duplication.
The basic Ultimo library is hardware-independent and should work on any
recent micropython version.
recent Micropython version.

The :py:mod:`ultimo_machine` library provides hardware support wrapping
the micropython :py:mod:`machine` module and other standard library
the Micropython :py:mod:`machine` module and other standard library
modules. It provides sources for simple polling of and interrupts from GPIO
pins, polled ADC, polled RTC and interrupt-based timer sources.

Expand Down
Loading

0 comments on commit 01b3ec8

Please sign in to comment.