st3m.input module

All user facing classes contained herein are provided by the st3m.application.Application class, there is not really any need to import this module ever, and this documentation does not cover how to use these classes in an isolated way.

InputState

This class and its contained classes should not be instantiated directly in an application, but instead the ins argument provided by .think(ins, delta_ms) method of the Application instance should be used.

class st3m.input.InputState
captouch: captouch.CaptouchState

The state of the captouch surface, see documentation of the captouch module.

buttons: InputButtonState

The state of the shoulder buttons.

imu: IMUState

The state of the inertial measurement unit.

temperature: float

The internal ambient temperature in degree Celsius.

battery_voltage: float

The battery voltage in Volts.

pressure: float

The ambient pressure in Pascal. This is raw unfiltered data and very jittery. You might want to apply some sort of filtering for most typical applications.

class st3m.input.InputButtonState
NOT_PRESSED: int = 0
PRESSED_LEFT: int = -1
PRESSED_RIGHT: int = 1
PRESSED_DOWN: int = 2
app: int

State of the app shoulder button. May be any *PRESSED* constant.

os: int

State of the OS shoulder button. May be any *PRESSED* constant.

You probably don’t wanna use this without engaging st3m.application.Application.override_os_button_back and/or st3m.application.Application.override_os_button_volume to avoid clashes with the operating system’s use of this button. Please check out the recommended override restrictions in their respective documentations.

app_is_left: bool

Indicates whether the app button is the left shoulder button.

For context: While it is possible to operate flow3r by holding it in both hands not unlike a game controller, this restricts access to the captouch surface. For many instruments, more speed and flexibility is needed, so it is recommended to hold flow3r in one hand and play the captouch surface with the other. In this configuration, one shoulder button is easily reachable by the holding hand’s index finger while the other is far away and can only be operated by the floating hand.

Since this results in a completely different user experience depending on the handedness of the user (being able to control OS functionality with the holding hand vs. being able to control app functionality with the holding hand) we decided to leave it up to the user to flip them in the global settings.

Since this also affects where hints might be placed on the display etc., making this feature hidden from application developers would result in a second-class experience for one of the user groups. In order to prevent a default, we use the abstract app and os terms instead of left and right.

class st3m.input.IMUState
acc: Tuple[float, float, float]

Acceleration in m/s^2. Includes gravity. See image below for mapping indices to axis.

gyro: Tuple[float, float, float]

Angular velocity in deg/s. See image below for mapping indices to axis.

pressure

Duplicate of InputState.pressure

The axis of the IMU are arranged as follows, with the x-axis pointing from the center of the badge to the USB-C port and the z-axis pointing upwards through the display. Both acc and gyro tuples are arranged as (x,y,z). Image taken from the BMI270 datasheet.

../../_images/imu_axis.png

InputController

The InputController class holds edges of all button-like inputs, i.e. the shoulder buttons and captouch petals. Similar to InputState it is not typically initialized by the user but rather provided in the .input attribute of the Application instance. The structure of these classes are not dissimilar, but there are some important differences to account for:

class App(st3m.application.Application):
    def think(self, ins, delta_ms):
        # mandatory for updating self.input
        super().think(self, ins, delta_ms)

        # True if the petal is currently being pressed or not
        petal_pressed = ins.captouch.petal[0].pressed
        # True if the petal has just switched from not pressed to pressed
        rising_edge_of_petal_pressed = self.input.captouch.petal[0].whole.pressed

        # True if the shoulder button is pressed down
        button_pressed = ins.buttons.app == ins.buttons.DOWN
        # True if the shoulder button has just switched from not pressed to pressed
        rising_edge_of_button_pressed = self.input.buttons.app.middle.pressed

All end nodes of InputController are Pressable objects:

class st3m.input.Pressable
pressed: bool

True if an object hadn’t been pressed in the cycle before but now is.

Note that this attribute follows a different naming convention than captouch.CaptouchPetalState.pressed, which corresponds more to the .down attribute (but not quite). For the purposes of documentation this name is an exception to the general rule that “pressed” means “currently being touched”, leading to somewhat silly sentences as in .down. Sorry about that, fixing this naming inconsistency is somewhat difficult.

repeated: bool

True if an object has been pressed for sufficiently long to trigger a key repeat, see .repeat_enable().

released: bool

True if an object had been pressed in the cycle before but now isn’t.

Note: .pressed and .released do not need to come in pairs. When entering an application, any Pressable will check if it is pressed and assume that this interaction was used to enter the application, therefore pretending that it isn’t pressed right now. If the button was held the last time the application ran, that release event it will be supressed. Equally, exiting an application while the button is held does not generate a release event, so any process that starts on .pressed and ends on .released might not be terminated when closing an application.

down: bool

True if an object is being pressed and .pressed is False.

up: bool

True if an object is not being pressed and .released is False.

repeat_enable(first: int = 400, subsequent: int = 200) None:

Enable key repeat functionality. Arguments are amount to wait in ms until first repeat is emitted and until subsequent repeats are emitted.

Repeat is enabled by default on Pressables.

repeat_disable(self) None:

Turns off key repeat functionality.

The basic idea of Pressable is that all state attributes (i.e., .pressed, .repeated, .released, .down, .up) are mutually exclusive. A single exception to that rule is that .down and .repeated may be true at the same time since repeats are enabled by default which causes flickering in .down which may be unexpected by many users.

The full structure of InputController is as follows:

class st3m.input.InputController
captouch.petals: list(PetalState)

A container for the edges of the captouch surface.

buttons.app: TriSwitchState

A container for the edges of the app button.

buttons.os: TriSwitchState

A container for the edges of the OS button.

You probably don’t wanna use this without engaging st3m.application.Application.override_os_button_back and/or st3m.application.Application.override_os_button_volume to avoid clashes with the operating system’s use of this button. Please check out the recommended override restrictions in their respective documentations.

class st3m.input.TriSwitchState
left: Pressable
middle: Pressable
right: Pressable
class st3m.input.PetalState
whole: Pressable