<commit_before># 0. Introduction

Drivers for switches and pushbuttons are provided, plus a retriggerable delay
class. The switch and button drivers support debouncing. The switch driver
provides for running a callback or launching a coroutine (coro) on contact
closure and/or opening.

The pushbutton driver extends this to support long-press and double-click
events.

The asynchronous ADC supports pausing a task until the value read from an ADC
goes outside defined bounds.

# 1. Contents

 1. [Contents](./DRIVERS.md#1-contents)  
 2. [Installation and usage](./DRIVERS.md#2-installation-and-usage)  
 3. [Interfacing switches](./DRIVERS.md#3-interfacing-switches) Switch debouncer with callbacks.  
  3.1 [Switch class](./DRIVERS.md#31-switch-class)  
 4. [Interfacing pushbuttons](./DRIVERS.md#4-interfacing-pushbuttons) Extends Switch for long and double click events  
  4.1 [Pushbutton class](./DRIVERS.md#41-pushbutton-class)  
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.1.1 [The suppress constructor argument](./DRIVERS.md#411-the-suppress-constructor-argument)  
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.1.2 [The sense constructor argument](./DRIVERS.md#412-the-sense-constructor-argument)  
 5. [ADC monitoring](./DRIVERS.md#5-adc-monitoring) Pause until an ADC goes out of bounds  
  5.1 [AADC class](./DRIVERS.md#51-aadc-class)  
  5.2 [Design note](./DRIVERS.md#52-design-note)  
 6. [Additional functions](./DRIVERS.md#6-additional-functions)  
  6.1 [launch](./DRIVERS.md#61-launch) Run a coro or callback interchangeably  
  6.2 [set_global_exception](./DRIVERS.md#62-set_global_exception) Simplify debugging with a global exception handler  

###### [Tutorial](./TUTORIAL.md#contents)

# 2. Installation and usage

The drivers are in the primitives package. To install copy the `primitives`
directory and its contents to the target hardware.

Drivers are imported with:
```python
from primitives.switch import Switch
from primitives.pushbutton import Pushbutton
from primitives.aadc import AADC
```
There is a test/demo program for the Switch and Pushbutton classes. On import
this lists available tests. It assumes a Pyboard with a switch or pushbutton
between X1 and Gnd. It is run as follows:
```python
from primitives.tests.switches import *
test_sw()  # For example
```
The test for the `AADC` class requires a Pyboard with pins X1 and X5 linked. It
is run as follows:
```python
from primitives.tests.adctest import test
test()
```

###### [Contents](./DRIVERS.md#1-contents)

# 3. Interfacing switches

The `primitives.switch` module provides the `Switch` class. This supports
debouncing a normally open switch connected between a pin and ground. Can run
callbacks or schedule coros on contact closure and/or opening.

In the following text the term `callable` implies a Python `callable`: namely a
function, bound method, coroutine or bound coroutine. The term implies that any
of these may be supplied.

### Timing

The `Switch` class relies on millisecond-level timing: callback functions must
be designed to terminate rapidly. This applies to all functions in the
application; coroutines should yield regularly. If these constraints are not
met, switch events can be missed.

## 3.1 Switch class

This assumes a normally open switch connected between a pin and ground. The pin
should be initialised as an input with a pullup. A `callable` may be specified
to run on contact closure or opening; where the `callable` is a coroutine it
will be converted to a `Task` and will run asynchronously. Debouncing is
implicit: contact bounce will not cause spurious execution of the `callable`.

Constructor argument (mandatory):

 1. `pin` The initialised Pin instance.
 
Methods:

 1. `close_func` Args: `func` (mandatory) a `callable` to run on contact
 closure. `args` a tuple of arguments for the `callable` (default `()`)
 2. `open_func` Args: `func` (mandatory) a `callable` to run on contact open.
 `args` a tuple of arguments for the `callable` (default `()`)
 3. `__call__` Call syntax e.g. `myswitch()` returns the physical debounced
 state of the switch i.e. 0 if grounded, 1 if connected to `3V3`.

Methods 1 and 2 should be called before starting the scheduler.

Class attribute:
 1. `debounce_ms` Debounce time in ms. Default 50.

```python
from pyb import LED
from machine import Pin
import uasyncio as asyncio
from primitives.switch import Switch

async def pulse(led, ms):
    led.on()
    await asyncio.sleep_ms(ms)
    led.off()

async def my_app():
    await asyncio.sleep(60)  # Dummy application code

pin = Pin('X1', Pin.IN, Pin.PULL_UP)  # Hardware: switch to gnd
red = LED(1)
sw = Switch(pin)
sw.close_func(pulse, (red, 1000))  # Note how coro and args are passed
asyncio.run(my_app())  # Run main application code
```

###### [Contents](./DRIVERS.md#1-contents)

# 4. Interfacing pushbuttons

The `primitives.pushbutton` module provides the `Pushbutton` class. This is a
generalisation of `Switch` to support normally open or normally closed switches
connected to ground or 3V3. Can run a `callable` on on press, release,
double-click or long press events.

## 4.1 Pushbutton class

This can support normally open or normally closed switches, connected to `gnd`
(with a pullup) or to `3V3` (with a pull-down). The `Pin` object should be
initialised appropriately. The default state of the switch can be passed in the
optional "sense" parameter on the constructor, otherwise the assumption is that
on instantiation the button is not pressed.

The Pushbutton class uses logical rather than physical state: a button's state
is considered `True` if pressed, otherwise `False` regardless of its physical
implementation.

`callable` instances may be specified to run on button press, release, double
click or long press events; where the `callable` is a coroutine it will be
converted to a `Task` and will run asynchronously.

Please see the note on timing in section 3.

Constructor arguments:

 1. `pin` Mandatory. The initialised Pin instance.
 2. `suppress` Default `False`. See
 [section 4.1.1](./DRIVERS.md#411-the-suppress-constructor-argument).
 3. `sense` Default `None`. See
 [section 4.1.1](./DRIVERS.md#412-the-sense-constructor-argument).

Methods:

 1. `press_func` Args: `func` (mandatory) a `callable` to run on button push.
 `args` a tuple of arguments for the `callable` (default `()`).
 2. `release_func` Args: `func` (mandatory) a `callable` to run on button
 release. `args` a tuple of arguments for the `callable` (default `()`).
 3. `long_func` Args: `func` (mandatory) a `callable` to run on long button
 push. `args` a tuple of arguments for the `callable` (default `()`).
 4. `double_func` Args: `func` (mandatory) a `callable` to run on double
 push. `args` a tuple of arguments for the `callable` (default `()`).
 5. `__call__` Call syntax e.g. `mybutton()` Returns the logical debounced
 state of the button (`True` corresponds to pressed).
 6. `rawstate()` Returns the logical instantaneous state of the button. There
 is probably no reason to use this.

Methods 1 - 4 should be called before starting the scheduler.

Class attributes:
 1. `debounce_ms` Debounce time in ms. Default 50.<commit_msg>V3 DRIVERS.md fix TOC and link.<commit_after># 0. Introduction

Drivers for switches and pushbuttons are provided, plus a retriggerable delay
class. The switch and button drivers support debouncing. The switch driver
provides for running a callback or launching a coroutine (coro) on contact
closure and/or opening.

The pushbutton driver extends this to support long-press and double-click
events.

The asynchronous ADC supports pausing a task until the value read from an ADC
goes outside defined bounds.

# 1. Contents

 1. [Contents](./DRIVERS.md#1-contents)  
 2. [Installation and usage](./DRIVERS.md#2-installation-and-usage)  
 3. [Interfacing switches](./DRIVERS.md#3-interfacing-switches) Switch debouncer with callbacks.  
  3.1 [Switch class](./DRIVERS.md#31-switch-class)  
 4. [Interfacing pushbuttons](./DRIVERS.md#4-interfacing-pushbuttons) Extends Switch for long and double click events  
  4.1 [Pushbutton class](./DRIVERS.md#41-pushbutton-class)  
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.1.1 [The suppress constructor argument](./DRIVERS.md#411-the-suppress-constructor-argument)  
  &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.1.2 [The sense constructor argument](./DRIVERS.md#412-the-sense-constructor-argument)  
 5. [ADC monitoring](./DRIVERS.md#5-adc-monitoring) Pause until an ADC goes out of bounds  
  5.1 [AADC class](./DRIVERS.md#51-aadc-class)  
  5.2 [Design note](./DRIVERS.md#52-design-note)  
 6. [Additional functions](./DRIVERS.md#6-additional-functions)  
  6.1 [launch](./DRIVERS.md#61-launch) Run a coro or callback interchangeably  
  6.2 [set_global_exception](./DRIVERS.md#62-set_global_exception) Simplify debugging with a global exception handler  

###### [Tutorial](./TUTORIAL.md#contents)

# 2. Installation and usage

The drivers are in the primitives package. To install copy the `primitives`
directory and its contents to the target hardware.

Drivers are imported with:
```python
from primitives.switch import Switch
from primitives.pushbutton import Pushbutton
from primitives.aadc import AADC
```
There is a test/demo program for the Switch and Pushbutton classes. On import
this lists available tests. It assumes a Pyboard with a switch or pushbutton
between X1 and Gnd. It is run as follows:
```python
from primitives.tests.switches import *
test_sw()  # For example
```
The test for the `AADC` class requires a Pyboard with pins X1 and X5 linked. It
is run as follows:
```python
from primitives.tests.adctest import test
test()
```

###### [Contents](./DRIVERS.md#1-contents)

# 3. Interfacing switches

The `primitives.switch` module provides the `Switch` class. This supports
debouncing a normally open switch connected between a pin and ground. Can run
callbacks or schedule coros on contact closure and/or opening.

In the following text the term `callable` implies a Python `callable`: namely a
function, bound method, coroutine or bound coroutine. The term implies that any
of these may be supplied.

### Timing

The `Switch` class relies on millisecond-level timing: callback functions must
be designed to terminate rapidly. This applies to all functions in the
application; coroutines should yield regularly. If these constraints are not
met, switch events can be missed.

## 3.1 Switch class

This assumes a normally open switch connected between a pin and ground. The pin
should be initialised as an input with a pullup. A `callable` may be specified
to run on contact closure or opening; where the `callable` is a coroutine it
will be converted to a `Task` and will run asynchronously. Debouncing is
implicit: contact bounce will not cause spurious execution of the `callable`.

Constructor argument (mandatory):

 1. `pin` The initialised Pin instance.
 
Methods:

 1. `close_func` Args: `func` (mandatory) a `callable` to run on contact
 closure. `args` a tuple of arguments for the `callable` (default `()`)
 2. `open_func` Args: `func` (mandatory) a `callable` to run on contact open.
 `args` a tuple of arguments for the `callable` (default `()`)
 3. `__call__` Call syntax e.g. `myswitch()` returns the physical debounced
 state of the switch i.e. 0 if grounded, 1 if connected to `3V3`.

Methods 1 and 2 should be called before starting the scheduler.

Class attribute:
 1. `debounce_ms` Debounce time in ms. Default 50.

```python
from pyb import LED
from machine import Pin
import uasyncio as asyncio
from primitives.switch import Switch

async def pulse(led, ms):
    led.on()
    await asyncio.sleep_ms(ms)
    led.off()

async def my_app():
    await asyncio.sleep(60)  # Dummy application code

pin = Pin('X1', Pin.IN, Pin.PULL_UP)  # Hardware: switch to gnd
red = LED(1)
sw = Switch(pin)
sw.close_func(pulse, (red, 1000))  # Note how coro and args are passed
asyncio.run(my_app())  # Run main application code
```

###### [Contents](./DRIVERS.md#1-contents)

# 4. Interfacing pushbuttons

The `primitives.pushbutton` module provides the `Pushbutton` class. This is a
generalisation of `Switch` to support normally open or normally closed switches
connected to ground or 3V3. Can run a `callable` on on press, release,
double-click or long press events.

## 4.1 Pushbutton class

This can support normally open or normally closed switches, connected to `gnd`
(with a pullup) or to `3V3` (with a pull-down). The `Pin` object should be
initialised appropriately. The default state of the switch can be passed in the
optional "sense" parameter on the constructor, otherwise the assumption is that
on instantiation the button is not pressed.

The Pushbutton class uses logical rather than physical state: a button's state
is considered `True` if pressed, otherwise `False` regardless of its physical
implementation.

`callable` instances may be specified to run on button press, release, double
click or long press events; where the `callable` is a coroutine it will be
converted to a `Task` and will run asynchronously.

Please see the note on timing in section 3.

Constructor arguments:

 1. `pin` Mandatory. The initialised Pin instance.
 2. `suppress` Default `False`. See
 [section 4.1.1](./DRIVERS.md#411-the-suppress-constructor-argument).
 3. `sense` Default `None`. See
 [section 4.1.2](./DRIVERS.md#412-the-sense-constructor-argument).

Methods:

 1. `press_func` Args: `func` (mandatory) a `callable` to run on button push.
 `args` a tuple of arguments for the `callable` (default `()`).
 2. `release_func` Args: `func` (mandatory) a `callable` to run on button
 release. `args` a tuple of arguments for the `callable` (default `()`).
 3. `long_func` Args: `func` (mandatory) a `callable` to run on long button
 push. `args` a tuple of arguments for the `callable` (default `()`).
 4. `double_func` Args: `func` (mandatory) a `callable` to run on double
 push. `args` a tuple of arguments for the `callable` (default `()`).
 5. `__call__` Call syntax e.g. `mybutton()` Returns the logical debounced
 state of the button (`True` corresponds to pressed).
 6. `rawstate()` Returns the logical instantaneous state of the button. There
 is probably no reason to use this.

Methods 1 - 4 should be called before starting the scheduler.

Class attributes:
 1. `debounce_ms` Debounce time in ms. Default 50.
{'fraction_non_alphanumeric': 0.09649490294651585, 'fraction_numerical': 0.01598938695712889, 'mean_word_length': 4.404905660377358, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6094399', 'n_tokens_mistral': 4494, 'n_tokens_neox': 4216, 'n_words': 1846}