diff --git a/epicardium/epicardium.h b/epicardium/epicardium.h index 36ea64b818dc32c39b071a97305d36d5362b85bf..ce254cb6678c75c0af949dad1f748151b9b1d021 100644 --- a/epicardium/epicardium.h +++ b/epicardium/epicardium.h @@ -88,6 +88,8 @@ typedef _Bool bool; #define API_LIGHT_SENSOR_RUN 0x80 #define API_LIGHT_SENSOR_GET 0x81 #define API_LIGHT_SENSOR_STOP 0x82 + +#define API_BUTTONS_READ 0x90 /* clang-format on */ typedef uint32_t api_int_id_t; @@ -274,6 +276,68 @@ API_ISR(EPIC_INT_UART_RX, epic_isr_uart_rx); */ API_ISR(EPIC_INT_CTRL_C, epic_isr_ctrl_c); +/** + * Buttons + * ======= + * + */ + +/** Button IDs */ +enum epic_button { + /** ``1``, Bottom left button (bit 0). */ + BUTTON_LEFT_BOTTOM = 1, + /** ``2``, Bottom right button (bit 1). */ + BUTTON_RIGHT_BOTTOM = 2, + /** ``4``, Top right button (bit 2). */ + BUTTON_RIGHT_TOP = 4, + /** ``8``, Top left (power) button (bit 3). */ + BUTTON_LEFT_TOP = 8, + /** ``8``, Top left (power) button (bit 3). */ + BUTTON_RESET = 8, +}; + +/** + * Read buttons. + * + * :c:func:`epic_buttons_read` will read all buttons specified in ``mask`` and + * return set bits for each button which was reported as pressed. + * + * .. note:: + * + * The reset button cannot be unmapped from reset functionality. So, while + * you can read it, it cannot be used for app control. + * + * **Example**: + * + * .. code-block:: cpp + * + * #include "epicardium.h" + * + * uint8_t pressed = epic_buttons_read(BUTTON_LEFT_BOTTOM | BUTTON_RIGHT_BOTTOM); + * + * if (pressed & BUTTON_LEFT_BOTTOM) { + * // Bottom left button is pressed + * } + * + * if (pressed & BUTTON_RIGHT_BOTTOM) { + * // Bottom right button is pressed + * } + * + * :param uint8_t mask: Mask of buttons to read. The 4 LSBs correspond to the 4 + * buttons: + * + * ===== ========= ============ =========== + * ``3`` ``2`` ``1`` ``0`` + * ----- --------- ------------ ----------- + * Reset Right Top Right Bottom Left Bottom + * ===== ========= ============ =========== + * + * Use the values defined in :c:type:`epic_button` for masking, as shown in + * the example above. + * :return: Returns nonzero value if unmasked buttons are pushed. + */ +API(API_BUTTONS_READ, uint8_t epic_buttons_read(uint8_t mask)); + /** * LEDs * ==== diff --git a/epicardium/modules/buttons.c b/epicardium/modules/buttons.c new file mode 100644 index 0000000000000000000000000000000000000000..e2cb20d39f053a8123a4f730986403dd3dd74493 --- /dev/null +++ b/epicardium/modules/buttons.c @@ -0,0 +1,32 @@ +#include "epicardium.h" + +#include "portexpander.h" +#include "MAX77650-Arduino-Library.h" + +#include <stdint.h> + +static const uint8_t pin_mask[] = { + [BUTTON_LEFT_BOTTOM] = 1 << 5, + [BUTTON_RIGHT_BOTTOM] = 1 << 3, + [BUTTON_RIGHT_TOP] = 1 << 6, +}; + +uint8_t epic_buttons_read(uint8_t mask) +{ + uint8_t ret = 0; + if (portexpander_detected() && (mask & 0x3)) { + uint8_t pin_status = ~portexpander_get(); + + for (uint8_t m = 1; m < 0x8; m <<= 1) { + if (mask & m && pin_status & pin_mask[m]) { + ret |= m; + } + } + } + + if (mask & BUTTON_RESET && MAX77650_getDebounceStatusnEN0()) { + ret |= BUTTON_RESET; + } + + return ret; +} diff --git a/epicardium/modules/meson.build b/epicardium/modules/meson.build index d7c9f40b90fe174bc81cba76cd928a210a4c2b75..3389a40911849b75cbd06ca8d0de7ebef785e601 100644 --- a/epicardium/modules/meson.build +++ b/epicardium/modules/meson.build @@ -1,4 +1,5 @@ module_sources = files( + 'buttons.c', 'dispatcher.c', 'display.c', 'fileops.c',