Ver código fonte

[FL-1161] Input bug fixes and cleanup (#416)

* Input: start/stop timers only from the input thread, adjust long/short/repeat timings, improve timer routines reliability.
あく 4 anos atrás
pai
commit
8ada9b817b
2 arquivos alterados com 41 adições e 23 exclusões
  1. 35 19
      applications/input/input.c
  2. 6 4
      applications/input/input_i.h

+ 35 - 19
applications/input/input.c

@@ -1,5 +1,4 @@
 #include "input_i.h"
 #include "input_i.h"
-#include <m-string.h>
 
 
 #define GPIO_Read(input_pin)                                                    \
 #define GPIO_Read(input_pin)                                                    \
     (HAL_GPIO_ReadPin((GPIO_TypeDef*)input_pin.pin->port, input_pin.pin->pin) ^ \
     (HAL_GPIO_ReadPin((GPIO_TypeDef*)input_pin.pin->port, input_pin.pin->pin) ^ \
@@ -7,19 +6,33 @@
 
 
 static Input* input = NULL;
 static Input* input = NULL;
 
 
+inline static void input_timer_start(osTimerId_t timer_id, uint32_t ticks) {
+    TimerHandle_t hTimer = (TimerHandle_t)timer_id;
+    furi_check(xTimerChangePeriod(hTimer, ticks, portMAX_DELAY) == pdPASS);
+}
+
+inline static void input_timer_stop(osTimerId_t timer_id) {
+    TimerHandle_t hTimer = (TimerHandle_t)timer_id;
+    furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS);
+    // xTimerStop is not actually stopping timer,
+    // Instead it places stop event into timer queue
+    // This code ensures that timer is stopped
+    while(xTimerIsTimerActive(hTimer) == pdTRUE) osDelay(1);
+}
+
 void input_press_timer_callback(void* arg) {
 void input_press_timer_callback(void* arg) {
     InputPinState* input_pin = arg;
     InputPinState* input_pin = arg;
     InputEvent event;
     InputEvent event;
     event.key = input_pin->pin->key;
     event.key = input_pin->pin->key;
-    if(!input_pin->repeat_event) {
+    input_pin->press_counter++;
+    if(input_pin->press_counter == INPUT_LONG_PRESS_COUNTS) {
         event.type = InputTypeLong;
         event.type = InputTypeLong;
         notify_pubsub(&input->event_pubsub, &event);
         notify_pubsub(&input->event_pubsub, &event);
-        input_pin->repeat_event = true;
-    } else {
+    } else if(input_pin->press_counter > INPUT_LONG_PRESS_COUNTS) {
+        input_pin->press_counter--;
         event.type = InputTypeRepeat;
         event.type = InputTypeRepeat;
         notify_pubsub(&input->event_pubsub, &event);
         notify_pubsub(&input->event_pubsub, &event);
     }
     }
-    osTimerStart(input_pin->press_timer, INPUT_REPEATE_PRESS_TICKS);
 }
 }
 
 
 void input_isr(void* _pin, void* _ctx) {
 void input_isr(void* _pin, void* _ctx) {
@@ -34,7 +47,7 @@ void input_cli_send(string_t args, void* context) {
     string_init(key_name);
     string_init(key_name);
     size_t ws = string_search_char(args, ' ');
     size_t ws = string_search_char(args, ' ');
     if(ws == STRING_FAILURE) {
     if(ws == STRING_FAILURE) {
-        printf("Wrong input");
+        printf("Invalid arguments. Use `input_send KEY TYPE`.");
         string_clear(key_name);
         string_clear(key_name);
         return;
         return;
     } else {
     } else {
@@ -56,7 +69,7 @@ void input_cli_send(string_t args, void* context) {
     } else if(!string_cmp(key_name, "back")) {
     } else if(!string_cmp(key_name, "back")) {
         event.key = InputKeyBack;
         event.key = InputKeyBack;
     } else {
     } else {
-        printf("Wrong argument");
+        printf("Invalid key name. Valid keys: `up`, `down`, `left`, `right`, `back`, `ok`.");
         string_clear(key_name);
         string_clear(key_name);
         return;
         return;
     }
     }
@@ -71,7 +84,7 @@ void input_cli_send(string_t args, void* context) {
     } else if(!string_cmp(args, "long")) {
     } else if(!string_cmp(args, "long")) {
         event.type = InputTypeLong;
         event.type = InputTypeLong;
     } else {
     } else {
-        printf("Wrong argument");
+        printf("Ivalid type. Valid types: `press`, `release`, `short`, `long`.");
         return;
         return;
     }
     }
     // Publish input event
     // Publish input event
@@ -97,10 +110,10 @@ int32_t input_task() {
     for(size_t i = 0; i < pin_count; i++) {
     for(size_t i = 0; i < pin_count; i++) {
         input->pin_states[i].pin = &input_pins[i];
         input->pin_states[i].pin = &input_pins[i];
         input->pin_states[i].state = GPIO_Read(input->pin_states[i]);
         input->pin_states[i].state = GPIO_Read(input->pin_states[i]);
-        input->pin_states[i].repeat_event = false;
         input->pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF;
         input->pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF;
         input->pin_states[i].press_timer =
         input->pin_states[i].press_timer =
-            osTimerNew(input_press_timer_callback, osTimerOnce, &input->pin_states[i], NULL);
+            osTimerNew(input_press_timer_callback, osTimerPeriodic, &input->pin_states[i], NULL);
+        input->pin_states[i].press_counter = 0;
     }
     }
 
 
     while(1) {
     while(1) {
@@ -113,21 +126,24 @@ int32_t input_task() {
                 input->pin_states[i].debounce += (state ? 1 : -1);
                 input->pin_states[i].debounce += (state ? 1 : -1);
             } else if(input->pin_states[i].state != state) {
             } else if(input->pin_states[i].state != state) {
                 input->pin_states[i].state = state;
                 input->pin_states[i].state = state;
+
                 // Common state info
                 // Common state info
                 InputEvent event;
                 InputEvent event;
-                event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease;
                 event.key = input->pin_states[i].pin->key;
                 event.key = input->pin_states[i].pin->key;
+                event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease;
                 // Send Press/Release event
                 // Send Press/Release event
                 notify_pubsub(&input->event_pubsub, &event);
                 notify_pubsub(&input->event_pubsub, &event);
-                // Short/Long press logic
+
+                // Short / Long / Repeat timer routine
                 if(state) {
                 if(state) {
-                    osTimerStart(input->pin_states[i].press_timer, INPUT_LONG_PRESS_TICKS);
-                } else if(input->pin_states[i].repeat_event) {
-                    osTimerStop(input->pin_states[i].press_timer);
-                    input->pin_states[i].repeat_event = false;
-                } else if(osTimerStop(input->pin_states[i].press_timer) == osOK) {
-                    event.type = InputTypeShort;
-                    notify_pubsub(&input->event_pubsub, &event);
+                    input_timer_start(input->pin_states[i].press_timer, INPUT_PRESS_TICKS);
+                } else {
+                    input_timer_stop(input->pin_states[i].press_timer);
+                    if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) {
+                        event.type = InputTypeShort;
+                        notify_pubsub(&input->event_pubsub, &event);
+                    }
+                    input->pin_states[i].press_counter = 0;
                 }
                 }
             }
             }
         }
         }

+ 6 - 4
applications/input/input_i.h

@@ -1,16 +1,18 @@
 #pragma once
 #pragma once
 
 
 #include "input.h"
 #include "input.h"
-
+#include <FreeRTOS.h>
+#include <timers.h>
 #include <stdbool.h>
 #include <stdbool.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <furi.h>
 #include <furi.h>
 #include <cli/cli.h>
 #include <cli/cli.h>
+#include <m-string.h>
 
 
 #define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2)
 #define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2)
-#define INPUT_LONG_PRESS_TICKS 2048
-#define INPUT_REPEATE_PRESS_TICKS 256
+#define INPUT_PRESS_TICKS 200
+#define INPUT_LONG_PRESS_COUNTS 4
 #define INPUT_THREAD_FLAG_ISR 0x00000001
 #define INPUT_THREAD_FLAG_ISR 0x00000001
 
 
 /* Input pin state */
 /* Input pin state */
@@ -18,9 +20,9 @@ typedef struct {
     const InputPin* pin;
     const InputPin* pin;
     // State
     // State
     volatile bool state;
     volatile bool state;
-    volatile bool repeat_event;
     volatile uint8_t debounce;
     volatile uint8_t debounce;
     volatile osTimerId_t press_timer;
     volatile osTimerId_t press_timer;
+    volatile uint8_t press_counter;
 } InputPinState;
 } InputPinState;
 
 
 /* Input state */
 /* Input state */