Skip to content

API Reference

chumicro_buttons.core

Button reads one momentary button or switch: a debounced level, the edges either side of it, and the durations built on top (long press, auto-repeat, click counting). Buttons reads several keys on one scan and hands you each as a Button.

chumicro_buttons.core

Buttons and switches: debounced level, edges, long press, repeat, and click counting.

Button

One momentary button or switch, read as a debounced level plus what it meant.

Every reading is a plain attribute refreshed by check(now_ms), and the just_ family is true only for the tick the thing happened on, so a loop can read them without consuming anything. A switch that stays where you put it uses the same object, reading pressed and watching the edges for when it moved. Constructing with pin builds the runtime's own source, a firmware keypad scan on CircuitPython and a capture interrupt on MicroPython, and both catch a tap that starts and ends between two passes of your loop.

Parameters:

Name Type Description Default
pin object | None

Runtime pin object for the key, or None when a parent drives this button.

None
ticks object

The clock every duration here is judged by, chumicro_timing.ticks or anything shaped like it. Required, and it is the only clock this library reads, so the ticks you pass check(now_ms) and the settle window the source debounces against share one time base.

required
source object | None

Pre-built edge source; overrides pin. Tests inject a fake here.

None
active_low bool

True when a pressed key reads low. True suits a button wired to ground with the internal pull-up enabled, which is nearly always the wiring.

True
settle_ms int

Debounce window in milliseconds, and the shortest press that can be reported. Raise it for a switch that bounces badly, lower it for fast tapping, and use zero for a button with hardware debouncing behind it.

DEFAULT_SETTLE_MS
long_press_ms int

Hold time that fires just_long_pressed. Zero disables it.

DEFAULT_LONG_PRESS_MS
repeat_ms int

Interval between just_repeated fires while held. Zero disables it.

0
repeat_delay_ms int

Hold time before repeat starts.

DEFAULT_REPEAT_DELAY_MS
click_ms int

Quiet time after a release that closes a click series and publishes click_count. Zero disables click counting.

0

check(now_ms)

Drain captured edges and advance the timers by one tick.

Parameters:

Name Type Description Default
now_ms int

Tick this pass of the loop is measured from.

required

Returns:

Type Description
bool

True when anything happened, so a quiet tick can skip handle.

handle(now_ms)

Call whichever callbacks this tick's readings earned.

next_deadline(now_ms)

Return the earliest tick a timer here fires at, or None while none is armed.

The runner reads this before it sleeps, so a long press, an auto-repeat, or a click window fires on time instead of at the next unrelated wake. A press is a pin edge rather than a timer, so no deadline can name one; an edge that lands mid-sleep is captured with its real timestamp and reported at the next tick.

deinit()

Release the pins and any interrupt the source installed.

Buttons

Several keys on one source, ticked together and read one key at a time.

buttons[0] is a :class:Button carrying that key's readings and its own callbacks, and the whole-panel callbacks take the key number instead. On CircuitPython this is one firmware keypad scan across all the pins rather than one per key, which is both cheaper and what makes chords land on the same tick.

Parameters:

Name Type Description Default
pins object | None

Runtime pin objects, one per key.

None
ticks object

The clock every duration here is judged by, chumicro_timing.ticks or anything shaped like it. Required, and it reaches the scan and every key below, so the whole panel measures against one time base.

required
source object | None

Pre-built edge source; overrides pins. Tests inject a fake here.

None
active_low bool

True when a pressed key reads low.

True
settle_ms int

Debounce window in milliseconds; 0 trusts the signal.

DEFAULT_SETTLE_MS
long_press_ms int

Hold time that fires just_long_pressed. Zero disables it.

DEFAULT_LONG_PRESS_MS
repeat_ms int

Interval between repeat fires while held. Zero disables it.

0
repeat_delay_ms int

Hold time before repeat starts.

DEFAULT_REPEAT_DELAY_MS
click_ms int

Quiet time that closes a click series. Zero disables click counting.

0

check(now_ms)

Drain captured edges into every key and advance their timers.

Parameters:

Name Type Description Default
now_ms int

Tick this pass of the loop is measured from.

required

Returns:

Type Description
bool

True when any key produced news this tick, so a quiet tick can skip handle.

handle(now_ms)

Call the per-key callbacks, then the whole-panel ones.

next_deadline(now_ms)

Return the earliest tick any key's timer fires at, or None while none is armed.

deinit()

Release the pins and any interrupt the source installed.

__len__()

Return how many keys this panel reads.

__getitem__(key_index)

Return the :class:Button for key_index.

chumicro_buttons.matrix

KeyMatrix reads a keypad wired as rows by columns. Keys are numbered row-major and carry the same readings and callbacks as any other button.

chumicro_buttons.matrix

A keypad wired as rows by columns, read as the same buttons everything else reads.

KeyMatrix

Bases: Buttons

A keypad whose keys sit where a row crosses a column, read one key at a time.

Wiring keys as a grid is what lets twelve of them share seven pins, and every key still reads as an ordinary button: matrix[5] is a :class:~chumicro_buttons.core.Button with its own pressed, its own edges, and its own long press, repeat, and click counting. Keys are numbered row-major, so the key at row, column is row * len(column_pins) + column, and with three columns key 4 is row 1, column 1.

CircuitPython drives the grid in the firmware's own background scan; MicroPython drives it once per check(now_ms), because a grid has to be scanned a row at a time and column interrupts would report keys nobody touched.

Parameters:

Name Type Description Default
row_pins object | None

Runtime pin objects for the rows.

None
column_pins object | None

Runtime pin objects for the columns.

None
ticks object

The clock every duration here is judged by, chumicro_timing.ticks or anything shaped like it. Required, and it reaches the scan and every key below, so the whole keypad measures against one time base.

required
source object | None

Pre-built edge source; overrides the pins. Tests inject a fake here.

None
columns_to_anodes bool

Which way the matrix's diodes face. Leave it True when each diode's striped end points at a row pin, which is how ready-made keypads are built. Guessing wrong is quiet rather than damaging: the diodes block the scan and no key ever reads as pressed, so a keypad that reports nothing is the symptom to try it on.

True
settle_ms int

Debounce window in milliseconds; 0 trusts the signal.

DEFAULT_SETTLE_MS
long_press_ms int

Hold time that fires just_long_pressed. Zero disables it.

DEFAULT_LONG_PRESS_MS
repeat_ms int

Interval between repeat fires while held. Zero disables it.

0
repeat_delay_ms int

Hold time before repeat starts.

DEFAULT_REPEAT_DELAY_MS
click_ms int

Quiet time that closes a click series. Zero disables click counting.

0

chumicro_buttons.testing

FakeButtonSource stands in for the hardware so button logic can be tested on a host. Queue the edges, tick the button, assert on what it made of them.

chumicro_buttons.testing

Test-support helpers: a hand-driven :class:FakeButtonSource.

FakeButtonSource

Edge source a test drives by hand instead of by hardware.

Queue the edges you want the button to see, then tick the button. Each edge carries its own timestamp, which is how a test exercises the case that matters on a real board: an edge captured earlier than the tick that noticed it.

Parameters:

Name Type Description Default
key_count int

How many keys this source reports.

1

press(key_index=0, at_ms=0)

Queue a press edge for key_index stamped at at_ms.

release(key_index=0, at_ms=0)

Queue a release edge for key_index stamped at at_ms.

poll(now_ms)

Record that a capture step was asked for; the queue is filled by the test.

next_event()

Advance to the next queued edge, or report the queue drained.

deinit()

Record that the button released this source.