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.
- 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/orst3m.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
andos
terms instead ofleft
andright
.
- 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.
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
isFalse
.
- up: bool
True if an object is not being pressed and
.released
isFalse
.
- 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/orst3m.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.