diff --git a/applications/applications.c b/applications/applications.c index b667f196..e484bc8e 100644 --- a/applications/applications.c +++ b/applications/applications.c @@ -34,6 +34,7 @@ int32_t sd_filesystem(void* p); int32_t app_subghz(void* p); int32_t gui_test(void* p); +int32_t keypad_test(void* p); const FlipperApplication FLIPPER_SERVICES[] = { #ifdef APP_CLI @@ -153,6 +154,10 @@ const FlipperApplication FLIPPER_SERVICES[] = { #ifdef APP_SUBGHZ {.app = app_subghz, .name = "app_subghz", .stack_size = 1024, .icon = A_Plugins_14}, #endif + +#ifdef APP_KEYPAD_TEST + {.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14}, +#endif }; const size_t FLIPPER_SERVICES_COUNT = sizeof(FLIPPER_SERVICES) / sizeof(FlipperApplication); @@ -229,6 +234,11 @@ const FlipperApplication FLIPPER_PLUGINS[] = { #ifdef BUILD_SUBGHZ {.app = app_subghz, .name = "app_subghz", .stack_size = 1024, .icon = A_Plugins_14}, #endif + +#ifdef BUILD_KEYPAD_TEST + {.app = keypad_test, .name = "keypad_test", .icon = A_Plugins_14}, +#endif + }; const size_t FLIPPER_PLUGINS_COUNT = sizeof(FLIPPER_PLUGINS) / sizeof(FlipperApplication); diff --git a/applications/applications.mk b/applications/applications.mk index fe6a5092..99855836 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -30,6 +30,7 @@ BUILD_MUSIC_PLAYER = 1 BUILD_FLOOPPER_BLOOPPER = 1 BUILD_IBUTTON = 1 BUILD_GUI_TEST = 1 +BUILD_KEYPAD_TEST = 1 BUILD_SUBGHZ = 1 endif @@ -222,6 +223,19 @@ C_SOURCES += $(wildcard $(APP_DIR)/examples/vibro.c) APP_INPUT = 1 endif +APP_KEYPAD_TEST ?= 0 +ifeq ($(APP_KEYPAD_TEST), 1) +CFLAGS += -DAPP_KEYPAD_TEST +BUILD_KEYPAD_TEST = 1 +endif +BUILD_KEYPAD_TEST ?= 0 +ifeq ($(BUILD_KEYPAD_TEST), 1) +CFLAGS += -DBUILD_KEYPAD_TEST +C_SOURCES += $(APP_DIR)/examples/keypad_test.c +BUILD_KEYPAD_TEST = 1 +endif + + APP_GPIO_DEMO ?= 0 ifeq ($(APP_GPIO_DEMO), 1) CFLAGS += -DAPP_GPIO_DEMO diff --git a/applications/examples/keypad_test.c b/applications/examples/keypad_test.c new file mode 100644 index 00000000..01fd6070 --- /dev/null +++ b/applications/examples/keypad_test.c @@ -0,0 +1,189 @@ +#include +#include +#include + +extern TIM_HandleTypeDef SPEAKER_TIM; + +typedef struct { + bool press[5]; + uint16_t up; + uint16_t down; + uint16_t left; + uint16_t right; + uint16_t ok; +} State; + +typedef enum { + EventTypeTick, + EventTypeKey, +} EventType; + +typedef struct { + union { + InputEvent input; + } value; + EventType type; +} AppEvent; + +static void reset_state(State* state) { + state->left = 0; + state->right = 0; + state->up = 0; + state->down = 0; + state->ok = 0; +} + +static void render_callback(Canvas* canvas, void* ctx) { + State* state = (State*)acquire_mutex((ValueMutex*)ctx, 25); + canvas_clear(canvas); + char strings[5][20]; + + sprintf(strings[0], "Ok: %d", state->ok); + sprintf(strings[1], "L: %d", state->left); + sprintf(strings[2], "R: %d", state->right); + sprintf(strings[3], "U: %d", state->up); + sprintf(strings[4], "D: %d", state->down); + + canvas_set_font(canvas, FontPrimary); + canvas_draw_str(canvas, 0, 10, "Keypad test"); + + canvas_set_font(canvas, FontSecondary); + canvas_draw_str(canvas, 0, 24, strings[1]); + canvas_draw_str(canvas, 35, 24, strings[2]); + canvas_draw_str(canvas, 0, 36, strings[3]); + canvas_draw_str(canvas, 35, 36, strings[4]); + canvas_draw_str(canvas, 0, 48, strings[0]); + canvas_draw_circle(canvas, 100, 26, 25); + + if(state->press[0]) canvas_draw_disc(canvas, 118, 26, 5); + if(state->press[1]) canvas_draw_disc(canvas, 82, 26, 5); + if(state->press[2]) canvas_draw_disc(canvas, 100, 8, 5); + if(state->press[3]) canvas_draw_disc(canvas, 100, 44, 5); + if(state->press[4]) canvas_draw_disc(canvas, 100, 26, 5); + + canvas_draw_str(canvas, 10, 63, "[back] - reset, hold to exit"); + + release_mutex((ValueMutex*)ctx, state); +} + +static void input_callback(InputEvent* input_event, void* ctx) { + osMessageQueueId_t event_queue = ctx; + + AppEvent event; + event.type = EventTypeKey; + event.value.input = *input_event; + osMessageQueuePut(event_queue, &event, 0, 0); +} + +int32_t keypad_test(void* p) { + osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL); + furi_check(event_queue); + + State _state = {{false, false, false, false, false}, 0, 0, 0, 0, 0}; + + ValueMutex state_mutex; + if(!init_mutex(&state_mutex, &_state, sizeof(State))) { + printf("[keypad_test] cannot create mutex\r\n"); + return 0; + } + + ViewPort* view_port = view_port_alloc(); + + view_port_draw_callback_set(view_port, render_callback, &state_mutex); + view_port_input_callback_set(view_port, input_callback, event_queue); + + // Open GUI and register view_port + Gui* gui = furi_record_open("gui"); + gui_add_view_port(gui, view_port, GuiLayerFullscreen); + + AppEvent event; + while(1) { + 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.type == InputTypeLong && + event.value.input.key == InputKeyBack) { + printf("[keypad test] bye!\r\n"); + release_mutex(&state_mutex, state); + break; + } + + if(event.value.input.type == InputTypeShort && + event.value.input.key == InputKeyBack) { + reset_state(state); + } + + if(event.value.input.key == InputKeyRight) { + if(event.value.input.type == InputTypePress) { + state->press[0] = true; + } else if(event.value.input.type == InputTypeRelease) { + state->press[0] = false; + } + + if(event.value.input.type == InputTypeShort) { + ++state->right; + } + } + + if(event.value.input.key == InputKeyLeft) { + if(event.value.input.type == InputTypePress) { + state->press[1] = true; + } else if(event.value.input.type == InputTypeRelease) { + state->press[1] = false; + } + + if(event.value.input.type == InputTypeShort) { + ++state->left; + } + } + + if(event.value.input.key == InputKeyUp) { + if(event.value.input.type == InputTypePress) { + state->press[2] = true; + } else if(event.value.input.type == InputTypeRelease) { + state->press[2] = false; + } + + if(event.value.input.type == InputTypeShort) { + ++state->up; + } + } + + if(event.value.input.key == InputKeyDown) { + if(event.value.input.type == InputTypePress) { + state->press[3] = true; + } else if(event.value.input.type == InputTypeRelease) { + state->press[3] = false; + } + + if(event.value.input.type == InputTypeShort) { + ++state->down; + } + } + + if(event.value.input.key == InputKeyOk) { + if(event.value.input.type == InputTypePress) { + state->press[4] = true; + } else if(event.value.input.type == InputTypeRelease) { + state->press[4] = false; + } + + if(event.value.input.type == InputTypeShort) { + ++state->ok; + } + } + } + } + view_port_update(view_port); + release_mutex(&state_mutex, state); + } + // remove & free all stuff created by app + gui_remove_view_port(gui, view_port); + view_port_free(view_port); + osMessageQueueDelete(event_queue); + delete_mutex(&state_mutex); + + return 0; +} \ No newline at end of file diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index 6c68176a..9927993c 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -216,6 +216,20 @@ void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_ u8g2_DrawLine(&canvas->fb, x1, y1, x2, y2); } +void canvas_draw_circle(Canvas* canvas, uint8_t x, uint8_t y, uint8_t radius) { + furi_assert(canvas); + x += canvas->offset_x; + y += canvas->offset_y; + u8g2_DrawCircle(&canvas->fb, x, y, radius, U8G2_DRAW_ALL); +} + +void canvas_draw_disc(Canvas* canvas, uint8_t x, uint8_t y, uint8_t radius) { + furi_assert(canvas); + x += canvas->offset_x; + y += canvas->offset_y; + u8g2_DrawDisc(&canvas->fb, x, y, radius, U8G2_DRAW_ALL); +} + void canvas_draw_xbm( Canvas* canvas, uint8_t x, diff --git a/applications/gui/canvas.h b/applications/gui/canvas.h index 9cfeb2b0..c3a04ed5 100644 --- a/applications/gui/canvas.h +++ b/applications/gui/canvas.h @@ -132,6 +132,16 @@ void canvas_draw_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint */ void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); +/* + * Draw circle at x,y with radius r + */ +void canvas_draw_circle(Canvas* canvas, uint8_t x, uint8_t y, uint8_t r); + +/* + * Draw disc at x,y with radius r + */ +void canvas_draw_disc(Canvas* canvas, uint8_t x, uint8_t y, uint8_t r); + /* * Draw glyph */