diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c index c1b31339c..df49b3e0a 100644 --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -36,7 +36,7 @@ static void render_callback(Canvas* canvas, void* _ctx) { static void input_callback(InputEvent* input_event, void* _ctx) { AppLoaderState* ctx = (AppLoaderState*)_ctx; - if(input_event->state && input_event->input == InputBack) { + if(input_event->type == InputTypeShort && input_event->key == InputKeyBack) { osThreadTerminate(ctx->app_thread_id); view_port_enabled_set(ctx->view_port, false); api_hal_timebase_insomnia_exit(); diff --git a/applications/cc1101-workaround/cc1101-workaround.cpp b/applications/cc1101-workaround/cc1101-workaround.cpp index 30e90507e..2dfe86ff8 100644 --- a/applications/cc1101-workaround/cc1101-workaround.cpp +++ b/applications/cc1101-workaround/cc1101-workaround.cpp @@ -237,8 +237,11 @@ const FreqConfig FREQ_LIST[] = { {&bands[10], 0}, }; -extern "C" void cc1101_isr() { - gpio_write((GpioPin*)&debug_0, gpio_read(&cc1101_g0_gpio)); +extern "C" void cc1101_isr(void* _pin, void* _ctx) { + uint32_t pin = (uint32_t)_pin; + if(pin == CC1101_G0_Pin) { + gpio_write((GpioPin*)&debug_0, gpio_read(&cc1101_g0_gpio)); + } } typedef enum { @@ -343,7 +346,7 @@ static void input_callback(InputEvent* input_event, void* ctx) { } extern "C" void cc1101_workaround(void* p) { - osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(AppEvent), NULL); + osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL); furi_check(event_queue); State _state; @@ -383,7 +386,7 @@ extern "C" void cc1101_workaround(void* p) { GpioPin cs_pin = {CC1101_CS_GPIO_Port, CC1101_CS_Pin}; gpio_init(&cc1101_g0_gpio, GpioModeInput); - + api_interrupt_add(cc1101_isr, InterruptTypeExternalInterrupt, NULL); // TODO open record GpioPin* cs_pin_record = &cs_pin; CC1101 cc1101(cs_pin_record); @@ -425,7 +428,8 @@ extern "C" void cc1101_workaround(void* p) { if(event_status == osOK) { if(event.type == EventTypeKey) { - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyBack) { printf("[cc1101] bye!\r\n"); cc1101.SpiStrobe(CC1101_SIDLE); @@ -438,7 +442,8 @@ extern "C" void cc1101_workaround(void* p) { furiac_exit(NULL); } - if(event.value.input.state && event.value.input.input == InputDown) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyDown) { if(state->active_freq_idx > 0) { state->active_freq_idx--; } @@ -448,7 +453,8 @@ extern "C" void cc1101_workaround(void* p) { state->need_cc1101_conf = true; } - if(event.value.input.state && event.value.input.input == InputUp) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyUp) { if(state->active_freq_idx < (sizeof(FREQ_LIST) / sizeof(FREQ_LIST[0]) - 1)) { state->active_freq_idx++; } @@ -458,7 +464,8 @@ extern "C" void cc1101_workaround(void* p) { state->need_cc1101_conf = true; } - if(event.value.input.state && event.value.input.input == InputRight) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyRight) { /* if(state->tx_level < (sizeof(TX_LEVELS) / sizeof(TX_LEVELS[0]) - 1)) { state->tx_level++; @@ -471,7 +478,8 @@ extern "C" void cc1101_workaround(void* p) { state->need_cc1101_conf = true; } - if(event.value.input.state && event.value.input.input == InputLeft) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyLeft) { /* if(state->tx_level < (sizeof(TX_LEVELS) / sizeof(TX_LEVELS[0]) - 1)) { state->tx_level++; @@ -484,9 +492,14 @@ extern "C" void cc1101_workaround(void* p) { state->need_cc1101_conf = true; } - if(event.value.input.input == InputOk) { - state->mode = event.value.input.state ? ModeTx : ModeRx; - state->need_cc1101_conf = true; + if(event.value.input.key == InputKeyOk) { + if(event.value.input.type == InputTypePress) { + state->mode = ModeTx; + state->need_cc1101_conf = true; + } else if(event.value.input.type == InputTypeRelease) { + state->mode = ModeRx; + state->need_cc1101_conf = true; + } } } } else { diff --git a/applications/dolphin/dolphin.c b/applications/dolphin/dolphin.c index 33e08ebf9..ec52f9315 100644 --- a/applications/dolphin/dolphin.c +++ b/applications/dolphin/dolphin.c @@ -4,13 +4,13 @@ bool dolphin_view_first_start_input(InputEvent* event, void* context) { furi_assert(event); furi_assert(context); Dolphin* dolphin = context; - if(event->state) { - if(event->input == InputLeft) { + if(event->type == InputTypeShort) { + if(event->key == InputKeyLeft) { with_view_model( dolphin->idle_view_first_start, (DolphinViewFirstStartModel * model) { if(model->page > 0) model->page--; }); - } else if(event->input == InputRight) { + } else if(event->key == InputKeyRight) { uint32_t page; with_view_model( dolphin->idle_view_first_start, @@ -30,13 +30,13 @@ bool dolphin_view_idle_main_input(InputEvent* event, void* context) { furi_assert(context); Dolphin* dolphin = context; - if(event->state) { - if(event->input == InputOk) { + if(event->type == InputTypeShort) { + if(event->key == InputKeyOk) { with_value_mutex( dolphin->menu_vm, (Menu * menu) { menu_ok(menu); }); - } else if(event->input == InputUp) { + } else if(event->key == InputKeyUp) { view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleStats); - } else if(event->input == InputDown) { + } else if(event->key == InputKeyDown) { view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleDebug); } } @@ -49,13 +49,13 @@ bool dolphin_view_idle_stats_input(InputEvent* event, void* context) { furi_assert(context); Dolphin* dolphin = context; - if(!event->state) return false; + if(event->type != InputTypeShort) return false; - if(event->input == InputLeft) { + if(event->key == InputKeyLeft) { dolphin_deed(dolphin, DolphinDeedWrong); - } else if(event->input == InputRight) { + } else if(event->key == InputKeyRight) { dolphin_deed(dolphin, DolphinDeedIButtonRead); - } else if(event->input == InputOk) { + } else if(event->key == InputKeyOk) { dolphin_save(dolphin); } else { return false; diff --git a/applications/examples/input_dump.c b/applications/examples/input_dump.c index 806451719..2284e90eb 100644 --- a/applications/examples/input_dump.c +++ b/applications/examples/input_dump.c @@ -4,27 +4,17 @@ typedef union { unsigned int packed; - InputState state; + InputType state; } InputDump; -static void state_cb(const void* value, void* ctx) { - InputDump dump = {.packed = 0}; - dump.state = *(InputState*)value; - - printf("state: %02x\r\n", dump.packed); -} - static void event_cb(const void* value, void* ctx) { const InputEvent* event = value; - printf("event: %02x %s\r\n", event->input, event->state ? "pressed" : "released"); + printf("event: %02x %s\r\n", event->key, event->type ? "pressed" : "released"); } void application_input_dump(void* p) { // open record - ValueManager* state_record = furi_record_open("input_state"); - subscribe_pubsub(&state_record->pubsub, state_cb, NULL); - PubSub* event_record = furi_record_open("input_events"); subscribe_pubsub(event_record, event_cb, NULL); diff --git a/applications/examples/strobe.c b/applications/examples/strobe.c index ea922196a..8e8379483 100644 --- a/applications/examples/strobe.c +++ b/applications/examples/strobe.c @@ -7,11 +7,11 @@ static void event_cb(const void* value, void* ctx) { uint32_t* delay_time = acquire_mutex(ctx, 0); if(delay_time == NULL) return; - if(event->input == InputUp && *delay_time < 1000) { + if(event->key == InputKeyUp && *delay_time < 1000) { *delay_time += 5; } - if(event->input == InputDown && *delay_time > 10) { + if(event->key == InputKeyDown && *delay_time > 10) { *delay_time -= 5; } release_mutex(ctx, delay_time); diff --git a/applications/examples/vibro.c b/applications/examples/vibro.c index 4189910db..fa4fdc2e6 100644 --- a/applications/examples/vibro.c +++ b/applications/examples/vibro.c @@ -10,9 +10,14 @@ static void button_handler(const void* value, void* _ctx) { const InputEvent* event = value; Ctx* ctx = (Ctx*)_ctx; - if(event->input == InputOk) { - gpio_write(ctx->vibro, event->state); - gpio_write(ctx->led, !event->state); + if(event->key != InputKeyOk) return; + + if(event->type == InputTypePress) { + gpio_write(ctx->led, false); + gpio_write(ctx->vibro, true); + } else if(event->type == InputTypeRelease) { + gpio_write(ctx->led, true); + gpio_write(ctx->vibro, false); } } diff --git a/applications/floopper-bloopper b/applications/floopper-bloopper index 318b5f6c4..598edd541 160000 --- a/applications/floopper-bloopper +++ b/applications/floopper-bloopper @@ -1 +1 @@ -Subproject commit 318b5f6c43b0219ec490a088ef51421fc8b94ac5 +Subproject commit 598edd54197d58b35d8cc2513549ddda3938fa38 diff --git a/applications/gpio-tester/gpio-tester.c b/applications/gpio-tester/gpio-tester.c index 92b6bd915..765758681 100644 --- a/applications/gpio-tester/gpio-tester.c +++ b/applications/gpio-tester/gpio-tester.c @@ -58,7 +58,7 @@ static void input_callback(InputEvent* input_event, void* ctx) { } void app_gpio_test(void* p) { - osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(AppEvent), NULL); + osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL); furi_check(event_queue); State _state; @@ -88,34 +88,41 @@ void app_gpio_test(void* p) { AppEvent event; while(1) { - osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 150); + osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, osWaitForever); State* state = (State*)acquire_mutex_block(&state_mutex); if(event_status == osOK) { if(event.type == EventTypeKey) { - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyBack) { printf("[gpio-tester] bye!\r\n"); // TODO remove all view_ports create by app view_port_enabled_set(view_port, false); furiac_exit(NULL); } - if(event.value.input.state && event.value.input.input == InputRight) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyRight) { if(state->gpio_index < (sizeof(GPIO_PINS) / sizeof(GPIO_PINS[0]) - 1)) { state->gpio_index++; } } - if(event.value.input.state && event.value.input.input == InputLeft) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyLeft) { if(state->gpio_index > 0) { state->gpio_index--; } } - if(event.value.input.input == InputOk) { - gpio_write( - (GpioPin*)&GPIO_PINS[state->gpio_index].pin, event.value.input.state); - gpio_write((GpioPin*)&led_gpio[1], !event.value.input.state); + if(event.value.input.key == InputKeyOk) { + if(event.value.input.type == InputTypePress) { + gpio_write((GpioPin*)&GPIO_PINS[state->gpio_index].pin, true); + gpio_write((GpioPin*)&led_gpio[1], false); + } else if(event.value.input.type == InputTypeRelease) { + gpio_write((GpioPin*)&GPIO_PINS[state->gpio_index].pin, false); + gpio_write((GpioPin*)&led_gpio[1], true); + } } } } diff --git a/applications/gui/modules/dialog.c b/applications/gui/modules/dialog.c index 74298e95c..df20ad9a2 100644 --- a/applications/gui/modules/dialog.c +++ b/applications/gui/modules/dialog.c @@ -43,11 +43,11 @@ static bool dialog_view_input_callback(InputEvent* event, void* context) { bool consumed = false; // Process key presses only - if(event->state && dialog->callback) { - if(event->input == InputLeft) { + if(event->type == InputTypeShort && dialog->callback) { + if(event->key == InputKeyLeft) { dialog->callback(DialogResultLeft, dialog->context); consumed = true; - } else if(event->input == InputRight) { + } else if(event->key == InputKeyRight) { dialog->callback(DialogResultRight, dialog->context); consumed = true; } diff --git a/applications/gui/modules/dialog_ex.c b/applications/gui/modules/dialog_ex.c index 23534b4f2..4fbbc4f41 100644 --- a/applications/gui/modules/dialog_ex.c +++ b/applications/gui/modules/dialog_ex.c @@ -97,14 +97,14 @@ static bool dialog_ex_view_input_callback(InputEvent* event, void* context) { }); // Process key presses only - if(event->state && dialog_ex->callback) { - if(event->input == InputLeft && left_text != NULL) { + if(event->type == InputTypeShort && dialog_ex->callback) { + if(event->key == InputKeyLeft && left_text != NULL) { dialog_ex->callback(DialogExResultLeft, dialog_ex->context); consumed = true; - } else if(event->input == InputOk && center_text != NULL) { + } else if(event->key == InputKeyOk && center_text != NULL) { dialog_ex->callback(DialogExResultCenter, dialog_ex->context); consumed = true; - } else if(event->input == InputRight && right_text != NULL) { + } else if(event->key == InputKeyRight && right_text != NULL) { dialog_ex->callback(DialogExResultRight, dialog_ex->context); consumed = true; } diff --git a/applications/gui/modules/popup.c b/applications/gui/modules/popup.c index 73a855d28..8f79850cf 100644 --- a/applications/gui/modules/popup.c +++ b/applications/gui/modules/popup.c @@ -83,7 +83,7 @@ static bool popup_view_input_callback(InputEvent* event, void* context) { bool consumed = false; // Process key presses only - if(event->state && popup->callback) { + if(event->type == InputTypeShort && popup->callback) { popup->callback(popup->context); consumed = true; } diff --git a/applications/gui/modules/submenu.c b/applications/gui/modules/submenu.c index 02887fa1f..d2873c8c1 100644 --- a/applications/gui/modules/submenu.c +++ b/applications/gui/modules/submenu.c @@ -74,17 +74,17 @@ static bool submenu_view_input_callback(InputEvent* event, void* context) { furi_assert(submenu); bool consumed = false; - if(event->state) { - switch(event->input) { - case InputUp: + if(event->type == InputTypeShort) { + switch(event->key) { + case InputKeyUp: consumed = true; submenu_process_up(submenu); break; - case InputDown: + case InputKeyDown: consumed = true; submenu_process_down(submenu); break; - case InputOk: + case InputKeyOk: consumed = true; submenu_process_ok(submenu); break; diff --git a/applications/gui/modules/text_input.c b/applications/gui/modules/text_input.c index 80a7fe6bf..88441b843 100644 --- a/applications/gui/modules/text_input.c +++ b/applications/gui/modules/text_input.c @@ -289,25 +289,25 @@ static bool text_input_view_input_callback(InputEvent* event, void* context) { furi_assert(text_input); bool consumed = false; - if(event->state) { - switch(event->input) { - case InputUp: + if(event->type == InputTypeShort) { + switch(event->key) { + case InputKeyUp: text_input_handle_up(text_input); consumed = true; break; - case InputDown: + case InputKeyDown: text_input_handle_down(text_input); consumed = true; break; - case InputLeft: + case InputKeyLeft: text_input_handle_left(text_input); consumed = true; break; - case InputRight: + case InputKeyRight: text_input_handle_right(text_input); consumed = true; break; - case InputOk: + case InputKeyOk: text_input_handle_ok(text_input); consumed = true; break; diff --git a/applications/gui/view_dispatcher.c b/applications/gui/view_dispatcher.c index 1ec57a4f9..7cf9e422b 100644 --- a/applications/gui/view_dispatcher.c +++ b/applications/gui/view_dispatcher.c @@ -89,11 +89,11 @@ void view_dispatcher_input_callback(InputEvent* event, void* context) { if(view_dispatcher->current_view) { is_consumed = view_input(view_dispatcher->current_view, event); } - if(!is_consumed && event->state) { + if(!is_consumed && event->type == InputTypeShort) { uint32_t view_id = VIEW_IGNORE; - if(event->input == InputBack) { + if(event->key == InputKeyBack) { view_id = view_previous(view_dispatcher->current_view); - } else if(event->input == InputOk) { + } else if(event->key == InputKeyOk) { view_id = view_next(view_dispatcher->current_view); } view_dispatcher_switch_to_view(view_dispatcher, view_id); diff --git a/applications/ibutton/ibutton.cpp b/applications/ibutton/ibutton.cpp index 06f76a385..8557d2d6c 100644 --- a/applications/ibutton/ibutton.cpp +++ b/applications/ibutton/ibutton.cpp @@ -28,10 +28,11 @@ void AppiButton::run() { AppiButtonEvent event; while(1) { - if(get_event(&event, 20)) { + if(get_event(&event, 1024 / 8)) { if(event.type == AppiButtonEvent::EventTypeKey) { // press events - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyBack) { view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); api_hal_timebase_insomnia_exit(); @@ -39,11 +40,13 @@ void AppiButton::run() { osThreadExit(); } - if(event.value.input.state && event.value.input.input == InputLeft) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyLeft) { decrease_mode(); } - if(event.value.input.state && event.value.input.input == InputRight) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyRight) { increase_mode(); } } diff --git a/applications/ibutton/ibutton_mode_cyfral_emulate.h b/applications/ibutton/ibutton_mode_cyfral_emulate.h index 157e15ca2..e0b2cb609 100644 --- a/applications/ibutton/ibutton_mode_cyfral_emulate.h +++ b/applications/ibutton/ibutton_mode_cyfral_emulate.h @@ -29,11 +29,11 @@ void AppiButtonModeCyfralEmulate::event(AppiButtonEvent* event, AppiButtonState* app->blink_green(); } else if(event->type == AppiButtonEvent::EventTypeKey) { - if(event->value.input.state && event->value.input.input == InputUp) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) { app->decrease_cyfral_address(); } - if(event->value.input.state && event->value.input.input == InputDown) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) { app->increase_cyfral_address(); } } diff --git a/applications/ibutton/ibutton_mode_cyfral_read.h b/applications/ibutton/ibutton_mode_cyfral_read.h index a887289cf..236c8e22c 100644 --- a/applications/ibutton/ibutton_mode_cyfral_read.h +++ b/applications/ibutton/ibutton_mode_cyfral_read.h @@ -59,11 +59,11 @@ void AppiButtonModeCyfralRead::event(AppiButtonEvent* event, AppiButtonState* st } } } else if(event->type == AppiButtonEvent::EventTypeKey) { - if(event->value.input.state && event->value.input.input == InputUp) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) { app->decrease_cyfral_address(); } - if(event->value.input.state && event->value.input.input == InputDown) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) { app->increase_cyfral_address(); } } diff --git a/applications/ibutton/ibutton_mode_dallas_emulate.h b/applications/ibutton/ibutton_mode_dallas_emulate.h index 02a0f4dd4..d502a5789 100644 --- a/applications/ibutton/ibutton_mode_dallas_emulate.h +++ b/applications/ibutton/ibutton_mode_dallas_emulate.h @@ -48,11 +48,11 @@ void AppiButtonModeDallasEmulate::event(AppiButtonEvent* event, AppiButtonState* app->blink_green(); } } else if(event->type == AppiButtonEvent::EventTypeKey) { - if(event->value.input.state && event->value.input.input == InputUp) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) { app->decrease_dallas_address(); } - if(event->value.input.state && event->value.input.input == InputDown) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) { app->increase_dallas_address(); } } diff --git a/applications/ibutton/ibutton_mode_dallas_read.h b/applications/ibutton/ibutton_mode_dallas_read.h index 2e23b38a4..0f3303421 100644 --- a/applications/ibutton/ibutton_mode_dallas_read.h +++ b/applications/ibutton/ibutton_mode_dallas_read.h @@ -46,11 +46,11 @@ void AppiButtonModeDallasRead::event(AppiButtonEvent* event, AppiButtonState* st } } } else if(event->type == AppiButtonEvent::EventTypeKey) { - if(event->value.input.state && event->value.input.input == InputUp) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) { app->decrease_dallas_address(); } - if(event->value.input.state && event->value.input.input == InputDown) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) { app->increase_dallas_address(); } } diff --git a/applications/ibutton/ibutton_mode_dallas_write.h b/applications/ibutton/ibutton_mode_dallas_write.h index 6f0f72c8b..135511aa7 100644 --- a/applications/ibutton/ibutton_mode_dallas_write.h +++ b/applications/ibutton/ibutton_mode_dallas_write.h @@ -39,11 +39,11 @@ void AppiButtonModeDallasWrite::event(AppiButtonEvent* event, AppiButtonState* s } } else if(event->type == AppiButtonEvent::EventTypeKey) { - if(event->value.input.state && event->value.input.input == InputUp) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) { app->decrease_dallas_address(); } - if(event->value.input.state && event->value.input.input == InputDown) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) { app->increase_dallas_address(); } } diff --git a/applications/input/input.c b/applications/input/input.c index 658412ccf..92e8a0f4b 100644 --- a/applications/input/input.c +++ b/applications/input/input.c @@ -1,131 +1,72 @@ -#include -#include -#include +#include "input_i.h" -#ifdef APP_NFC -void nfc_isr(void); -#endif +#define GPIO_Read(input_pin) \ + (HAL_GPIO_ReadPin((GPIO_TypeDef*)input_pin.pin->port, input_pin.pin->pin) ^ \ + input_pin.pin->inverted) -#ifdef BUILD_CC1101 -void cc1101_isr(); -#endif +static Input* input = NULL; -static volatile bool initialized = false; -static ValueManager input_state_record; -static PubSub input_events_record; -static Event event; -static InputState input_state = { - false, -}; +void input_press_timer_callback(void* arg) { + InputPin* input_pin = arg; + InputEvent event; + event.key = input_pin->key; + event.type = InputTypeLong; + notify_pubsub(&input->event_pubsub, &event); +} -static void exti_input_callback(void* _pin, void* _ctx); +void input_isr(void* _pin, void* _ctx) { + osThreadFlagsSet(input->thread, INPUT_THREAD_FLAG_ISR); +} -void input_task(void* p) { - uint32_t state_bits = 0; - uint8_t debounce_counters[INPUT_COUNT]; +void input_task() { + input = furi_alloc(sizeof(Input)); + input->thread = osThreadGetId(); + init_pubsub(&input->event_pubsub); + furi_record_create("input_events", &input->event_pubsub); - if(!init_managed(&input_state_record, &input_state, sizeof(input_state))) { - printf("[input_task] cannot initialize ValueManager for input_state\r\n"); - furiac_exit(NULL); - } - if(!init_pubsub(&input_events_record)) { - printf("[input_task] cannot initialize PubSub for input_events\r\n"); - furiac_exit(NULL); - } - if(!init_event(&event)) { - printf("[input_task] cannot initialize Event\r\n"); - furiac_exit(NULL); + const size_t pin_count = input_pins_count; + input->pin_states = furi_alloc(pin_count * sizeof(InputPinState)); + + api_interrupt_add(input_isr, InterruptTypeExternalInterrupt, NULL); + + for(size_t i = 0; i < pin_count; i++) { + 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 = + osTimerNew(input_press_timer_callback, osTimerOnce, &input->pin_states[i], NULL); } - furi_record_create("input_state", &input_state_record); - furi_record_create("input_events", &input_events_record); - - api_interrupt_add(exti_input_callback, InterruptTypeExternalInterrupt, NULL); - - // we ready to work - initialized = true; - - // Force state update - for(uint32_t i = 0; i < INPUT_COUNT; i++) { - debounce_counters[i] = DEBOUNCE_TICKS / 2; - } - - for(;;) { - bool changed = false; - for(uint32_t i = 0; i < INPUT_COUNT; i++) { - bool input_state = false; - - // dirty hack, f3 has no CHARGING pin - // TODO rewrite this - if(i < GPIO_INPUT_PINS_COUNT) { - input_state = gpio_read(&input_gpio[i]) ^ input_invert[i]; - } - - if(input_state) { - if(debounce_counters[i] < DEBOUNCE_TICKS) { - debounce_counters[i] += 1; - changed = true; - } - } else { - if(debounce_counters[i] > 0) { - debounce_counters[i] -= 1; - changed = true; + while(1) { + bool is_changing = false; + for(size_t i = 0; i < pin_count; i++) { + bool state = GPIO_Read(input->pin_states[i]); + if(input->pin_states[i].debounce > 0 && + input->pin_states[i].debounce < INPUT_DEBOUNCE_TICKS) { + is_changing = true; + input->pin_states[i].debounce += (state ? 1 : -1); + } else if(input->pin_states[i].state != state) { + input->pin_states[i].state = state; + // Common state info + InputEvent event; + event.type = input->pin_states[i].state ? InputTypePress : InputTypeRelease; + event.key = input->pin_states[i].pin->key; + // Send Press/Release event + notify_pubsub(&input->event_pubsub, &event); + // Short/Long press logic + if(state) { + osTimerStart(input->pin_states[i].press_timer, INPUT_LONG_PRESS_TICKS); + } else if(osTimerStop(input->pin_states[i].press_timer) == osOK) { + event.type = InputTypeShort; + notify_pubsub(&input->event_pubsub, &event); } } } - if(!changed) { - uint32_t new_state_bits = 0; - for(uint32_t i = 0; i < INPUT_COUNT; i++) { - if(debounce_counters[i] == DEBOUNCE_TICKS) { - new_state_bits |= (1 << i); - } - } - uint32_t changed_bits = new_state_bits ^ state_bits; - - if(changed_bits != 0) { - // printf("[input] %02x -> %02x\n", state_bits, new_state_bits); - InputState new_state = _BITS2STATE(new_state_bits); - write_managed(&input_state_record, &new_state, sizeof(new_state), osWaitForever); - - state_bits = new_state_bits; - - for(uint32_t i = 0; i < INPUT_COUNT; i++) { - if((changed_bits & (1 << i)) != 0) { - bool state = (new_state_bits & (1 << i)) != 0; - InputEvent event = {i, state}; - notify_pubsub(&input_events_record, &event); - } - } - } - - // Sleep: wait for event - wait_event(&event); - } else { + if(is_changing) { osDelay(1); + } else { + osThreadFlagsWait(INPUT_THREAD_FLAG_ISR, osFlagsWaitAny, osWaitForever); } } } - -static void exti_input_callback(void* _pin, void* _ctx) { - // interrupt manager get us pin constant, so... - uint32_t pin = (uint32_t)_pin; - -#ifdef APP_NFC - if(pin == NFC_IRQ_Pin) { - nfc_isr(); - return; - } -#endif - -#ifdef BUILD_CC1101 - if(pin == CC1101_G0_Pin) { - cc1101_isr(); - return; - } -#endif - - if(!initialized) return; - - signal_event(&event); -} \ No newline at end of file diff --git a/applications/input/input.h b/applications/input/input.h index 8e555c41a..a3500acbd 100644 --- a/applications/input/input.h +++ b/applications/input/input.h @@ -1,40 +1,19 @@ -#ifndef __INPUT_H -#define __INPUT_H +#pragma once -#include - -#define INPUT_COUNT 7 +#include +/* Input Types + * Some of them are physical events and some logical + */ typedef enum { - InputUp = 0, - InputDown, - InputRight, - InputLeft, - InputOk, - InputBack, - InputCharging, -} Input; + InputTypePress, /* Press event, emitted after debounce */ + InputTypeRelease, /* Release event, emitted after debounce */ + InputTypeShort, /* Short event, emitted after InputTypeRelease done withing INPUT_LONG_PRESS interval */ + InputTypeLong, /* Long event, emmited after INPUT_LONG_PRESS interval, asynchronouse to InputTypeRelease */ +} InputType; +/* Input Event, dispatches with PubSub */ typedef struct { - Input input; - bool state; + InputKey key; + InputType type; } InputEvent; - -typedef struct { - bool up : 1; - bool down : 1; - bool right : 1; - bool left : 1; - bool ok : 1; - bool back : 1; - bool charging : 1; -} __attribute__((packed)) InputState; - -#define _BITS2STATE(bits) \ - { \ - .up = (((bits)&0x01) != 0), .down = (((bits)&0x02) != 0), .right = (((bits)&0x04) != 0), \ - .left = (((bits)&0x08) != 0), .ok = (((bits)&0x10) != 0), .back = (((bits)&0x20) != 0), \ - .charging = (((bits)&0x40) != 0) \ - } - -#endif /* __INPUT_H */ diff --git a/applications/input/input_i.h b/applications/input/input_i.h new file mode 100644 index 000000000..2f0c883dd --- /dev/null +++ b/applications/input/input_i.h @@ -0,0 +1,34 @@ +#pragma once + +#include "input.h" + +#include +#include +#include +#include + +#define INPUT_DEBOUNCE_TICKS_HALF (INPUT_DEBOUNCE_TICKS / 2) +#define INPUT_LONG_PRESS_TICKS 2048 +#define INPUT_THREAD_FLAG_ISR 0x00000001 + +/* Input pin state */ +typedef struct { + const InputPin* pin; + // State + volatile bool state; + volatile uint8_t debounce; + volatile osTimerId_t press_timer; +} InputPinState; + +/* Input state */ +typedef struct { + osThreadId_t thread; + PubSub event_pubsub; + InputPinState* pin_states; +} Input; + +/* Input press timer callback */ +void input_press_timer_callback(void* arg); + +/* Input interrupt handler */ +void input_isr(void* _pin, void* _ctx); diff --git a/applications/irda/irda.c b/applications/irda/irda.c index e43112cdd..6da6f0885 100644 --- a/applications/irda/irda.c +++ b/applications/irda/irda.c @@ -78,15 +78,15 @@ void render_carrier(Canvas* canvas, State* state) { } void input_carrier(AppEvent* event, State* state) { - if(event->value.input.input == InputOk) { - if(event->value.input.state) { + if(event->value.input.key == InputKeyOk) { + if(event->value.input.type == InputTypePress) { irda_pwm_set(duty_cycles[state->carrier_duty_cycle_id], state->carrier_freq); - } else { + } else if(event->value.input.type == InputTypeRelease) { irda_pwm_stop(); } } - if(event->value.input.state && event->value.input.input == InputUp) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) { if(state->carrier_freq < 45000) { state->carrier_freq += 1000; } else { @@ -94,7 +94,7 @@ void input_carrier(AppEvent* event, State* state) { } } - if(event->value.input.state && event->value.input.input == InputDown) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) { uint8_t duty_cycles_count = sizeof(duty_cycles) / sizeof(duty_cycles[0]); if(state->carrier_duty_cycle_id < (duty_cycles_count - 1)) { state->carrier_duty_cycle_id++; @@ -137,8 +137,8 @@ void render_packet(Canvas* canvas, State* state) { } void input_packet(AppEvent* event, State* state) { - if(event->value.input.input == InputOk) { - if(event->value.input.state) { + if(event->value.input.key == InputKeyOk) { + if(event->value.input.type == InputTypeShort) { switch(state->packets[state->packet_id].protocol) { case IRDA_NEC: ir_nec_send( @@ -156,13 +156,13 @@ void input_packet(AppEvent* event, State* state) { } } - if(event->value.input.state && event->value.input.input == InputDown) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyDown) { if(state->packet_id < (IRDA_PACKET_COUNT - 1)) { state->packet_id++; }; } - if(event->value.input.state && event->value.input.input == InputUp) { + if(event->value.input.type == InputTypeShort && event->value.input.key == InputKeyUp) { if(state->packet_id > 0) { state->packet_id--; }; @@ -299,7 +299,8 @@ void irda(void* p) { if(event_status == osOK) { if(event.type == EventTypeKey) { // press events - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyBack) { // remove all view_ports create by app view_port_enabled_set(view_port, false); gui_remove_view_port(gui, view_port); @@ -311,13 +312,15 @@ void irda(void* p) { furiac_exit(NULL); } - if(event.value.input.state && event.value.input.input == InputLeft) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyLeft) { if(state->mode_id > 0) { state->mode_id--; } } - if(event.value.input.state && event.value.input.input == InputRight) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyRight) { if(state->mode_id < (mode_count - 1)) { state->mode_id++; } diff --git a/applications/lf-rfid/lf-rfid.c b/applications/lf-rfid/lf-rfid.c index b1bb1691a..382d5895f 100644 --- a/applications/lf-rfid/lf-rfid.c +++ b/applications/lf-rfid/lf-rfid.c @@ -161,7 +161,7 @@ static void extract_data(uint8_t* buf, uint8_t* customer, uint32_t* em_data) { } void lf_rfid_workaround(void* p) { - osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(AppEvent), NULL); + osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL); // create pin GpioPin pull_pin = {.pin = RFID_PULL_Pin, .port = RFID_PULL_GPIO_Port}; @@ -222,7 +222,7 @@ void lf_rfid_workaround(void* p) { } while(1) { - osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 100); + osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, 1024 / 8); if(event.type == EventTypeRx && event_status == osOK) { uint32_t dt = (event.value.rx.dwt_value - prev_dwt) / (SystemCoreClock / 1000000.0f); @@ -285,7 +285,8 @@ void lf_rfid_workaround(void* p) { if(event_status == osOK) { if(event.type == EventTypeKey) { // press events - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyBack) { hal_pwmn_stop(&TIM_C, TIM_CHANNEL_1); // TODO: move to furiac_onexit gpio_init(pull_pin_record, GpioModeInput); gpio_init((GpioPin*)&ibutton_gpio, GpioModeInput); @@ -295,23 +296,28 @@ void lf_rfid_workaround(void* p) { furiac_exit(NULL); } - if(event.value.input.state && event.value.input.input == InputUp) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyUp) { state->dirty = true; state->freq_khz += 10; } - if(event.value.input.state && event.value.input.input == InputDown) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyDown) { state->dirty = true; state->freq_khz -= 10; } - if(event.value.input.state && event.value.input.input == InputLeft) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyLeft) { } - if(event.value.input.state && event.value.input.input == InputRight) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyRight) { } - if(event.value.input.state && event.value.input.input == InputOk) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyOk) { state->dirty = true; state->on = !state->on; } diff --git a/applications/menu/menu_event.c b/applications/menu/menu_event.c index eea029053..805127986 100644 --- a/applications/menu/menu_event.c +++ b/applications/menu/menu_event.c @@ -55,19 +55,19 @@ void menu_event_input_callback(InputEvent* input_event, void* context) { MenuEvent* menu_event = context; MenuMessage message; - if(!input_event->state) return; + if(input_event->type != InputTypeShort) return; - if(input_event->input == InputUp) { + if(input_event->key == InputKeyUp) { message.type = MenuMessageTypeUp; - } else if(input_event->input == InputDown) { + } else if(input_event->key == InputKeyDown) { message.type = MenuMessageTypeDown; - } else if(input_event->input == InputRight) { + } else if(input_event->key == InputKeyRight) { message.type = MenuMessageTypeRight; - } else if(input_event->input == InputLeft) { + } else if(input_event->key == InputKeyLeft) { message.type = MenuMessageTypeLeft; - } else if(input_event->input == InputOk) { + } else if(input_event->key == InputKeyOk) { message.type = MenuMessageTypeOk; - } else if(input_event->input == InputBack) { + } else if(input_event->key == InputKeyBack) { message.type = MenuMessageTypeBack; } else { message.type = MenuMessageTypeUnknown; diff --git a/applications/music-player/music-player.c b/applications/music-player/music-player.c index c12408f0e..453724b3c 100644 --- a/applications/music-player/music-player.c +++ b/applications/music-player/music-player.c @@ -357,7 +357,7 @@ void music_player_thread(void* p) { } void music_player(void* p) { - osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(MusicDemoEvent), NULL); + osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(MusicDemoEvent), NULL); State _state; _state.note_record = NULL; @@ -384,7 +384,7 @@ void music_player(void* p) { // open input record PubSub* input_events_record = furi_record_open("input_events"); // prepare "do nothing" event - InputEvent input_event = {InputRight, true}; + InputEvent input_event = {InputKeyRight, true}; // start player thread // TODO change to fuirac_start @@ -406,24 +406,29 @@ void music_player(void* p) { if(event_status == osOK) { if(event.type == EventTypeKey) { // press events - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyBack) { } - if(event.value.input.state && event.value.input.input == InputUp) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyUp) { if(state->volume_id < state->volume_id_max - 1) state->volume_id++; } - if(event.value.input.state && event.value.input.input == InputDown) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyDown) { if(state->volume_id > 0) state->volume_id--; } - if(event.value.input.state && event.value.input.input == InputLeft) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyLeft) { } - if(event.value.input.state && event.value.input.input == InputRight) { + if(event.value.input.type == InputTypePress && + event.value.input.key == InputKeyRight) { } - if(event.value.input.input == InputOk) { + if(event.value.input.key == InputKeyOk) { } } else if(event.type == EventTypeNote) { diff --git a/applications/sd-card-test/sd-card-test.cpp b/applications/sd-card-test/sd-card-test.cpp index e2e736680..495cc28ed 100644 --- a/applications/sd-card-test/sd-card-test.cpp +++ b/applications/sd-card-test/sd-card-test.cpp @@ -57,8 +57,8 @@ public: void render(Canvas* canvas); template void set_text(std::initializer_list list); template void set_error(std::initializer_list list); - void wait_for_button(Input input_button); - bool ask(Input input_button_cancel, Input input_button_ok); + void wait_for_button(InputKey input_button); + bool ask(InputKey input_button_cancel, InputKey input_button_ok); void blink_red(); void set_red(); void blink_green(); @@ -145,7 +145,7 @@ void SdTest::run() { "", "press BACK to exit", }); - wait_for_button(InputBack); + wait_for_button(InputKeyBack); exit(); } @@ -184,9 +184,9 @@ void SdTest::show_warning() { "", "press UP DOWN OK to continue"}); - wait_for_button(InputUp); - wait_for_button(InputDown); - wait_for_button(InputOk); + wait_for_button(InputKeyUp); + wait_for_button(InputKeyDown); + wait_for_button(InputKeyOk); } // get info about sd card, label, sn @@ -216,7 +216,7 @@ void SdTest::get_sd_card_info() { blink_green(); - wait_for_button(InputOk); + wait_for_button(InputKeyOk); } // prepare benchmark data (allocate data in ram) @@ -296,7 +296,7 @@ void SdTest::write_benchmark() { blink_green(); - wait_for_button(InputOk); + wait_for_button(InputKeyOk); } uint32_t SdTest::write_benchmark_internal(const uint32_t size, const uint32_t count, bool silent) { @@ -436,7 +436,7 @@ void SdTest::read_benchmark() { blink_green(); - wait_for_button(InputOk); + wait_for_button(InputKeyOk); } uint32_t SdTest::read_benchmark_internal( @@ -590,7 +590,7 @@ void SdTest::hash_benchmark() { blink_green(); - wait_for_button(InputOk); + wait_for_button(InputKeyOk); } void SdTest::cli_read_benchmark(string_t args, void* _ctx) { @@ -786,18 +786,18 @@ void SdTest::cli_write_benchmark(string_t args, void* _ctx) { } // wait for button press -void SdTest::wait_for_button(Input input_button) { +void SdTest::wait_for_button(InputKey input_button) { SdTestEvent event; osMessageQueueReset(event_queue); while(1) { osStatus_t result = osMessageQueueGet(event_queue, &event, NULL, osWaitForever); if(result == osOK && event.type == SdTestEvent::EventTypeKey) { - if(event.value.input.state == true) { - if(event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort) { + if(event.value.input.key == InputKeyBack) { exit(); } else { - if(event.value.input.input == input_button) { + if(event.value.input.key == input_button) { blink_green(); break; } else { @@ -811,7 +811,7 @@ void SdTest::wait_for_button(Input input_button) { } // ask user to proceed or cancel -bool SdTest::ask(Input input_button_cancel, Input input_button_ok) { +bool SdTest::ask(InputKey input_button_cancel, InputKey input_button_ok) { bool return_result; SdTestEvent event; osMessageQueueReset(event_queue); @@ -819,15 +819,15 @@ bool SdTest::ask(Input input_button_cancel, Input input_button_ok) { osStatus_t result = osMessageQueueGet(event_queue, &event, NULL, osWaitForever); if(result == osOK && event.type == SdTestEvent::EventTypeKey) { - if(event.value.input.state == true) { - if(event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort) { + if(event.value.input.key == InputKeyBack) { exit(); } else { - if(event.value.input.input == input_button_ok) { + if(event.value.input.key == input_button_ok) { blink_green(); return_result = true; break; - } else if(event.value.input.input == input_button_cancel) { + } else if(event.value.input.key == input_button_cancel) { blink_green(); return_result = false; break; @@ -865,7 +865,7 @@ void SdTest::blink_green() { template void SdTest::set_error(std::initializer_list list) { set_text(list); set_red(); - wait_for_button(InputBack); + wait_for_button(InputKeyBack); exit(); } diff --git a/applications/sd-filesystem/sd-filesystem.c b/applications/sd-filesystem/sd-filesystem.c index 4afa1165a..3f4b18183 100644 --- a/applications/sd-filesystem/sd-filesystem.c +++ b/applications/sd-filesystem/sd-filesystem.c @@ -105,7 +105,7 @@ SdApp* sd_app_alloc() { furiac_exit(NULL); } - sd_app->event_queue = osMessageQueueNew(1, sizeof(InputEvent), NULL); + sd_app->event_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL); // init view_port sd_app->view_port = view_port_alloc(); @@ -127,7 +127,7 @@ SdApp* sd_app_alloc() { return sd_app; } -bool app_sd_ask(SdApp* sd_app, Input input_true, Input input_false) { +bool app_sd_ask(SdApp* sd_app, InputKey input_true, InputKey input_false) { bool result; InputEvent event; @@ -136,11 +136,11 @@ bool app_sd_ask(SdApp* sd_app, Input input_true, Input input_false) { osMessageQueueGet(sd_app->event_queue, &event, NULL, osWaitForever); if(event_status == osOK) { - if(event.state && event.input == input_true) { + if(event.type == InputTypeShort && event.key == input_true) { result = true; break; } - if(event.state && event.input == InputBack) { + if(event.type == InputTypeShort && event.key == InputKeyBack) { result = false; break; } @@ -254,7 +254,7 @@ void app_sd_info_callback(void* context) { str_buffer[5]); } - app_sd_ask(sd_app, InputBack, InputBack); + app_sd_ask(sd_app, InputKeyBack, InputKeyBack); sd_set_lines(sd_app, 0); view_port_enabled_set(sd_app->view_port, false); @@ -294,7 +294,7 @@ void app_sd_format_callback(void* context) { view_port_enabled_set(sd_app->view_port, true); // wait for input - if(!app_sd_ask(sd_app, InputUp, InputBack)) { + if(!app_sd_ask(sd_app, InputKeyUp, InputKeyBack)) { view_port_enabled_set(sd_app->view_port, false); return; } @@ -313,7 +313,7 @@ void app_sd_format_callback(void* context) { } // wait for BACK - app_sd_ask(sd_app, InputBack, InputBack); + app_sd_ask(sd_app, InputKeyBack, InputKeyBack); view_port_enabled_set(sd_app->view_port, false); } @@ -357,7 +357,7 @@ void app_sd_eject_callback(void* context) { sd_set_lines(sd_app, 1, "SD card can be pulled out"); // wait for BACK - app_sd_ask(sd_app, InputBack, InputBack); + app_sd_ask(sd_app, InputKeyBack, InputKeyBack); view_port_enabled_set(sd_app->view_port, false); } diff --git a/applications/sd-nfc/sdnfc.cpp b/applications/sd-nfc/sdnfc.cpp index 1a63715a2..032afa1bf 100644 --- a/applications/sd-nfc/sdnfc.cpp +++ b/applications/sd-nfc/sdnfc.cpp @@ -105,7 +105,8 @@ void AppSdNFC::run() { if(get_event(&event, 1000)) { if(event.type == AppSdNFCEvent::EventTypeKey) { // press events - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyBack) { exit(); } } diff --git a/applications/template/template.c.example b/applications/template/template.c.example index d86805c9d..7cd7975b3 100644 --- a/applications/template/template.c.example +++ b/applications/template/template.c.example @@ -38,7 +38,7 @@ static void input_callback(InputEvent* input_event, void* ctx) { } void template_app(void* p) { - osMessageQueueId_t event_queue = osMessageQueueNew(1, sizeof(Event), NULL); + osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(Event), NULL); State _state; /* init state here */ @@ -72,22 +72,22 @@ void template_app(void* p) { if(event_status == osOK) { if(event.type == EventTypeKey) { // press events - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyBack) { } - if(event.value.input.state && event.value.input.input == InputUp) { + if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyUp) { } - if(event.value.input.state && event.value.input.input == InputDown) { + if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyDown) { } - if(event.value.input.state && event.value.input.input == InputLeft) { + if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyLeft) { } - if(event.value.input.state && event.value.input.input == InputRight) { + if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyRight) { } - if(event.value.input.input == InputOk) { + if(event.value.input.key == InputKeyOk) { } } } else { diff --git a/firmware/targets/f4/Src/target-resources.c b/firmware/targets/f4/Src/target-resources.c deleted file mode 100644 index e14619e67..000000000 --- a/firmware/targets/f4/Src/target-resources.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "main.h" -#include - -const bool input_invert[GPIO_INPUT_PINS_COUNT] = { - true, // {BUTTON_UP_GPIO_Port, BUTTON_UP_Pin}, - true, // {BUTTON_DOWN_GPIO_Port, BUTTON_DOWN_Pin}, - true, // {BUTTON_RIGHT_GPIO_Port, BUTTON_RIGHT_Pin}, - true, // {BUTTON_LEFT_GPIO_Port, BUTTON_LEFT_Pin}, - false, // {BUTTON_OK_GPIO_Port, BUTTON_OK_Pin}, - true, // {BUTTON_BACK_GPIO_Port, BUTTON_BACK_Pin}, -}; diff --git a/firmware/targets/f4/api-hal/api-hal-resources.c b/firmware/targets/f4/api-hal/api-hal-resources.c index d65d0fb63..369e9f4b5 100644 --- a/firmware/targets/f4/api-hal/api-hal-resources.c +++ b/firmware/targets/f4/api-hal/api-hal-resources.c @@ -1,15 +1,30 @@ +#include #include "main.h" #include -const GpioPin input_gpio[GPIO_INPUT_PINS_COUNT] = { - {BUTTON_UP_GPIO_Port, BUTTON_UP_Pin}, - {BUTTON_DOWN_GPIO_Port, BUTTON_DOWN_Pin}, - {BUTTON_RIGHT_GPIO_Port, BUTTON_RIGHT_Pin}, - {BUTTON_LEFT_GPIO_Port, BUTTON_LEFT_Pin}, - {BUTTON_OK_GPIO_Port, BUTTON_OK_Pin}, - {BUTTON_BACK_GPIO_Port, BUTTON_BACK_Pin}, +const InputPin input_pins[] = { + {.port = BUTTON_UP_GPIO_Port, .pin = BUTTON_UP_Pin, .key = InputKeyUp, .inverted = true}, + {.port = BUTTON_DOWN_GPIO_Port, + .pin = BUTTON_DOWN_Pin, + .key = InputKeyDown, + .inverted = true}, + {.port = BUTTON_RIGHT_GPIO_Port, + .pin = BUTTON_RIGHT_Pin, + .key = InputKeyRight, + .inverted = true}, + {.port = BUTTON_LEFT_GPIO_Port, + .pin = BUTTON_LEFT_Pin, + .key = InputKeyLeft, + .inverted = true}, + {.port = BUTTON_OK_GPIO_Port, .pin = BUTTON_OK_Pin, .key = InputKeyOk, .inverted = false}, + {.port = BUTTON_BACK_GPIO_Port, + .pin = BUTTON_BACK_Pin, + .key = InputKeyBack, + .inverted = true}, }; +const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin); + const GpioPin led_gpio[3] = { {LED_RED_GPIO_Port, LED_RED_Pin}, {LED_GREEN_GPIO_Port, LED_GREEN_Pin}, diff --git a/firmware/targets/f4/api-hal/api-hal-resources.h b/firmware/targets/f4/api-hal/api-hal-resources.h index eaedc85b3..53b3f7e5b 100644 --- a/firmware/targets/f4/api-hal/api-hal-resources.h +++ b/firmware/targets/f4/api-hal/api-hal-resources.h @@ -2,11 +2,28 @@ #include "main.h" #include -#define DEBOUNCE_TICKS 10 -#define GPIO_INPUT_PINS_COUNT 6 +/* Input Related Constants */ +#define INPUT_DEBOUNCE_TICKS 20 -extern const GpioPin input_gpio[GPIO_INPUT_PINS_COUNT]; -extern const bool input_invert[GPIO_INPUT_PINS_COUNT]; +/* Input Keys */ +typedef enum { + InputKeyUp, + InputKeyDown, + InputKeyRight, + InputKeyLeft, + InputKeyOk, + InputKeyBack, +} InputKey; + +typedef struct { + const GPIO_TypeDef* port; + const uint16_t pin; + const InputKey key; + const bool inverted; +} InputPin; + +extern const InputPin input_pins[]; +extern const size_t input_pins_count; extern const GpioPin led_gpio[3]; extern const GpioPin backlight_gpio; diff --git a/lib/ST25RFAL002/platform.c b/lib/ST25RFAL002/platform.c index 00ffb0b6e..8c51e7dcd 100644 --- a/lib/ST25RFAL002/platform.c +++ b/lib/ST25RFAL002/platform.c @@ -1,14 +1,18 @@ #include "platform.h" #include #include +#include #include static osThreadAttr_t platform_irq_thread_attr; static volatile osThreadId_t platform_irq_thread_id = NULL; static volatile PlatformIrqCallback platform_irq_callback = NULL; -void nfc_isr() { - if(platform_irq_callback && platformGpioIsHigh( ST25R_INT_PORT, ST25R_INT_PIN )) { +void nfc_isr(void* _pin, void* _ctx) { + uint32_t pin = (uint32_t)_pin; + if(pin == NFC_IRQ_Pin + && platform_irq_callback + && platformGpioIsHigh(ST25R_INT_PORT, ST25R_INT_PIN)) { osThreadFlagsSet(platform_irq_thread_id, 0x1); } } @@ -28,6 +32,7 @@ void platformSetIrqCallback(PlatformIrqCallback callback) { platform_irq_thread_attr.stack_size = 512; platform_irq_thread_attr.priority = osPriorityISR; platform_irq_thread_id = osThreadNew(platformIrqWorker, NULL, &platform_irq_thread_attr); + api_interrupt_add(nfc_isr, InterruptTypeExternalInterrupt, NULL); } HAL_StatusTypeDef platformSpiTxRx(const uint8_t *txBuf, uint8_t *rxBuf, uint16_t len) { diff --git a/lib/app-template/app-template.cpp b/lib/app-template/app-template.cpp index b04210f14..d085f0c55 100644 --- a/lib/app-template/app-template.cpp +++ b/lib/app-template/app-template.cpp @@ -65,12 +65,12 @@ void AppExample::run() { if(get_event(&event, 1000)) { if(event.type == AppExampleEvent::EventTypeKey) { // press events - if(event.value.input.state && event.value.input.input == InputBack) { + if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyBack) { printf("bye!\n"); exit(); } - if(event.value.input.state && event.value.input.input == InputUp) { + if(event.value.input.type == InputTypeShort && event.value.input.key == InputKeyUp) { // to read or write state you need to execute // acquire modify release state acquire_state();