Input: refactoring, platform agnostic key configuration.
Update input usage across project. Minor queue usage fixes and tick timings. (#330)
This commit is contained in:
parent
5dbe2983aa
commit
8b94eff7f9
@ -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();
|
||||
|
@ -237,8 +237,11 @@ const FreqConfig FREQ_LIST[] = {
|
||||
{&bands[10], 0},
|
||||
};
|
||||
|
||||
extern "C" void cc1101_isr() {
|
||||
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;
|
||||
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 {
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 318b5f6c43b0219ec490a088ef51421fc8b94ac5
|
||||
Subproject commit 598edd54197d58b35d8cc2513549ddda3938fa38
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -1,131 +1,72 @@
|
||||
#include <input/input.h>
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
#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);
|
||||
}
|
@ -1,40 +1,19 @@
|
||||
#ifndef __INPUT_H
|
||||
#define __INPUT_H
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#define INPUT_COUNT 7
|
||||
#include <api-hal-resources.h>
|
||||
|
||||
/* 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 */
|
||||
|
34
applications/input/input_i.h
Normal file
34
applications/input/input_i.h
Normal file
@ -0,0 +1,34 @@
|
||||
#pragma once
|
||||
|
||||
#include "input.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <furi.h>
|
||||
|
||||
#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);
|
@ -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++;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -57,8 +57,8 @@ public:
|
||||
void render(Canvas* canvas);
|
||||
template <class T> void set_text(std::initializer_list<T> list);
|
||||
template <class T> void set_error(std::initializer_list<T> 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 <class T> void SdTest::set_error(std::initializer_list<T> list) {
|
||||
set_text(list);
|
||||
set_red();
|
||||
wait_for_button(InputBack);
|
||||
wait_for_button(InputKeyBack);
|
||||
exit();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -1,11 +0,0 @@
|
||||
#include "main.h"
|
||||
#include <furi.h>
|
||||
|
||||
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},
|
||||
};
|
@ -1,15 +1,30 @@
|
||||
#include <api-hal-resources.h>
|
||||
#include "main.h"
|
||||
#include <furi.h>
|
||||
|
||||
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},
|
||||
|
@ -2,11 +2,28 @@
|
||||
#include "main.h"
|
||||
#include <furi.h>
|
||||
|
||||
#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;
|
||||
|
@ -1,14 +1,18 @@
|
||||
#include "platform.h"
|
||||
#include <assert.h>
|
||||
#include <main.h>
|
||||
#include <furi.h>
|
||||
#include <api-hal-spi.h>
|
||||
|
||||
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) {
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user