diff --git a/firmware/application/src/app_main.c b/firmware/application/src/app_main.c index ec240b0..1b0eb0d 100644 --- a/firmware/application/src/app_main.c +++ b/firmware/application/src/app_main.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "nordic_common.h" #include "nrf.h" @@ -41,9 +42,17 @@ NRF_LOG_MODULE_REGISTER(); // Defining soft timers APP_TIMER_DEF(m_button_check_timer); // Timer for button debounce + +static uint32_t m_last_btn_press = 0; + +static bool m_is_btn_long_press = false; + static bool m_is_b_btn_press = false; static bool m_is_a_btn_press = false; +static bool m_is_b_btn_release = false; +static bool m_is_a_btn_release = false; + // cpu reset reason static uint32_t m_reset_source; static uint32_t m_gpregret_val; @@ -152,12 +161,41 @@ static void timer_button_event_handle(void *arg) { if (settings_get_button_press_config('b') != SettingsButtonDisable) { NRF_LOG_INFO("BUTTON_LEFT"); // Button B? m_is_b_btn_press = true; + m_last_btn_press = app_timer_cnt_get(); } } if (pin == BUTTON_2) { if (settings_get_button_press_config('a') != SettingsButtonDisable) { NRF_LOG_INFO("BUTTON_RIGHT"); // Button A? m_is_a_btn_press = true; + m_last_btn_press = app_timer_cnt_get(); + } + } + } + + if (nrf_gpio_pin_read(pin) == 0) { + uint32_t now = app_timer_cnt_get(); + uint32_t ticks = app_timer_cnt_diff_compute(now, m_last_btn_press); + + uint32_t time = ticks * ((APP_TIMER_CONFIG_RTC_FREQUENCY + 1 ) * 1000 ) / APP_TIMER_CLOCK_FREQ; + + bool is_long_press = time > 1000; + + if (pin == BUTTON_1 && m_is_b_btn_press == true) { + // If button is disable, we can didn't dispatch key event. + if (settings_get_button_press_config('b') != SettingsButtonDisable) { + NRF_LOG_INFO("BUTTON_LEFT_RELEASE"); // Button B? + m_is_b_btn_release = true; + m_is_b_btn_press = false; + m_is_btn_long_press = is_long_press; + } + } + if (pin == BUTTON_2 && m_is_a_btn_press == true) { + if (settings_get_button_press_config('a') != SettingsButtonDisable) { + NRF_LOG_INFO("BUTTON_RIGHT_RELEASE"); // Button A? + m_is_a_btn_release = true; + m_is_a_btn_press = false; + m_is_btn_long_press = is_long_press; } } } @@ -173,7 +211,7 @@ static void button_init(void) { APP_ERROR_CHECK(err_code); // Configure SENSE mode, select false for sense configuration - nrf_drv_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_LOTOHI(false); + nrf_drv_gpiote_in_config_t in_config = NRFX_GPIOTE_CONFIG_IN_SENSE_TOGGLE(false); in_config.pull = NRF_GPIO_PIN_PULLDOWN; // Pulldown // Configure key binding POTR @@ -635,14 +673,22 @@ static void run_button_function_by_settings(settings_button_function_t sbf) { extern bool g_usb_led_marquee_enable; static void button_press_process(void) { // Make sure that one of the AB buttons has a click event - if (m_is_b_btn_press || m_is_a_btn_press) { - if (m_is_a_btn_press) { - run_button_function_by_settings(settings_get_button_press_config('a')); - m_is_a_btn_press = false; + if (m_is_b_btn_release || m_is_a_btn_release) { + if (m_is_a_btn_release) { + if(!m_is_btn_long_press) { + run_button_function_by_settings(settings_get_button_press_config('a')); + } else { + run_button_function_by_settings(settings_get_button_press_config('c')); + } + m_is_a_btn_release = false; } - if (m_is_b_btn_press) { - run_button_function_by_settings(settings_get_button_press_config('b')); - m_is_b_btn_press = false; + if (m_is_b_btn_release) { + if(!m_is_btn_long_press) { + run_button_function_by_settings(settings_get_button_press_config('b')); + } else { + run_button_function_by_settings(settings_get_button_press_config('d')); + } + m_is_b_btn_release = false; } // Disable led marquee for usb at button pressed. g_usb_led_marquee_enable = false; diff --git a/firmware/application/src/settings.c b/firmware/application/src/settings.c index 18bbe15..5879f68 100644 --- a/firmware/application/src/settings.c +++ b/firmware/application/src/settings.c @@ -51,6 +51,10 @@ void settings_migrate(void) { settings_update_version_for_config(); break; + case 2: + config.button_a_long_press = SettingsButtonCloneIcUid; + config.button_b_long_press = SettingsButtonCloneIcUid; + /* * When needed migrations can be implemented like this: * @@ -167,6 +171,31 @@ uint8_t settings_get_button_press_config(char which) { return SettingsButtonDisable; } +/** + * @brief Get the long button press config + * + * @param which 'a' or 'b' + * @return uint8_t @link{ settings_button_function_t } + */ +uint8_t settings_get_long_button_press_config(char which) { + switch (which) { + case 'a': + case 'A': + return config.button_a_long_press; + + case 'b': + case 'B': + return config.button_b_long_press; + + default: + // can't to here. + APP_ERROR_CHECK_BOOL(false); + break; + } + // can't to here. + return SettingsButtonDisable; +} + /** * @brief Set the button press config * @@ -191,3 +220,28 @@ void settings_set_button_press_config(char which, uint8_t value) { break; } } + +/** + * @brief Set the long button press config + * + * @param which 'a' or 'b' + * @param value @link{ settings_button_function_t } + */ +void settings_set_long_button_press_config(char which, uint8_t value) { + switch (which) { + case 'a': + case 'A': + config.button_a_long_press = value; + break; + + case 'b': + case 'B': + config.button_b_long_press = value; + break; + + default: + // can't to here. + APP_ERROR_CHECK_BOOL(false); + break; + } +} diff --git a/firmware/application/src/settings.h b/firmware/application/src/settings.h index d1775f2..1713374 100644 --- a/firmware/application/src/settings.h +++ b/firmware/application/src/settings.h @@ -5,7 +5,7 @@ #include "utils.h" -#define SETTINGS_CURRENT_VERSION 2 +#define SETTINGS_CURRENT_VERSION 3 typedef enum { SettingsAnimationModeFull = 0U, @@ -36,6 +36,10 @@ typedef struct ALIGN_U32 { uint8_t button_a_press : 4; uint8_t button_b_press : 4; + // 1 byte + uint8_t button_a_long_press : 4; + uint8_t button_b_long_press : 4; + // 8 byte uint32_t reserved1; uint32_t reserved2; @@ -48,7 +52,9 @@ uint8_t settings_save_config(void); uint8_t settings_get_animation_config(void); void settings_set_animation_config(uint8_t value); uint8_t settings_get_button_press_config(char which); +uint8_t settings_get_long_button_press_config(char which); void settings_set_button_press_config(char which, uint8_t value); +void settings_set_long_button_press_config(char which, uint8_t value); bool is_settings_button_type_valid(char type); #endif