diff --git a/components/micropython/usermodule/mp_sys_buttons.c b/components/micropython/usermodule/mp_sys_buttons.c index 76a87dc03b8ff083dea48e2750c19ec0ef54eb85..0db6816a22bd851180bb286284f8bc24e1e95cce 100644 --- a/components/micropython/usermodule/mp_sys_buttons.c +++ b/components/micropython/usermodule/mp_sys_buttons.c @@ -18,21 +18,35 @@ #include "mp_uctx.h" -STATIC mp_obj_t mp_get_left() { - return mp_obj_new_int(st3m_io_left_button_get()); +STATIC mp_obj_t mp_get_app(void) { + return mp_obj_new_int(st3m_io_app_button_get()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_left_obj, mp_get_left); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_app_obj, mp_get_app); -STATIC mp_obj_t mp_get_right() { - return mp_obj_new_int(st3m_io_right_button_get()); +STATIC mp_obj_t mp_get_os(void) { + return mp_obj_new_int(st3m_io_os_button_get()); } -STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_right_obj, mp_get_right); +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_get_os_obj, mp_get_os); + +STATIC mp_obj_t mp_configure(mp_obj_t left_in) { + bool left = mp_obj_is_true(left_in); + st3m_io_app_button_configure(left); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_1(mp_configure_obj, mp_configure); + +STATIC mp_obj_t mp_app_is_left(void) { + return mp_obj_new_bool(st3m_io_app_button_is_left()); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_0(mp_app_is_left_obj, mp_app_is_left); STATIC const mp_rom_map_elem_t mp_module_sys_buttons_globals_table[] = { { MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_sys_buttons) }, - { MP_ROM_QSTR(MP_QSTR_get_left), MP_ROM_PTR(&mp_get_left_obj) }, - { MP_ROM_QSTR(MP_QSTR_get_right), MP_ROM_PTR(&mp_get_right_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_app), MP_ROM_PTR(&mp_get_app_obj) }, + { MP_ROM_QSTR(MP_QSTR_get_os), MP_ROM_PTR(&mp_get_os_obj) }, + { MP_ROM_QSTR(MP_QSTR_configure), MP_ROM_PTR(&mp_configure_obj) }, + { MP_ROM_QSTR(MP_QSTR_app_is_left), MP_ROM_PTR(&mp_app_is_left_obj) }, { MP_ROM_QSTR(MP_QSTR_PRESSED_LEFT), MP_ROM_INT(st3m_tripos_left) }, { MP_ROM_QSTR(MP_QSTR_PRESSED_RIGHT), MP_ROM_INT(st3m_tripos_right) }, diff --git a/components/st3m/st3m_io.c b/components/st3m/st3m_io.c index ed82fbb6115ceb63c88464bed1856fe9d4e88120..e9c7a62a257584f91898698a12830bc8579760af 100644 --- a/components/st3m/st3m_io.c +++ b/components/st3m/st3m_io.c @@ -5,12 +5,16 @@ static const char *TAG = "st3m-io"; #include "esp_err.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" +#include "freertos/semphr.h" #include "freertos/task.h" #include "flow3r_bsp.h" #include "flow3r_bsp_i2c.h" #include "st3m_audio.h" +static bool _app_button_left = true; +static SemaphoreHandle_t _mu = NULL; + static void _update_button_state() { esp_err_t ret = flow3r_bsp_spio_update(); if (ret != ESP_OK) { @@ -18,23 +22,35 @@ static void _update_button_state() { } } -void init_buttons() { - esp_err_t ret = flow3r_bsp_spio_init(); - if (ret != ESP_OK) { - ESP_LOGE(TAG, "init failed: %s", esp_err_to_name(ret)); - for (;;) { - } - } +bool st3m_io_charger_state_get() { return flow3r_bsp_spio_charger_state_get(); } + +void st3m_io_app_button_configure(bool left) { + xSemaphoreTake(_mu, portMAX_DELAY); + _app_button_left = left; + xSemaphoreGive(_mu); } -bool st3m_io_charger_state_get() { return flow3r_bsp_spio_charger_state_get(); } +bool st3m_io_app_button_is_left(void) { + xSemaphoreTake(_mu, portMAX_DELAY); + bool res = _app_button_left; + xSemaphoreGive(_mu); + return res; +} -st3m_tripos st3m_io_left_button_get() { - return flow3r_bsp_spio_left_button_get(); +st3m_tripos st3m_io_app_button_get() { + if (st3m_io_app_button_is_left()) { + return flow3r_bsp_spio_left_button_get(); + } else { + return flow3r_bsp_spio_right_button_get(); + } } -st3m_tripos st3m_io_right_button_get() { - return flow3r_bsp_spio_right_button_get(); +st3m_tripos st3m_io_os_button_get() { + if (st3m_io_app_button_is_left()) { + return flow3r_bsp_spio_right_button_get(); + } else { + return flow3r_bsp_spio_left_button_get(); + } } static uint8_t badge_link_enabled = 0; @@ -102,6 +118,10 @@ static void _task(void *data) { } void st3m_io_init(void) { + assert(_mu == NULL); + _mu = xSemaphoreCreateMutex(); + assert(_mu != NULL); + esp_err_t ret = flow3r_bsp_spio_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "spio init failed: %s", esp_err_to_name(ret)); diff --git a/components/st3m/st3m_io.h b/components/st3m/st3m_io.h index 5cf59bf15b4d053e79671aa5bcd1bb4b5956c189..9a250a0807823a1e3a1e617ee9dd878fad910f36 100644 --- a/components/st3m/st3m_io.h +++ b/components/st3m/st3m_io.h @@ -19,11 +19,20 @@ typedef enum { st3m_tripos_right = 1, } st3m_tripos; -/* Read the state of the left/right button. - * This ignores user preference and should be used only with good reason. +/* Configure whether the app button is on the left (default) or on the right. */ -st3m_tripos st3m_io_left_button_get(); -st3m_tripos st3m_io_right_button_get(); +void st3m_io_app_button_configure(bool left); + +/* Returns true if the app button is on the left (default), false otherwise. + */ +bool st3m_io_app_button_is_left(void); + +/* Read the state of the application and OS buttons. By default, the application + * button is on the left and the OS button is on the right. However, the user + * can change that preference - see st3m_io_app_button_configure. + */ +st3m_tripos st3m_io_app_button_get(); +st3m_tripos st3m_io_os_button_get(); #define BADGE_LINK_PIN_MASK_LINE_IN_TIP 0b0001 #define BADGE_LINK_PIN_MASK_LINE_IN_RING 0b0010 @@ -61,4 +70,4 @@ uint8_t st3m_io_badge_link_enable(uint8_t pin_mask); /* Returns true if the battery is currently being charged. */ -bool st3m_io_charger_state_get(); +bool st3m_io_charger_state_get(); \ No newline at end of file diff --git a/components/st3m/st3m_mode.c b/components/st3m/st3m_mode.c index 2b226128ff5847c9877367dff11bc51d66c2f692..ed703bf0a3b578d3406c5b39b2ec3edc43319803 100644 --- a/components/st3m/st3m_mode.c +++ b/components/st3m/st3m_mode.c @@ -186,7 +186,7 @@ static void _task(void *arg) { st3m_mode_update_display(&restartable); if (restartable) { - st3m_tripos tp = st3m_io_right_button_get(); + st3m_tripos tp = st3m_io_os_button_get(); if (tp == st3m_tripos_mid) { st3m_gfx_textview_t tv = { .title = "Restarting...", diff --git a/python_payload/mypystubs/sys_buttons.pyi b/python_payload/mypystubs/sys_buttons.pyi index 4b3346a2106c0ceac5d9fa6744dbe5826e7024e1..047ba764c48a5390f8048816dac57a1f7ffd2c94 100644 --- a/python_payload/mypystubs/sys_buttons.pyi +++ b/python_payload/mypystubs/sys_buttons.pyi @@ -1,5 +1,7 @@ -def get_left() -> int: ... -def get_right() -> int: ... +def get_app() -> int: ... +def get_os() -> int: ... +def configure(left: bool) -> None: ... +def app_is_left() -> bool: ... PRESSED_LEFT: int PRESSED_RIGHT: int diff --git a/python_payload/st3m/input.py b/python_payload/st3m/input.py index 27db554c36de0d75b132d1f553cf858a26bfaeb5..8a6faaf82c15a4559c7b9c7818d4edb60ec80b75 100644 --- a/python_payload/st3m/input.py +++ b/python_payload/st3m/input.py @@ -58,17 +58,10 @@ class InputButtonState: PRESSED_DOWN = sys_buttons.PRESSED_DOWN NOT_PRESSED = sys_buttons.NOT_PRESSED - def __init__(self, left: int, right: int, swapped: bool): - app = left - os = right - if swapped: - app, os = os, app - + def __init__(self, app: int, os: int, app_is_left: bool): self.app = app self.os = os - self._left = left - self._right = right - self.app_is_left = not swapped + self.app_is_left = app_is_left class InputState: @@ -95,15 +88,16 @@ class InputState: self.battery_voltage = battery_voltage @classmethod - def gather(cls, swapped_buttons: bool = False) -> "InputState": + def gather(cls) -> "InputState": """ Build InputState from current hardware state. Should only be used by the Reactor. """ cts = captouch.read() - left = sys_buttons.get_left() - right = sys_buttons.get_right() - buttons = InputButtonState(left, right, swapped_buttons) + app = sys_buttons.get_app() + os = sys_buttons.get_os() + app_is_left = sys_buttons.app_is_left() + buttons = InputButtonState(app, os, app_is_left) acc = imu.acc_read() gyro = imu.gyro_read() diff --git a/python_payload/st3m/reactor.py b/python_payload/st3m/reactor.py index 505c6096cc4730705cad17c6fb3de924434efe7b..55bc1108676be2b90362c65b1842d9bf843198f6 100644 --- a/python_payload/st3m/reactor.py +++ b/python_payload/st3m/reactor.py @@ -84,7 +84,6 @@ class Reactor: "_ctx", "_ts", "_last_ctx_get", - "_swap_buttons", "stats", ) @@ -95,7 +94,6 @@ class Reactor: self._last_tick: Optional[int] = None self._last_ctx_get: Optional[int] = None self._ctx: Optional[Context] = None - self._swap_buttons = False self.stats = ReactorStats() def set_top(self, top: Responder) -> None: @@ -114,9 +112,6 @@ class Reactor: while True: self._run_once() - def set_buttons_swapped(self, swapped: bool) -> None: - self._swap_buttons = swapped - def _run_once(self) -> None: start = time.ticks_ms() deadline = start + self._tickrate_ms @@ -143,7 +138,7 @@ class Reactor: self._ts += delta - hr = InputState.gather(self._swap_buttons) + hr = InputState.gather() # Think! self._top.think(hr, delta) diff --git a/python_payload/st3m/run.py b/python_payload/st3m/run.py index fcd663769af431e5aab3a429ece370483cb726a1..6ba18204a85b73a65785bd87dd441b7e033460df 100644 --- a/python_payload/st3m/run.py +++ b/python_payload/st3m/run.py @@ -20,7 +20,7 @@ from st3m.application import ( from st3m.about import About from st3m import settings, logging, processors, wifi -import captouch, audio, leds, gc +import captouch, audio, leds, gc, sys_buttons import os import machine @@ -37,7 +37,8 @@ def _make_reactor() -> Reactor: reactor = Reactor() def _onoff_button_swap_update() -> None: - reactor.set_buttons_swapped(settings.onoff_button_swap.value) + left = not settings.onoff_button_swap.value + sys_buttons.configure(left) settings.onoff_button_swap.subscribe(_onoff_button_swap_update) _onoff_button_swap_update() diff --git a/sim/fakes/sys_buttons.py b/sim/fakes/sys_buttons.py index 46e4aef28dc6d13f5490367c4459ef99d57d3701..0d340af7dfe62889f5e36add86e1081ed9fc8068 100644 --- a/sim/fakes/sys_buttons.py +++ b/sim/fakes/sys_buttons.py @@ -1,12 +1,29 @@ import _sim +_app_is_left = True -def get_left(): - return _sim.get_button_state(1) +def get_app(): + if _app_is_left: + return _sim.get_button_state(1) + else: + return _sim.get_button_state(0) -def get_right(): - return _sim.get_button_state(0) + +def get_os(): + if _app_is_left: + return _sim.get_button_state(0) + else: + return _sim.get_button_state(1) + + +def app_is_left(): + return _app_is_left + + +def configure(left): + global _app_is_left + _app_is_left = left PRESSED_LEFT = -1