diff --git a/applications/services/input/input.c b/applications/services/input/input.c index 216aa39b2e..a7610688e6 100644 --- a/applications/services/input/input.c +++ b/applications/services/input/input.c @@ -1,11 +1,36 @@ -#include "input_i.h" +#include "input.h" + +#include +#include +#include +#include +#include +#include + +#define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2) +#define INPUT_PRESS_TICKS 150 +#define INPUT_LONG_PRESS_COUNTS 2 +#define INPUT_THREAD_FLAG_ISR 0x00000001 + +/** Input pin state */ +typedef struct { + const InputPin* pin; + // State + volatile bool state; + volatile uint8_t debounce; + FuriTimer* press_timer; + FuriPubSub* event_pubsub; + volatile uint8_t press_counter; + volatile uint32_t counter; +} InputPinState; + +/** Input CLI command handler */ +void input_cli(Cli* cli, FuriString* args, void* context); // #define INPUT_DEBUG #define GPIO_Read(input_pin) (furi_hal_gpio_read(input_pin.pin->gpio) ^ (input_pin.pin->inverted)) -static Input* input = NULL; - void input_press_timer_callback(void* arg) { InputPinState* input_pin = arg; InputEvent event; @@ -15,17 +40,17 @@ void input_press_timer_callback(void* arg) { input_pin->press_counter++; if(input_pin->press_counter == INPUT_LONG_PRESS_COUNTS) { event.type = InputTypeLong; - furi_pubsub_publish(input->event_pubsub, &event); + furi_pubsub_publish(input_pin->event_pubsub, &event); } else if(input_pin->press_counter > INPUT_LONG_PRESS_COUNTS) { input_pin->press_counter--; event.type = InputTypeRepeat; - furi_pubsub_publish(input->event_pubsub, &event); + furi_pubsub_publish(input_pin->event_pubsub, &event); } } void input_isr(void* _ctx) { - UNUSED(_ctx); - furi_thread_flags_set(input->thread_id, INPUT_THREAD_FLAG_ISR); + FuriThreadId thread_id = (FuriThreadId)_ctx; + furi_thread_flags_set(thread_id, INPUT_THREAD_FLAG_ISR); } const char* input_get_key_name(InputKey key) { @@ -56,85 +81,83 @@ const char* input_get_type_name(InputType type) { int32_t input_srv(void* p) { UNUSED(p); - input = malloc(sizeof(Input)); - input->thread_id = furi_thread_get_current_id(); - input->event_pubsub = furi_pubsub_alloc(); - furi_record_create(RECORD_INPUT_EVENTS, input->event_pubsub); -#if INPUT_DEBUG + const FuriThreadId thread_id = furi_thread_get_current_id(); + FuriPubSub* event_pubsub = furi_pubsub_alloc(); + uint32_t counter = 1; + furi_record_create(RECORD_INPUT_EVENTS, event_pubsub); + +#ifdef INPUT_DEBUG furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeOutputPushPull); #endif #ifdef SRV_CLI - input->cli = furi_record_open(RECORD_CLI); - cli_add_command(input->cli, "input", CliCommandFlagParallelSafe, input_cli, input); + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command(cli, "input", CliCommandFlagParallelSafe, input_cli, event_pubsub); #endif - input->pin_states = malloc(input_pins_count * sizeof(InputPinState)); + InputPinState pin_states[input_pins_count]; for(size_t i = 0; i < input_pins_count; i++) { - furi_hal_gpio_add_int_callback(input_pins[i].gpio, input_isr, NULL); - input->pin_states[i].pin = &input_pins[i]; - input->pin_states[i].state = GPIO_Read(input->pin_states[i]); - input->pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF; - input->pin_states[i].press_timer = furi_timer_alloc( - input_press_timer_callback, FuriTimerTypePeriodic, &input->pin_states[i]); - input->pin_states[i].press_counter = 0; + furi_hal_gpio_add_int_callback(input_pins[i].gpio, input_isr, thread_id); + pin_states[i].pin = &input_pins[i]; + pin_states[i].state = GPIO_Read(pin_states[i]); + pin_states[i].debounce = INPUT_DEBOUNCE_TICKS_HALF; + pin_states[i].press_timer = + furi_timer_alloc(input_press_timer_callback, FuriTimerTypePeriodic, &pin_states[i]); + pin_states[i].event_pubsub = event_pubsub; + pin_states[i].press_counter = 0; } while(1) { bool is_changing = false; for(size_t i = 0; i < input_pins_count; i++) { - bool state = GPIO_Read(input->pin_states[i]); + bool state = GPIO_Read(pin_states[i]); if(state) { - if(input->pin_states[i].debounce < INPUT_DEBOUNCE_TICKS) - input->pin_states[i].debounce += 1; + if(pin_states[i].debounce < INPUT_DEBOUNCE_TICKS) pin_states[i].debounce += 1; } else { - if(input->pin_states[i].debounce > 0) input->pin_states[i].debounce -= 1; + if(pin_states[i].debounce > 0) pin_states[i].debounce -= 1; } - if(input->pin_states[i].debounce > 0 && - input->pin_states[i].debounce < INPUT_DEBOUNCE_TICKS) { + if(pin_states[i].debounce > 0 && pin_states[i].debounce < INPUT_DEBOUNCE_TICKS) { is_changing = true; - } else if(input->pin_states[i].state != state) { - input->pin_states[i].state = state; + } else if(pin_states[i].state != state) { + pin_states[i].state = state; // Common state info InputEvent event; event.sequence_source = INPUT_SEQUENCE_SOURCE_HARDWARE; - event.key = input->pin_states[i].pin->key; + event.key = pin_states[i].pin->key; // Short / Long / Repeat timer routine if(state) { - input->counter++; - input->pin_states[i].counter = input->counter; - event.sequence_counter = input->pin_states[i].counter; - furi_timer_start(input->pin_states[i].press_timer, INPUT_PRESS_TICKS); + pin_states[i].counter = counter++; + event.sequence_counter = pin_states[i].counter; + furi_timer_start(pin_states[i].press_timer, INPUT_PRESS_TICKS); } else { - event.sequence_counter = input->pin_states[i].counter; - furi_timer_stop(input->pin_states[i].press_timer); - while(furi_timer_is_running(input->pin_states[i].press_timer)) - furi_delay_tick(1); - if(input->pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) { + event.sequence_counter = pin_states[i].counter; + furi_timer_stop(pin_states[i].press_timer); + while(furi_timer_is_running(pin_states[i].press_timer)) furi_delay_tick(1); + if(pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) { event.type = InputTypeShort; - furi_pubsub_publish(input->event_pubsub, &event); + furi_pubsub_publish(event_pubsub, &event); } - input->pin_states[i].press_counter = 0; + pin_states[i].press_counter = 0; } // Send Press/Release event - event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease; - furi_pubsub_publish(input->event_pubsub, &event); + event.type = pin_states[i].state ? InputTypePress : InputTypeRelease; + furi_pubsub_publish(event_pubsub, &event); } } if(is_changing) { -#if INPUT_DEBUG +#ifdef INPUT_DEBUG furi_hal_gpio_write(&gpio_ext_pa4, 1); #endif furi_delay_tick(1); } else { -#if INPUT_DEBUG +#ifdef INPUT_DEBUG furi_hal_gpio_write(&gpio_ext_pa4, 0); #endif furi_thread_flags_wait(INPUT_THREAD_FLAG_ISR, FuriFlagWaitAny, FuriWaitForever); diff --git a/applications/services/input/input_cli.c b/applications/services/input/input_cli.c index 8aa04d6bdb..8e711c8954 100644 --- a/applications/services/input/input_cli.c +++ b/applications/services/input/input_cli.c @@ -1,4 +1,4 @@ -#include "input_i.h" +#include "input.h" #include #include @@ -19,11 +19,11 @@ static void input_cli_dump_events_callback(const void* value, void* ctx) { furi_message_queue_put(input_queue, value, FuriWaitForever); } -static void input_cli_dump(Cli* cli, FuriString* args, Input* input) { +static void input_cli_dump(Cli* cli, FuriString* args, FuriPubSub* event_pubsub) { UNUSED(args); FuriMessageQueue* input_queue = furi_message_queue_alloc(8, sizeof(InputEvent)); FuriPubSubSubscription* input_subscription = - furi_pubsub_subscribe(input->event_pubsub, input_cli_dump_events_callback, input_queue); + furi_pubsub_subscribe(event_pubsub, input_cli_dump_events_callback, input_queue); InputEvent input_event; printf("Press CTRL+C to stop\r\n"); @@ -36,7 +36,7 @@ static void input_cli_dump(Cli* cli, FuriString* args, Input* input) { } } - furi_pubsub_unsubscribe(input->event_pubsub, input_subscription); + furi_pubsub_unsubscribe(event_pubsub, input_subscription); furi_message_queue_free(input_queue); } @@ -47,7 +47,7 @@ static void input_cli_send_print_usage(void) { printf("\t\t \t - one of 'press', 'release', 'short', 'long'\r\n"); } -static void input_cli_send(Cli* cli, FuriString* args, Input* input) { +static void input_cli_send(Cli* cli, FuriString* args, FuriPubSub* event_pubsub) { UNUSED(cli); InputEvent event; FuriString* key_str; @@ -90,7 +90,7 @@ static void input_cli_send(Cli* cli, FuriString* args, Input* input) { } while(false); if(parsed) { //-V547 - furi_pubsub_publish(input->event_pubsub, &event); + furi_pubsub_publish(event_pubsub, &event); } else { input_cli_send_print_usage(); } @@ -100,7 +100,7 @@ static void input_cli_send(Cli* cli, FuriString* args, Input* input) { void input_cli(Cli* cli, FuriString* args, void* context) { furi_assert(cli); furi_assert(context); - Input* input = context; + FuriPubSub* event_pubsub = context; FuriString* cmd; cmd = furi_string_alloc(); @@ -110,11 +110,11 @@ void input_cli(Cli* cli, FuriString* args, void* context) { break; } if(furi_string_cmp_str(cmd, "dump") == 0) { - input_cli_dump(cli, args, input); + input_cli_dump(cli, args, event_pubsub); break; } if(furi_string_cmp_str(cmd, "send") == 0) { - input_cli_send(cli, args, input); + input_cli_send(cli, args, event_pubsub); break; } diff --git a/applications/services/input/input_i.h b/applications/services/input/input_i.h deleted file mode 100644 index 14d8b0735a..0000000000 --- a/applications/services/input/input_i.h +++ /dev/null @@ -1,48 +0,0 @@ -/** - * @file input_i.h - * Input: internal API - */ - -#pragma once - -#include "input.h" -#include -#include -#include -#include -#include -#include - -#define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2) -#define INPUT_PRESS_TICKS 150 -#define INPUT_LONG_PRESS_COUNTS 2 -#define INPUT_THREAD_FLAG_ISR 0x00000001 - -/** Input pin state */ -typedef struct { - const InputPin* pin; - // State - volatile bool state; - volatile uint8_t debounce; - FuriTimer* press_timer; - volatile uint8_t press_counter; - volatile uint32_t counter; -} InputPinState; - -/** Input state */ -typedef struct { - FuriThreadId thread_id; - FuriPubSub* event_pubsub; - InputPinState* pin_states; - Cli* cli; - volatile uint32_t counter; -} Input; - -/** Input press timer callback */ -void input_press_timer_callback(void* arg); - -/** Input interrupt handler */ -void input_isr(void* _ctx); - -/** Input CLI command handler */ -void input_cli(Cli* cli, FuriString* args, void* context);