From 665f6d7d9c20704430723f5fbfb718cae4a8666b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=81=82=E3=81=8F?= Date: Mon, 26 Oct 2020 20:00:17 +0300 Subject: [PATCH] Assets, Icons, UI toolkit. Part 1. (#202) * Assets: import from gdrive * Assets: fully working build pipeline and registry * NFC: menu icon * Gui: layers. Irukagotchi: base app to handle input on idle screen. Makefile: reboot after flash in dfu mode. * ValueMutex: with lambda * Assets: proper animation frames sorting * ValueMutex: proper furi_open usage * Assets,GUI: split icon into icon data and icon state. * Format source code * Docker: add python3 and imagemagic * Irukagotchi: cleanup * GUI: event lock moved to gui. * Rfid: proper gui layer * GUI: elements. Menu: frame and scroll * GUI, Menu: format code. * Menu: dual font main menu * Menu: format sources * GUI: 0 total scrollbar * CI: enable lfs * Menu: pixel perfect main menu Co-authored-by: Aleksandr Kutuzov Co-authored-by: aanper --- .github/workflows/ci.yml | 1 + applications/app-loader/app-loader.c | 2 +- applications/applications.h | 5 + applications/applications.mk | 8 + .../cc1101-workaround/cc1101-workaround.cpp | 2 +- applications/gui/canvas.c | 47 +++++ applications/gui/canvas.h | 6 + applications/gui/elements.c | 31 +++ applications/gui/elements.h | 8 + applications/gui/gui.c | 173 +++++++++------- applications/gui/gui.h | 16 +- applications/gui/gui_event.c | 33 +--- applications/gui/gui_event.h | 4 - applications/gui/gui_i.h | 2 + applications/gui/icon.c | 63 ++++++ applications/gui/icon.h | 21 ++ applications/gui/icon_i.h | 21 ++ applications/gui/widget.c | 6 +- applications/irda/irda.c | 2 +- applications/irukagotchi/irukagotchi.c | 69 +++++++ applications/irukagotchi/irukagotchi.h | 3 + applications/lf-rfid/lf-rfid.c | 2 +- applications/menu/menu.c | 92 ++++++--- applications/menu/menu_item.c | 25 ++- applications/menu/menu_item.h | 12 +- applications/nfc/nfc.c | 38 ++-- assets/.gitignore | 1 + assets/ReadMe.md | 17 ++ assets/assets.mk | 10 + assets/assets.py | 184 ++++++++++++++++++ assets/icons/MainMenu/125khz_14/frame_01.png | 3 + assets/icons/MainMenu/125khz_14/frame_02.png | 3 + assets/icons/MainMenu/125khz_14/frame_03.png | 3 + assets/icons/MainMenu/125khz_14/frame_04.png | 3 + assets/icons/MainMenu/125khz_14/frame_rate | 1 + .../icons/MainMenu/Bluetooth_14/frame_01.png | 3 + .../icons/MainMenu/Bluetooth_14/frame_02.png | 3 + .../icons/MainMenu/Bluetooth_14/frame_03.png | 3 + .../icons/MainMenu/Bluetooth_14/frame_04.png | 3 + .../icons/MainMenu/Bluetooth_14/frame_05.png | 3 + .../icons/MainMenu/Bluetooth_14/frame_06.png | 3 + assets/icons/MainMenu/Bluetooth_14/frame_rate | 1 + .../MainMenu/FileManager_14/frame_01.png | 3 + .../MainMenu/FileManager_14/frame_02.png | 3 + .../MainMenu/FileManager_14/frame_03.png | 3 + .../MainMenu/FileManager_14/frame_04.png | 3 + .../MainMenu/FileManager_14/frame_05.png | 3 + .../MainMenu/FileManager_14/frame_06.png | 3 + .../MainMenu/FileManager_14/frame_07.png | 3 + .../MainMenu/FileManager_14/frame_08.png | 3 + .../MainMenu/FileManager_14/frame_09.png | 3 + .../MainMenu/FileManager_14/frame_10.png | 3 + .../icons/MainMenu/FileManager_14/frame_rate | 1 + assets/icons/MainMenu/GPIO_14/frame_01.png | 3 + assets/icons/MainMenu/GPIO_14/frame_02.png | 3 + assets/icons/MainMenu/GPIO_14/frame_03.png | 3 + assets/icons/MainMenu/GPIO_14/frame_04.png | 3 + assets/icons/MainMenu/GPIO_14/frame_05.png | 3 + assets/icons/MainMenu/GPIO_14/frame_06.png | 3 + assets/icons/MainMenu/GPIO_14/frame_07.png | 3 + assets/icons/MainMenu/GPIO_14/frame_08.png | 3 + assets/icons/MainMenu/GPIO_14/frame_rate | 1 + .../icons/MainMenu/Infrared_14/frame_01.png | 3 + .../icons/MainMenu/Infrared_14/frame_02.png | 3 + .../icons/MainMenu/Infrared_14/frame_03.png | 3 + .../icons/MainMenu/Infrared_14/frame_04.png | 3 + .../icons/MainMenu/Infrared_14/frame_05.png | 3 + .../icons/MainMenu/Infrared_14/frame_06.png | 3 + assets/icons/MainMenu/Infrared_14/frame_rate | 1 + assets/icons/MainMenu/NFC_14/frame_01.png | 3 + assets/icons/MainMenu/NFC_14/frame_02.png | 3 + assets/icons/MainMenu/NFC_14/frame_03.png | 3 + assets/icons/MainMenu/NFC_14/frame_04.png | 3 + assets/icons/MainMenu/NFC_14/frame_rate | 1 + assets/icons/MainMenu/Sub1ghz_14/frame_01.png | 3 + assets/icons/MainMenu/Sub1ghz_14/frame_02.png | 3 + assets/icons/MainMenu/Sub1ghz_14/frame_03.png | 3 + assets/icons/MainMenu/Sub1ghz_14/frame_04.png | 3 + assets/icons/MainMenu/Sub1ghz_14/frame_05.png | 3 + assets/icons/MainMenu/Sub1ghz_14/frame_06.png | 3 + assets/icons/MainMenu/Sub1ghz_14/frame_rate | 1 + .../icons/MainMenu/Tamagotchi_14/frame_01.png | 3 + .../icons/MainMenu/Tamagotchi_14/frame_02.png | 3 + .../icons/MainMenu/Tamagotchi_14/frame_03.png | 3 + .../icons/MainMenu/Tamagotchi_14/frame_04.png | 3 + .../icons/MainMenu/Tamagotchi_14/frame_05.png | 3 + .../icons/MainMenu/Tamagotchi_14/frame_06.png | 3 + .../icons/MainMenu/Tamagotchi_14/frame_rate | 1 + assets/icons/MainMenu/U2F_14/frame_01.png | 3 + assets/icons/MainMenu/U2F_14/frame_02.png | 3 + assets/icons/MainMenu/U2F_14/frame_03.png | 3 + assets/icons/MainMenu/U2F_14/frame_04.png | 3 + assets/icons/MainMenu/U2F_14/frame_rate | 1 + assets/icons/MainMenu/iButton_14/frame_01.png | 3 + assets/icons/MainMenu/iButton_14/frame_02.png | 3 + assets/icons/MainMenu/iButton_14/frame_03.png | 3 + assets/icons/MainMenu/iButton_14/frame_04.png | 3 + assets/icons/MainMenu/iButton_14/frame_05.png | 3 + assets/icons/MainMenu/iButton_14/frame_06.png | 3 + assets/icons/MainMenu/iButton_14/frame_07.png | 3 + assets/icons/MainMenu/iButton_14/frame_rate | 1 + assets/icons/StatusBar/BadUsb_9x8.png | 3 + assets/icons/StatusBar/Battery_19x8.png | 3 + assets/icons/StatusBar/Bluetooth_5x8.png | 3 + assets/icons/StatusBar/SDcardFail_11x8.png | 3 + assets/icons/StatusBar/SDcardMounted_11x8.png | 3 + assets/icons/StatusBar/USBConnected_15x8.png | 3 + assets/output/.gitignore | 1 + core/api-basic/valuemutex.h | 14 ++ docker/Dockerfile | 2 + docker/syntax_check.sh | 1 + firmware/Makefile | 1 + lib/lib.mk | 1 + lib/u8g2/u8g2_line.c | 92 +++++++++ make/base.mk | 1 + make/rules.mk | 13 +- 116 files changed, 1057 insertions(+), 184 deletions(-) create mode 100644 applications/gui/elements.c create mode 100644 applications/gui/elements.h create mode 100644 applications/gui/icon.c create mode 100644 applications/gui/icon.h create mode 100644 applications/gui/icon_i.h create mode 100644 applications/irukagotchi/irukagotchi.c create mode 100644 applications/irukagotchi/irukagotchi.h create mode 100644 assets/.gitignore create mode 100644 assets/ReadMe.md create mode 100644 assets/assets.mk create mode 100755 assets/assets.py create mode 100644 assets/icons/MainMenu/125khz_14/frame_01.png create mode 100644 assets/icons/MainMenu/125khz_14/frame_02.png create mode 100644 assets/icons/MainMenu/125khz_14/frame_03.png create mode 100644 assets/icons/MainMenu/125khz_14/frame_04.png create mode 100644 assets/icons/MainMenu/125khz_14/frame_rate create mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_01.png create mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_02.png create mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_03.png create mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_04.png create mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_05.png create mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_06.png create mode 100644 assets/icons/MainMenu/Bluetooth_14/frame_rate create mode 100644 assets/icons/MainMenu/FileManager_14/frame_01.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_02.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_03.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_04.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_05.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_06.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_07.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_08.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_09.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_10.png create mode 100644 assets/icons/MainMenu/FileManager_14/frame_rate create mode 100644 assets/icons/MainMenu/GPIO_14/frame_01.png create mode 100644 assets/icons/MainMenu/GPIO_14/frame_02.png create mode 100644 assets/icons/MainMenu/GPIO_14/frame_03.png create mode 100644 assets/icons/MainMenu/GPIO_14/frame_04.png create mode 100644 assets/icons/MainMenu/GPIO_14/frame_05.png create mode 100644 assets/icons/MainMenu/GPIO_14/frame_06.png create mode 100644 assets/icons/MainMenu/GPIO_14/frame_07.png create mode 100644 assets/icons/MainMenu/GPIO_14/frame_08.png create mode 100644 assets/icons/MainMenu/GPIO_14/frame_rate create mode 100644 assets/icons/MainMenu/Infrared_14/frame_01.png create mode 100644 assets/icons/MainMenu/Infrared_14/frame_02.png create mode 100644 assets/icons/MainMenu/Infrared_14/frame_03.png create mode 100644 assets/icons/MainMenu/Infrared_14/frame_04.png create mode 100644 assets/icons/MainMenu/Infrared_14/frame_05.png create mode 100644 assets/icons/MainMenu/Infrared_14/frame_06.png create mode 100644 assets/icons/MainMenu/Infrared_14/frame_rate create mode 100644 assets/icons/MainMenu/NFC_14/frame_01.png create mode 100644 assets/icons/MainMenu/NFC_14/frame_02.png create mode 100644 assets/icons/MainMenu/NFC_14/frame_03.png create mode 100644 assets/icons/MainMenu/NFC_14/frame_04.png create mode 100644 assets/icons/MainMenu/NFC_14/frame_rate create mode 100644 assets/icons/MainMenu/Sub1ghz_14/frame_01.png create mode 100644 assets/icons/MainMenu/Sub1ghz_14/frame_02.png create mode 100644 assets/icons/MainMenu/Sub1ghz_14/frame_03.png create mode 100644 assets/icons/MainMenu/Sub1ghz_14/frame_04.png create mode 100644 assets/icons/MainMenu/Sub1ghz_14/frame_05.png create mode 100644 assets/icons/MainMenu/Sub1ghz_14/frame_06.png create mode 100644 assets/icons/MainMenu/Sub1ghz_14/frame_rate create mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_01.png create mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_02.png create mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_03.png create mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_04.png create mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_05.png create mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_06.png create mode 100644 assets/icons/MainMenu/Tamagotchi_14/frame_rate create mode 100644 assets/icons/MainMenu/U2F_14/frame_01.png create mode 100644 assets/icons/MainMenu/U2F_14/frame_02.png create mode 100644 assets/icons/MainMenu/U2F_14/frame_03.png create mode 100644 assets/icons/MainMenu/U2F_14/frame_04.png create mode 100644 assets/icons/MainMenu/U2F_14/frame_rate create mode 100644 assets/icons/MainMenu/iButton_14/frame_01.png create mode 100644 assets/icons/MainMenu/iButton_14/frame_02.png create mode 100644 assets/icons/MainMenu/iButton_14/frame_03.png create mode 100644 assets/icons/MainMenu/iButton_14/frame_04.png create mode 100644 assets/icons/MainMenu/iButton_14/frame_05.png create mode 100644 assets/icons/MainMenu/iButton_14/frame_06.png create mode 100644 assets/icons/MainMenu/iButton_14/frame_07.png create mode 100644 assets/icons/MainMenu/iButton_14/frame_rate create mode 100644 assets/icons/StatusBar/BadUsb_9x8.png create mode 100644 assets/icons/StatusBar/Battery_19x8.png create mode 100644 assets/icons/StatusBar/Bluetooth_5x8.png create mode 100644 assets/icons/StatusBar/SDcardFail_11x8.png create mode 100644 assets/icons/StatusBar/SDcardMounted_11x8.png create mode 100644 assets/icons/StatusBar/USBConnected_15x8.png create mode 100644 assets/output/.gitignore create mode 100644 lib/u8g2/u8g2_line.c diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa08c9d4..c0758df5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,7 @@ jobs: uses: actions/checkout@v2 with: submodules: true + lfs: true - uses: satackey/action-docker-layer-caching@v0.0.8 continue-on-error: true diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c index fb5768d9..b9d0fb3a 100644 --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -74,7 +74,7 @@ void app_loader(void* p) { printf("gui is not available\n"); furiac_exit(NULL); } - gui->add_widget(gui, state.widget, WidgetLayerFullscreen); + gui->add_widget(gui, state.widget, GuiLayerFullscreen); { Menu* menu = acquire_mutex_block(menu_mutex); diff --git a/applications/applications.h b/applications/applications.h index bfca7501..003d078d 100644 --- a/applications/applications.h +++ b/applications/applications.h @@ -30,6 +30,7 @@ void app_loader(void* p); void cc1101_workaround(void* p); void lf_rfid_workaround(void* p); void nfc_task(void* p); +void irukagotchi_task(void* p); const FlipperStartupApp FLIPPER_STARTUP[] = { #ifdef APP_DISPLAY @@ -54,6 +55,10 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { {.app = app_loader, .name = "app_loader", .libs = {1, FURI_LIB{"menu_task"}}}, #endif +#ifdef APP_IRUKAGOTCHI + {.app = irukagotchi_task, .name = "irukagotchi_task", .libs = {1, FURI_LIB{"menu_task"}}}, +#endif + #ifdef APP_CC1101 {.app = cc1101_workaround, .name = "cc1101 workaround", .libs = {1, FURI_LIB{"gui_task"}}}, #endif diff --git a/applications/applications.mk b/applications/applications.mk index f8f52696..beaf03d1 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -11,6 +11,7 @@ ifeq ($(APP_RELEASE), 1) APP_MENU = 1 APP_NFC = 1 BUILD_IRDA = 1 +APP_IRUKAGOTCHI = 1 BUILD_EXAMPLE_BLINK = 1 BUILD_EXAMPLE_UART_WRITE = 1 BUILD_EXAMPLE_INPUT_DUMP = 1 @@ -26,6 +27,13 @@ CFLAGS += -DAPP_NFC C_SOURCES += $(wildcard $(APP_DIR)/nfc/*.c) endif +APP_IRUKAGOTCHI ?= 0 +ifeq ($(APP_IRUKAGOTCHI), 1) +APP_MENU = 1 +CFLAGS += -DAPP_IRUKAGOTCHI +C_SOURCES += $(wildcard $(APP_DIR)/irukagotchi/*.c) +endif + APP_MENU ?= 0 ifeq ($(APP_MENU), 1) CFLAGS += -DAPP_MENU diff --git a/applications/cc1101-workaround/cc1101-workaround.cpp b/applications/cc1101-workaround/cc1101-workaround.cpp index 34fb4814..ac66e629 100644 --- a/applications/cc1101-workaround/cc1101-workaround.cpp +++ b/applications/cc1101-workaround/cc1101-workaround.cpp @@ -229,7 +229,7 @@ extern "C" void cc1101_workaround(void* p) { printf("[cc1101] gui is not available\n"); furiac_exit(NULL); } - gui->add_widget(gui, widget, WidgetLayerFullscreen); + gui->add_widget(gui, widget, GuiLayerFullscreen); printf("[cc1101] creating device\n"); GpioPin cs_pin = {CC1101_CS_GPIO_Port, CC1101_CS_Pin}; diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c index 842397bd..4f5af999 100644 --- a/applications/gui/canvas.c +++ b/applications/gui/canvas.c @@ -1,5 +1,7 @@ #include "canvas.h" #include "canvas_i.h" +#include "icon.h" +#include "icon_i.h" #include #include @@ -20,6 +22,11 @@ void canvas_clear(CanvasApi* api); void canvas_color_set(CanvasApi* api, uint8_t color); void canvas_font_set(CanvasApi* api, Font font); void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str); +void canvas_icon_draw(CanvasApi* api, uint8_t x, uint8_t y, Icon* icon); +void canvas_dot_draw(CanvasApi* api, uint8_t x, uint8_t y); +void canvas_box_draw(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height); +void canvas_draw_frame(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height); +void canvas_draw_line(CanvasApi* api, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr); @@ -43,6 +50,11 @@ CanvasApi* canvas_api_init() { canvas->api.set_color = canvas_color_set; canvas->api.set_font = canvas_font_set; canvas->api.draw_str = canvas_str_draw; + canvas->api.draw_icon = canvas_icon_draw; + canvas->api.draw_dot = canvas_dot_draw; + canvas->api.draw_box = canvas_box_draw; + canvas->api.draw_frame = canvas_draw_frame; + canvas->api.draw_line = canvas_draw_line; return (CanvasApi*)canvas; } @@ -112,8 +124,43 @@ void canvas_font_set(CanvasApi* api, Font font) { void canvas_str_draw(CanvasApi* api, uint8_t x, uint8_t y, const char* str) { assert(api); + if(!str) return; Canvas* canvas = (Canvas*)api; x += canvas->offset_x; y += canvas->offset_y; u8g2_DrawStr(&canvas->fb, x, y, str); } + +void canvas_icon_draw(CanvasApi* api, uint8_t x, uint8_t y, Icon* icon) { + assert(api); + if(!icon) return; + Canvas* canvas = (Canvas*)api; + x += canvas->offset_x; + y += canvas->offset_y; + u8g2_DrawXBM( + &canvas->fb, x, y, icon_get_width(icon), icon_get_height(icon), icon_get_data(icon)); +} + +void canvas_dot_draw(CanvasApi* api, uint8_t x, uint8_t y) { + assert(api); + Canvas* canvas = (Canvas*)api; + u8g2_DrawPixel(&canvas->fb, x, y); +} + +void canvas_box_draw(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { + assert(api); + Canvas* canvas = (Canvas*)api; + u8g2_DrawBox(&canvas->fb, x, y, width, height); +} + +void canvas_draw_frame(CanvasApi* api, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { + assert(api); + Canvas* canvas = (Canvas*)api; + u8g2_DrawFrame(&canvas->fb, x, y, width, height); +} + +void canvas_draw_line(CanvasApi* api, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2) { + assert(api); + Canvas* canvas = (Canvas*)api; + u8g2_DrawLine(&canvas->fb, x1, y1, x2, y2); +} diff --git a/applications/gui/canvas.h b/applications/gui/canvas.h index 237a75de..2d0c5edb 100644 --- a/applications/gui/canvas.h +++ b/applications/gui/canvas.h @@ -2,6 +2,7 @@ #include #include +#include typedef enum { ColorWhite = 0x00, @@ -24,4 +25,9 @@ struct CanvasApi { void (*set_font)(CanvasApi* canvas, Font font); void (*draw_str)(CanvasApi* canvas, uint8_t x, uint8_t y, const char* str); + void (*draw_icon)(CanvasApi* canvas, uint8_t x, uint8_t y, Icon* icon); + void (*draw_dot)(CanvasApi* canvas, uint8_t x, uint8_t y); + void (*draw_box)(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height); + void (*draw_frame)(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height); + void (*draw_line)(CanvasApi* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_t y2); }; diff --git a/applications/gui/elements.c b/applications/gui/elements.c new file mode 100644 index 00000000..fef63634 --- /dev/null +++ b/applications/gui/elements.c @@ -0,0 +1,31 @@ +#include "elements.h" + +void elements_scrollbar(CanvasApi* canvas, uint8_t pos, uint8_t total) { + uint8_t width = canvas->width(canvas); + uint8_t height = canvas->height(canvas); + // prevent overflows + canvas->set_color(canvas, ColorWhite); + canvas->draw_box(canvas, width - 3, 0, 3, height); + // dot line + canvas->set_color(canvas, ColorBlack); + for(uint8_t i = 0; i < height; i += 2) { + canvas->draw_dot(canvas, width - 2, i); + } + // Position block + if(total) { + uint8_t block_h = ((float)height) / total; + canvas->draw_box(canvas, width - 3, block_h * pos, 3, block_h); + } +} + +void elements_frame(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height) { + canvas->draw_line(canvas, x + 2, y, x + width - 2, y); + canvas->draw_line(canvas, x + 1, y + height - 1, x + width, y + height - 1); + canvas->draw_line(canvas, x + 2, y + height, x + width - 1, y + height); + + canvas->draw_line(canvas, x, y + 2, x, y + height - 2); + canvas->draw_line(canvas, x + width - 1, y + 1, x + width - 1, y + height - 2); + canvas->draw_line(canvas, x + width, y + 2, x + width, y + height - 2); + + canvas->draw_dot(canvas, x + 1, y + 1); +} \ No newline at end of file diff --git a/applications/gui/elements.h b/applications/gui/elements.h new file mode 100644 index 00000000..812ce99c --- /dev/null +++ b/applications/gui/elements.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include "canvas.h" + +void elements_scrollbar(CanvasApi* canvas, uint8_t pos, uint8_t total); + +void elements_frame(CanvasApi* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height); diff --git a/applications/gui/gui.c b/applications/gui/gui.c index 38243562..cdfa3f7e 100644 --- a/applications/gui/gui.c +++ b/applications/gui/gui.c @@ -3,8 +3,8 @@ #include #include -#include #include +#include #include "gui_event.h" #include "canvas.h" @@ -18,54 +18,10 @@ struct Gui { GuiApi api; GuiEvent* event; CanvasApi* canvas_api; - WidgetArray_t widgets_status_bar; - WidgetArray_t widgets; - WidgetArray_t widgets_fs; - WidgetArray_t widgets_dialog; + WidgetArray_t layers[GuiLayerMAX]; + osMutexId_t mutex; }; -void gui_add_widget(GuiApi* gui_api, Widget* widget, WidgetLayer layer) { - assert(gui_api); - assert(widget); - Gui* gui = (Gui*)gui_api; - - // TODO add mutex on widget array - WidgetArray_t* widget_array = NULL; - - switch(layer) { - case WidgetLayerStatusBar: - widget_array = &gui->widgets_status_bar; - break; - case WidgetLayerMain: - widget_array = &gui->widgets; - break; - case WidgetLayerFullscreen: - widget_array = &gui->widgets_fs; - break; - case WidgetLayerDialog: - widget_array = &gui->widgets_dialog; - break; - default: - break; - } - - assert(widget_array); - - gui_event_lock(gui->event); - WidgetArray_push_back(*widget_array, widget); - widget_gui_set(widget, gui); - gui_event_unlock(gui->event); - - gui_update(gui); -} - -void gui_update(Gui* gui) { - assert(gui); - GuiMessage message; - message.type = GuiMessageTypeRedraw; - gui_event_messsage_send(gui->event, &message); -} - Widget* gui_widget_find_enabled(WidgetArray_t array) { size_t widgets_count = WidgetArray_size(array); for(size_t i = 0; i < widgets_count; i++) { @@ -77,9 +33,16 @@ Widget* gui_widget_find_enabled(WidgetArray_t array) { return NULL; } +void gui_update(Gui* gui) { + assert(gui); + GuiMessage message; + message.type = GuiMessageTypeRedraw; + gui_event_messsage_send(gui->event, &message); +} + bool gui_redraw_fs(Gui* gui) { canvas_frame_set(gui->canvas_api, 0, 0, 128, 64); - Widget* widget = gui_widget_find_enabled(gui->widgets_fs); + Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerFullscreen]); if(widget) { widget_draw(widget, gui->canvas_api); return true; @@ -88,64 +51,128 @@ bool gui_redraw_fs(Gui* gui) { } } -void gui_redraw_status_bar(Gui* gui) { +bool gui_redraw_status_bar(Gui* gui) { canvas_frame_set(gui->canvas_api, 0, 0, 128, 64); - Widget* widget = gui_widget_find_enabled(gui->widgets_status_bar); - if(widget) widget_draw(widget, gui->canvas_api); + Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerStatusBar]); + if(widget) { + widget_draw(widget, gui->canvas_api); + return true; + } + return false; } -void gui_redraw_normal(Gui* gui) { +bool gui_redraw_normal(Gui* gui) { canvas_frame_set(gui->canvas_api, 0, 9, 128, 55); - Widget* widget = gui_widget_find_enabled(gui->widgets); - if(widget) widget_draw(widget, gui->canvas_api); + Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerMain]); + if(widget) { + widget_draw(widget, gui->canvas_api); + return true; + } + return false; } -void gui_redraw_dialogs(Gui* gui) { - canvas_frame_set(gui->canvas_api, 10, 20, 118, 44); - Widget* widget = gui_widget_find_enabled(gui->widgets_dialog); - if(widget) widget_draw(widget, gui->canvas_api); +bool gui_redraw_none(Gui* gui) { + canvas_frame_set(gui->canvas_api, 0, 9, 118, 44); + Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerNone]); + if(widget) { + widget_draw(widget, gui->canvas_api); + return true; + } + + return false; } void gui_redraw(Gui* gui) { assert(gui); + gui_lock(gui); if(!gui_redraw_fs(gui)) { + if(!gui_redraw_normal(gui)) { + gui_redraw_none(gui); + } gui_redraw_status_bar(gui); - gui_redraw_normal(gui); } - gui_redraw_dialogs(gui); canvas_commit(gui->canvas_api); + gui_unlock(gui); } void gui_input(Gui* gui, InputEvent* input_event) { assert(gui); + gui_lock(gui); - Widget* widget = gui_widget_find_enabled(gui->widgets_dialog); - if(!widget) widget = gui_widget_find_enabled(gui->widgets_fs); - if(!widget) widget = gui_widget_find_enabled(gui->widgets); + Widget* widget = gui_widget_find_enabled(gui->layers[GuiLayerFullscreen]); + if(!widget) widget = gui_widget_find_enabled(gui->layers[GuiLayerMain]); + if(!widget) widget = gui_widget_find_enabled(gui->layers[GuiLayerNone]); if(widget) { widget_input(widget, input_event); } + + gui_unlock(gui); +} + +void gui_lock(Gui* gui) { + assert(gui); + assert(osMutexAcquire(gui->mutex, osWaitForever) == osOK); +} + +void gui_unlock(Gui* gui) { + assert(gui); + assert(osMutexRelease(gui->mutex) == osOK); +} + +void gui_add_widget(GuiApi* gui_api, Widget* widget, GuiLayer layer) { + assert(gui_api); + assert(widget); + assert(layer < GuiLayerMAX); + Gui* gui = (Gui*)gui_api; + + gui_lock(gui); + WidgetArray_push_back(gui->layers[layer], widget); + widget_gui_set(widget, gui); + gui_unlock(gui); + gui_update(gui); +} + +void gui_remove_widget(GuiApi* gui_api, Widget* widget) { + assert(gui_api); + assert(widget); + Gui* gui = (Gui*)gui_api; + + gui_lock(gui); + + widget_gui_set(widget, NULL); + WidgetArray_it_t it; + for(size_t i = 0; i < GuiLayerMAX; i++) { + WidgetArray_it(it, gui->layers[i]); + while(!WidgetArray_end_p(it)) { + if(*WidgetArray_ref(it) == widget) { + WidgetArray_remove(gui->layers[i], it); + } + WidgetArray_next(it); + } + } + + gui_unlock(gui); } Gui* gui_alloc() { Gui* gui = furi_alloc(sizeof(Gui)); - - // Initialize widget arrays - WidgetArray_init(gui->widgets_status_bar); - WidgetArray_init(gui->widgets); - WidgetArray_init(gui->widgets_fs); - WidgetArray_init(gui->widgets_dialog); - + // Set API functions + gui->api.add_widget = gui_add_widget; + gui->api.remove_widget = gui_remove_widget; + // Allocate mutex + gui->mutex = osMutexNew(NULL); + assert(gui->mutex); // Event dispatcher gui->event = gui_event_alloc(); - // Drawing canvas api gui->canvas_api = canvas_api_init(); - - gui->api.add_widget = gui_add_widget; + // Compose Layers + for(size_t i = 0; i < GuiLayerMAX; i++) { + WidgetArray_init(gui->layers[i]); + } return gui; } diff --git a/applications/gui/gui.h b/applications/gui/gui.h index 8db1cc20..69cd5c37 100644 --- a/applications/gui/gui.h +++ b/applications/gui/gui.h @@ -4,15 +4,17 @@ #include "canvas.h" typedef enum { - WidgetLayerStatusBar, - WidgetLayerMain, - WidgetLayerFullscreen, - WidgetLayerDialog -} WidgetLayer; + GuiLayerNone, /* Special layer for internal use only */ -typedef struct Widget Widget; + GuiLayerStatusBar, /* Status bar widget layer */ + GuiLayerMain, /* Main widget layer, status bar is shown */ + GuiLayerFullscreen, /* Fullscreen widget layer */ + + GuiLayerMAX /* Don't use or move, special value */ +} GuiLayer; typedef struct GuiApi GuiApi; struct GuiApi { - void (*add_widget)(GuiApi* gui_api, Widget* widget, WidgetLayer layer); + void (*add_widget)(GuiApi* gui_api, Widget* widget, GuiLayer layer); + void (*remove_widget)(GuiApi* gui_api, Widget* widget); }; diff --git a/applications/gui/gui_event.c b/applications/gui/gui_event.c index b9dfffc9..c178b6e4 100644 --- a/applications/gui/gui_event.c +++ b/applications/gui/gui_event.c @@ -8,7 +8,6 @@ struct GuiEvent { PubSub* input_event_record; osMessageQueueId_t mqueue; - osMutexId_t lock_mutex; }; void gui_event_input_events_callback(const void* value, void* ctx) { @@ -33,37 +32,15 @@ GuiEvent* gui_event_alloc() { assert(gui_event->input_event_record != NULL); subscribe_pubsub(gui_event->input_event_record, gui_event_input_events_callback, gui_event); - // Lock mutex - gui_event->lock_mutex = osMutexNew(NULL); - assert(gui_event->lock_mutex); - gui_event_lock(gui_event); - return gui_event; } void gui_event_free(GuiEvent* gui_event) { - osStatus_t status; assert(gui_event); - gui_event_unlock(gui_event); - status = osMessageQueueDelete(gui_event->mqueue); - assert(status == osOK); + assert(osMessageQueueDelete(gui_event->mqueue) == osOK); free(gui_event); } -void gui_event_lock(GuiEvent* gui_event) { - osStatus_t status; - assert(gui_event); - status = osMutexAcquire(gui_event->lock_mutex, osWaitForever); - assert(status == osOK); -} - -void gui_event_unlock(GuiEvent* gui_event) { - osStatus_t status; - assert(gui_event); - status = osMutexRelease(gui_event->lock_mutex); - assert(status == osOK); -} - void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message) { assert(gui_event); assert(message); @@ -71,12 +48,10 @@ void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message) { } GuiMessage gui_event_message_next(GuiEvent* gui_event) { - osStatus_t status; assert(gui_event); GuiMessage message; - gui_event_unlock(gui_event); - status = osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever); - assert(status == osOK); - gui_event_lock(gui_event); + + assert(osMessageQueueGet(gui_event->mqueue, &message, NULL, osWaitForever) == osOK); + return message; } diff --git a/applications/gui/gui_event.h b/applications/gui/gui_event.h index 89ba4ee2..fc2f358f 100644 --- a/applications/gui/gui_event.h +++ b/applications/gui/gui_event.h @@ -20,10 +20,6 @@ GuiEvent* gui_event_alloc(); void gui_event_free(GuiEvent* gui_event); -void gui_event_lock(GuiEvent* gui_event); - -void gui_event_unlock(GuiEvent* gui_event); - void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message); GuiMessage gui_event_message_next(GuiEvent* gui_event); diff --git a/applications/gui/gui_i.h b/applications/gui/gui_i.h index a64874c1..4200e7e1 100644 --- a/applications/gui/gui_i.h +++ b/applications/gui/gui_i.h @@ -3,3 +3,5 @@ typedef struct Gui Gui; void gui_update(Gui* gui); +void gui_lock(Gui* gui); +void gui_unlock(Gui* gui); \ No newline at end of file diff --git a/applications/gui/icon.c b/applications/gui/icon.c new file mode 100644 index 00000000..97d4639c --- /dev/null +++ b/applications/gui/icon.c @@ -0,0 +1,63 @@ +#include "icon.h" +#include "icon_i.h" + +#include +#include +#include + +Icon* icon_alloc(const IconData* data) { + Icon* icon = furi_alloc(sizeof(Icon)); + icon->data = data; + return icon; +} + +void icon_free(Icon* icon) { + assert(icon); + free(icon); +} + +const uint8_t* icon_get_data(Icon* icon) { + assert(icon); + if(icon->tick) { + uint32_t now = osKernelGetTickCount(); + if(now < icon->tick) { + icon->tick = now; + icon_next_frame(icon); + } else if(now - icon->tick > osKernelGetTickFreq() / icon->data->frame_rate) { + icon->tick = now; + icon_next_frame(icon); + } + } + return icon->data->frames[icon->frame]; +} + +void icon_next_frame(Icon* icon) { + assert(icon); + icon->frame = (icon->frame + 1) % icon->data->frame_count; +} + +uint8_t icon_get_width(Icon* icon) { + assert(icon); + return icon->data->width; +} + +uint8_t icon_get_height(Icon* icon) { + assert(icon); + return icon->data->height; +} + +bool icon_is_animated(Icon* icon) { + assert(icon); + return icon->data->frame_count > 1; +} + +void icon_start_animation(Icon* icon) { + assert(icon); + icon->tick = osKernelGetTickCount(); +} + +void icon_stop_animation(Icon* icon) { + assert(icon); + icon->tick = 0; + icon->frame = 0; +} diff --git a/applications/gui/icon.h b/applications/gui/icon.h new file mode 100644 index 00000000..8d16cb1d --- /dev/null +++ b/applications/gui/icon.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +typedef struct IconData IconData; +typedef struct Icon Icon; + +Icon* icon_alloc(const IconData* data); + +void icon_free(Icon* icon); + +uint8_t icon_get_width(Icon* icon); + +uint8_t icon_get_height(Icon* icon); + +bool icon_is_animated(Icon* icon); + +void icon_start_animation(Icon* icon); + +void icon_stop_animation(Icon* icon); diff --git a/applications/gui/icon_i.h b/applications/gui/icon_i.h new file mode 100644 index 00000000..22b98316 --- /dev/null +++ b/applications/gui/icon_i.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +struct IconData { + const uint8_t width; + const uint8_t height; + const uint8_t frame_count; + const uint8_t frame_rate; + const uint8_t** frames; +}; + +struct Icon { + const IconData* data; + uint8_t frame; + uint32_t tick; +}; + +const uint8_t* icon_get_data(Icon* icon); + +void icon_next_frame(Icon* icon); diff --git a/applications/gui/widget.c b/applications/gui/widget.c index 4b22679d..2a97a593 100644 --- a/applications/gui/widget.c +++ b/applications/gui/widget.c @@ -32,8 +32,10 @@ void widget_free(Widget* widget) { void widget_enabled_set(Widget* widget, bool enabled) { assert(widget); - widget->is_enabled = enabled; - widget_update(widget); + if(widget->is_enabled != enabled) { + widget->is_enabled = enabled; + widget_update(widget); + } } bool widget_is_enabled(Widget* widget) { diff --git a/applications/irda/irda.c b/applications/irda/irda.c index 7e6c3ce8..13747ef4 100644 --- a/applications/irda/irda.c +++ b/applications/irda/irda.c @@ -262,7 +262,7 @@ void irda(void* p) { printf("gui is not available\n"); furiac_exit(NULL); } - gui->add_widget(gui, widget, WidgetLayerFullscreen); + gui->add_widget(gui, widget, GuiLayerFullscreen); AppEvent event; while(1) { diff --git a/applications/irukagotchi/irukagotchi.c b/applications/irukagotchi/irukagotchi.c new file mode 100644 index 00000000..2e317d9e --- /dev/null +++ b/applications/irukagotchi/irukagotchi.c @@ -0,0 +1,69 @@ +#include "irukagotchi.h" + +#include +#include + +#include +#include +#include +#include + +#include + +struct Irukagotchi { + Icon* icon; + Widget* widget; + ValueMutex* menu_vm; +}; + +void irukagotchi_draw_callback(CanvasApi* canvas, void* context) { + Irukagotchi* irukagotchi = context; + + canvas->clear(canvas); + canvas->set_color(canvas, ColorBlack); + canvas->set_font(canvas, FontPrimary); + canvas->draw_icon(canvas, 10, 20, irukagotchi->icon); + canvas->draw_str(canvas, 30, 32, "Irukagotchi"); +} + +void irukagotchi_input_callback(InputEvent* event, void* context) { + Irukagotchi* irukagotchi = context; + + if(!event->state || event->input != InputOk) return; + + with_value_mutex( + irukagotchi->menu_vm, (Menu * menu) { menu_ok(menu); }); +} + +Irukagotchi* irukagotchi_alloc() { + Irukagotchi* irukagotchi = furi_alloc(sizeof(Irukagotchi)); + + irukagotchi->icon = assets_icons_get(A_Tamagotchi_14); + icon_start_animation(irukagotchi->icon); + + irukagotchi->widget = widget_alloc(); + widget_draw_callback_set(irukagotchi->widget, irukagotchi_draw_callback, irukagotchi); + widget_input_callback_set(irukagotchi->widget, irukagotchi_input_callback, irukagotchi); + + irukagotchi->menu_vm = furi_open("menu"); + assert(irukagotchi->menu_vm); + + return irukagotchi; +} + +void irukagotchi_task() { + Irukagotchi* irukagotchi = irukagotchi_alloc(); + + FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); + assert(gui_record); + GuiApi* gui = furi_take(gui_record); + assert(gui); + gui->add_widget(gui, irukagotchi->widget, GuiLayerNone); + furi_commit(gui_record); + + furiac_ready(); + + while(1) { + osDelay(osWaitForever); + } +} \ No newline at end of file diff --git a/applications/irukagotchi/irukagotchi.h b/applications/irukagotchi/irukagotchi.h new file mode 100644 index 00000000..2a1f6eb6 --- /dev/null +++ b/applications/irukagotchi/irukagotchi.h @@ -0,0 +1,3 @@ +#pragma once + +typedef struct Irukagotchi Irukagotchi; diff --git a/applications/lf-rfid/lf-rfid.c b/applications/lf-rfid/lf-rfid.c index 54b70acd..7dc8c6dc 100644 --- a/applications/lf-rfid/lf-rfid.c +++ b/applications/lf-rfid/lf-rfid.c @@ -69,7 +69,7 @@ void lf_rfid_workaround(void* p) { printf("gui is not available\n"); furiac_exit(NULL); } - gui->add_widget(gui, widget, WidgetLayerFullscreen); + gui->add_widget(gui, widget, GuiLayerFullscreen); AppEvent event; while(1) { diff --git a/applications/menu/menu.c b/applications/menu/menu.c index 7e6bfb2e..77bb28aa 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -5,6 +5,7 @@ #include #include +#include #include "menu_event.h" #include "menu_item.h" @@ -19,7 +20,6 @@ struct Menu { MenuItem* root; MenuItem* settings; MenuItem* current; - uint32_t position; }; void menu_widget_callback(CanvasApi* canvas, void* context); @@ -42,8 +42,9 @@ ValueMutex* menu_init() { // Open GUI and register fullscreen widget GuiApi* gui = furi_open("gui"); assert(gui); - gui->add_widget(gui, menu->widget, WidgetLayerFullscreen); + gui->add_widget(gui, menu->widget, GuiLayerFullscreen); + widget_enabled_set(menu->widget, false); widget_draw_callback_set(menu->widget, menu_widget_callback, menu_mutex); widget_input_callback_set(menu->widget, menu_event_input_callback, menu->event); @@ -68,6 +69,12 @@ void menu_settings_item_add(Menu* menu, MenuItem* item) { menu_item_subitem_add(menu->settings, item); } +void menu_draw_primary(Menu* menu, CanvasApi* canvas) { +} + +void menu_draw_secondary(Menu* menu, CanvasApi* canvas) { +} + void menu_widget_callback(CanvasApi* canvas, void* context) { assert(canvas); assert(context); @@ -75,27 +82,41 @@ void menu_widget_callback(CanvasApi* canvas, void* context) { Menu* menu = acquire_mutex((ValueMutex*)context, 100); // wait 10 ms to get mutex if(menu == NULL) return; // redraw fail - if(!menu->current) { - canvas->clear(canvas); - canvas->set_color(canvas, ColorBlack); - canvas->set_font(canvas, FontPrimary); - canvas->draw_str(canvas, 2, 32, "Idle Screen"); - } else { - MenuItemArray_t* items = menu_item_get_subitems(menu->current); - canvas->clear(canvas); - canvas->set_color(canvas, ColorBlack); - canvas->set_font(canvas, FontSecondary); + assert(menu->current); - if(MenuItemArray_size(*items)) { - for(size_t i = 0; i < 5; i++) { - size_t shift_position = i + menu->position + MenuItemArray_size(*items) - 2; - shift_position = shift_position % (MenuItemArray_size(*items)); - MenuItem* item = *MenuItemArray_get(*items, shift_position); - canvas->draw_str(canvas, 2, 12 * (i + 1), menu_item_get_label(item)); - } - } else { - canvas->draw_str(canvas, 2, 32, "Empty"); - } + canvas->clear(canvas); + canvas->set_color(canvas, ColorBlack); + + size_t position = menu_item_get_position(menu->current); + MenuItemArray_t* items = menu_item_get_subitems(menu->current); + size_t items_count = MenuItemArray_size(*items); + if(items_count) { + MenuItem* item; + size_t shift_position; + // First line + canvas->set_font(canvas, FontSecondary); + shift_position = (0 + position + items_count - 1) % (MenuItemArray_size(*items)); + item = *MenuItemArray_get(*items, shift_position); + canvas->draw_icon(canvas, 4, 3, menu_item_get_icon(item)); + canvas->draw_str(canvas, 22, 14, menu_item_get_label(item)); + // Second line main + canvas->set_font(canvas, FontPrimary); + shift_position = (1 + position + items_count - 1) % (MenuItemArray_size(*items)); + item = *MenuItemArray_get(*items, shift_position); + canvas->draw_icon(canvas, 4, 24, menu_item_get_icon(item)); + canvas->draw_str(canvas, 22, 35, menu_item_get_label(item)); + // Third line + canvas->set_font(canvas, FontSecondary); + shift_position = (2 + position + items_count - 1) % (MenuItemArray_size(*items)); + item = *MenuItemArray_get(*items, shift_position); + canvas->draw_icon(canvas, 4, 46, menu_item_get_icon(item)); + canvas->draw_str(canvas, 22, 57, menu_item_get_label(item)); + // Frame and scrollbar + elements_frame(canvas, 0, 20, 128 - 5, 22); + elements_scrollbar(canvas, position, items_count); + } else { + canvas->draw_str(canvas, 2, 32, "Empty"); + elements_scrollbar(canvas, 0, 0); } release_mutex((ValueMutex*)context, menu); @@ -111,18 +132,21 @@ void menu_update(Menu* menu) { void menu_up(Menu* menu) { assert(menu); + size_t position = menu_item_get_position(menu->current); MenuItemArray_t* items = menu_item_get_subitems(menu->current); - if(menu->position == 0) menu->position = MenuItemArray_size(*items); - menu->position--; + if(position == 0) position = MenuItemArray_size(*items); + position--; + menu_item_set_position(menu->current, position); menu_update(menu); } void menu_down(Menu* menu) { assert(menu); - + size_t position = menu_item_get_position(menu->current); MenuItemArray_t* items = menu_item_get_subitems(menu->current); - menu->position++; - menu->position = menu->position % MenuItemArray_size(*items); + position++; + position = position % MenuItemArray_size(*items); + menu_item_set_position(menu->current, position); menu_update(menu); } @@ -130,18 +154,25 @@ void menu_ok(Menu* menu) { assert(menu); if(!menu->current) { + widget_enabled_set(menu->widget, true); menu->current = menu->root; + menu_item_set_position(menu->current, 0); menu_update(menu); return; } MenuItemArray_t* items = menu_item_get_subitems(menu->current); - MenuItem* item = *MenuItemArray_get(*items, menu->position); + if(!items || MenuItemArray_size(*items) == 0) { + return; + } + + size_t position = menu_item_get_position(menu->current); + MenuItem* item = *MenuItemArray_get(*items, position); MenuItemType type = menu_item_get_type(item); if(type == MenuItemTypeMenu) { menu->current = item; - menu->position = 0; + menu_item_set_position(menu->current, 0); menu_update(menu); } else if(type == MenuItemTypeFunction) { menu_item_function_call(item); @@ -153,7 +184,6 @@ void menu_back(Menu* menu) { MenuItem* parent = menu_item_get_parent(menu->current); if(parent) { menu->current = parent; - menu->position = 0; menu_update(menu); } else { menu_exit(menu); @@ -162,7 +192,7 @@ void menu_back(Menu* menu) { void menu_exit(Menu* menu) { assert(menu); - menu->position = 0; + widget_enabled_set(menu->widget, false); menu->current = NULL; menu_update(menu); } diff --git a/applications/menu/menu_item.c b/applications/menu/menu_item.c index 87c081c1..8e1e790e 100644 --- a/applications/menu/menu_item.c +++ b/applications/menu/menu_item.c @@ -6,10 +6,15 @@ struct MenuItem { MenuItemType type; + const char* label; - void* icon; + Icon* icon; + + size_t position; MenuItem* parent; void* data; + + // callback related MenuItemCallback callback; void* callback_context; }; @@ -19,7 +24,7 @@ MenuItem* menu_item_alloc() { return menu_item; } -MenuItem* menu_item_alloc_menu(const char* label, void* icon) { +MenuItem* menu_item_alloc_menu(const char* label, Icon* icon) { MenuItem* menu_item = menu_item_alloc(); menu_item->type = MenuItemTypeMenu; @@ -34,7 +39,7 @@ MenuItem* menu_item_alloc_menu(const char* label, void* icon) { } MenuItem* -menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context) { +menu_item_alloc_function(const char* label, Icon* icon, MenuItemCallback callback, void* context) { MenuItem* menu_item = menu_item_alloc(); menu_item->type = MenuItemTypeFunction; @@ -73,6 +78,16 @@ uint8_t menu_item_get_type(MenuItem* menu_item) { return menu_item->type; } +void menu_item_set_position(MenuItem* menu_item, size_t position) { + assert(menu_item); + menu_item->position = position; +} + +size_t menu_item_get_position(MenuItem* menu_item) { + assert(menu_item); + return menu_item->position; +} + void menu_item_set_label(MenuItem* menu_item, const char* label) { assert(menu_item); menu_item->label = label; @@ -83,12 +98,12 @@ const char* menu_item_get_label(MenuItem* menu_item) { return menu_item->label; } -void menu_item_set_icon(MenuItem* menu_item, void* icon) { +void menu_item_set_icon(MenuItem* menu_item, Icon* icon) { assert(menu_item); menu_item->icon = icon; } -void* menu_item_get_icon(MenuItem* menu_item) { +Icon* menu_item_get_icon(MenuItem* menu_item) { assert(menu_item); return menu_item->icon; } diff --git a/applications/menu/menu_item.h b/applications/menu/menu_item.h index 06838d6e..989cdcc8 100644 --- a/applications/menu/menu_item.h +++ b/applications/menu/menu_item.h @@ -2,6 +2,7 @@ #include #include +#include typedef enum { MenuItemTypeMenu = 0x00, @@ -13,10 +14,10 @@ typedef void (*MenuItemCallback)(void* context); ARRAY_DEF(MenuItemArray, MenuItem*, M_PTR_OPLIST); -MenuItem* menu_item_alloc_menu(const char* label, void* icon); +MenuItem* menu_item_alloc_menu(const char* label, Icon* icon); MenuItem* -menu_item_alloc_function(const char* label, void* icon, MenuItemCallback callback, void* context); +menu_item_alloc_function(const char* label, Icon* icon, MenuItemCallback callback, void* context); void menu_item_release(MenuItem* menu_item); @@ -26,11 +27,14 @@ void menu_item_subitem_add(MenuItem* menu_item, MenuItem* sub_item); MenuItemType menu_item_get_type(MenuItem* menu_item); +void menu_item_set_position(MenuItem* menu_item, size_t position); +size_t menu_item_get_position(MenuItem* menu_item); + void menu_item_set_label(MenuItem* menu_item, const char* label); const char* menu_item_get_label(MenuItem* menu_item); -void menu_item_set_icon(MenuItem* menu_item, void* icon); -void* menu_item_get_icon(MenuItem* menu_item); +void menu_item_set_icon(MenuItem* menu_item, Icon* icon); +Icon* menu_item_get_icon(MenuItem* menu_item); MenuItemArray_t* menu_item_get_subitems(MenuItem* menu_item); diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 1be5e355..4a116129 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -28,10 +29,10 @@ typedef struct { struct Nfc { Dispatcher* dispatcher; + Icon* icon; Widget* widget; + ValueMutex* menu_vm; MenuItem* menu; - FuriRecordSubscriber* gui_record; - FuriRecordSubscriber* menu_record; rfalNfcDiscoverParam* disParams; osThreadAttr_t worker_attr; @@ -222,15 +223,18 @@ void nfc_bridge_callback(void* context) { Nfc* nfc_alloc() { Nfc* nfc = furi_alloc(sizeof(Nfc)); - assert(nfc); nfc->dispatcher = dispatcher_alloc(32, sizeof(NfcMessage)); + nfc->icon = assets_icons_get(A_NFC_14); nfc->widget = widget_alloc(); widget_draw_callback_set(nfc->widget, nfc_draw_callback, nfc); widget_input_callback_set(nfc->widget, nfc_input_callback, nfc); - nfc->menu = menu_item_alloc_menu("NFC", NULL); + nfc->menu_vm = furi_open("menu"); + assert(nfc->menu_vm); + + nfc->menu = menu_item_alloc_menu("NFC", nfc->icon); menu_item_subitem_add( nfc->menu, menu_item_alloc_function("Test", NULL, nfc_test_callback, nfc)); menu_item_subitem_add( @@ -240,12 +244,6 @@ Nfc* nfc_alloc() { menu_item_subitem_add( nfc->menu, menu_item_alloc_function("Brdige", NULL, nfc_bridge_callback, nfc)); - nfc->gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); - assert(nfc->gui_record); - - nfc->menu_record = furi_open_deprecated("menu", false, false, NULL, NULL, NULL); - assert(nfc->menu_record); - nfc->worker_attr.name = "nfc_worker"; // nfc->worker_attr.attr_bits = osThreadJoinable; nfc->worker_attr.stack_size = 4096; @@ -255,29 +253,27 @@ Nfc* nfc_alloc() { void nfc_task(void* p) { Nfc* nfc = nfc_alloc(); - GuiApi* gui = furi_take(nfc->gui_record); + FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); + assert(gui_record); + GuiApi* gui = furi_take(gui_record); assert(gui); widget_enabled_set(nfc->widget, false); - gui->add_widget(gui, nfc->widget, WidgetLayerFullscreen); - furi_commit(nfc->gui_record); + gui->add_widget(gui, nfc->widget, GuiLayerFullscreen); + furi_commit(gui_record); - ValueMutex* menu_mutex = furi_open("menu"); - assert(menu_mutex); - - Menu* menu = acquire_mutex_block(menu_mutex); - menu_item_add(menu, nfc->menu); - release_mutex(menu_mutex, menu); + with_value_mutex( + nfc->menu_vm, (Menu * menu) { menu_item_add(menu, nfc->menu); }); if(!furi_create("nfc", nfc)) { printf("[nfc_task] cannot create nfc record\n"); furiac_exit(NULL); } - furiac_ready(); - nfc->ret = rfalNfcInitialize(); rfalLowPowerModeStart(); + furiac_ready(); + NfcMessage message; while(1) { dispatcher_recieve(nfc->dispatcher, (Message*)&message); diff --git a/assets/.gitignore b/assets/.gitignore new file mode 100644 index 00000000..3f30e227 --- /dev/null +++ b/assets/.gitignore @@ -0,0 +1 @@ +/headers \ No newline at end of file diff --git a/assets/ReadMe.md b/assets/ReadMe.md new file mode 100644 index 00000000..c92fc9dd --- /dev/null +++ b/assets/ReadMe.md @@ -0,0 +1,17 @@ +# Asset naming rules + +## Images and Animations + +`NAME_VARIANT_SIZE` + +- `NAME` - mandatory - Asset name in CamelCase. [A-Za-z0-9], special symbols not allowed +- `VARIANT` - optional - icon variant: can relate to state or rendering conditions. Examples: active, inactive, inverted. +- `SIZE` - mandatory - size in px. Example squere 10, 20, 24, etc. Example rectangular: 10x8, 19x5, etc. + +Image names will be automatically prefixed with `I_`, animation names with `A_`. +Icons and Animations will be gathered into `icon.h` and `icon.c`. + +# Important notes + +Don't include assets that you are not using, compiller is not going to strip unusued assets. + diff --git a/assets/assets.mk b/assets/assets.mk new file mode 100644 index 00000000..d8e85046 --- /dev/null +++ b/assets/assets.mk @@ -0,0 +1,10 @@ +ASSETS_DIR := $(PROJECT_ROOT)/assets +ASSETS_COMPILLER := $(ASSETS_DIR)/assets.py +ASSETS_OUTPUT_DIR := $(ASSETS_DIR)/output +ASSETS_SOURCE_DIR := $(ASSETS_DIR)/icons + +ASSETS_SOURCES += $(shell find $(ASSETS_SOURCE_DIR) -type f -iname '*.png' -or -iname 'frame_rate') +ASSETS += $(ASSETS_OUTPUT_DIR)/assets_icons.c + +CFLAGS += -I$(ASSETS_OUTPUT_DIR) +C_SOURCES += $(ASSETS_OUTPUT_DIR)/assets_icons.c diff --git a/assets/assets.py b/assets/assets.py new file mode 100755 index 00000000..565589f3 --- /dev/null +++ b/assets/assets.py @@ -0,0 +1,184 @@ +#!/usr/bin/env python3 + +import logging +import argparse +import subprocess +import io +import os +import sys + +ICONS_SUPPORTED_FORMATS = ["png"] + +ICONS_TEMPLATE_H_HEADER = """#pragma once + +#include + +typedef enum { +""" +ICONS_TEMPLATE_H_ICON_NAME = "\t{name},\n" +ICONS_TEMPLATE_H_FOOTER = """} IconName; + +Icon * assets_icons_get(IconName name); +""" + +ICONS_TEMPLATE_C_HEADER = """#include \"assets_icons.h\" +#include + +""" +ICONS_TEMPLATE_C_FRAME = "const uint8_t {name}[] = {data};\n" +ICONS_TEMPLATE_C_DATA = "const uint8_t *{name}[] = {data};\n" +ICONS_TEMPLATE_C_ICONS_ARRAY_START = "const IconData icons[] = {\n" +ICONS_TEMPLATE_C_ICONS_ITEM = "\t{{ .width={width}, .height={height}, .frame_count={frame_count}, .frame_rate={frame_rate}, .frames=_{name} }},\n" +ICONS_TEMPLATE_C_ICONS_ARRAY_END = "};" +ICONS_TEMPLATE_C_FOOTER = """ + +Icon * assets_icons_get(IconName name) { + return icon_alloc(&icons[name]); +} +""" + + +class Assets: + def __init__(self): + # command args + self.parser = argparse.ArgumentParser() + self.parser.add_argument("-d", "--debug", action="store_true", help="Debug") + self.subparsers = self.parser.add_subparsers(help="sub-command help") + self.parser_icons = self.subparsers.add_parser( + "icons", help="Process icons and build icon registry" + ) + self.parser_icons.add_argument( + "-s", "--source-directory", help="Source directory" + ) + self.parser_icons.add_argument( + "-o", "--output-directory", help="Output directory" + ) + self.parser_icons.set_defaults(func=self.icons) + # logging + self.logger = logging.getLogger() + + def __call__(self): + self.args = self.parser.parse_args() + if "func" not in self.args: + self.parser.error("Choose something to do") + # configure log output + self.log_level = logging.DEBUG if self.args.debug else logging.INFO + self.logger.setLevel(self.log_level) + self.handler = logging.StreamHandler(sys.stdout) + self.handler.setLevel(self.log_level) + self.formatter = logging.Formatter("%(asctime)s [%(levelname)s] %(message)s") + self.handler.setFormatter(self.formatter) + self.logger.addHandler(self.handler) + # execute requested function + self.args.func() + + def icons(self): + self.logger.debug(f"Converting icons") + icons_c = open(os.path.join(self.args.output_directory, "assets_icons.c"), "w") + icons_c.write(ICONS_TEMPLATE_C_HEADER) + icons = [] + # Traverse icons tree, append image data to source file + for dirpath, dirnames, filenames in os.walk(self.args.source_directory): + self.logger.debug(f"Processing directory {dirpath}") + if not filenames: + continue + if "frame_rate" in filenames: + self.logger.debug(f"Folder contatins animation") + icon_name = "A_" + os.path.split(dirpath)[1].replace("-", "_") + width = height = None + frame_count = 0 + frame_rate = 0 + frame_names = [] + for filename in sorted(filenames): + fullfilename = os.path.join(dirpath, filename) + if filename == "frame_rate": + frame_rate = int(open(fullfilename, "r").read().strip()) + continue + elif not self.iconIsSupported(filename): + continue + self.logger.debug(f"Processing animation frame {filename}") + temp_width, temp_height, data = self.icon2header(fullfilename) + if width is None: + width = temp_width + if height is None: + height = temp_height + assert width == temp_width + assert height == temp_height + frame_name = f"_{icon_name}_{frame_count}" + frame_names.append(frame_name) + icons_c.write( + ICONS_TEMPLATE_C_FRAME.format(name=frame_name, data=data) + ) + frame_count += 1 + assert frame_rate > 0 + assert frame_count > 0 + icons_c.write( + ICONS_TEMPLATE_C_DATA.format( + name=f"_{icon_name}", data=f'{{{",".join(frame_names)}}}' + ) + ) + icons_c.write("\n") + icons.append((icon_name, width, height, frame_rate, frame_count)) + else: + # process icons + for filename in filenames: + if not self.iconIsSupported(filename): + continue + self.logger.debug(f"Processing icon {filename}") + icon_name = "I_" + "_".join(filename.split(".")[:-1]).replace( + "-", "_" + ) + fullfilename = os.path.join(dirpath, filename) + width, height, data = self.icon2header(fullfilename) + frame_name = f"_{icon_name}_0" + icons_c.write( + ICONS_TEMPLATE_C_FRAME.format(name=frame_name, data=data) + ) + icons_c.write( + ICONS_TEMPLATE_C_DATA.format( + name=f"_{icon_name}", data=f"{{{frame_name}}}" + ) + ) + icons_c.write("\n") + icons.append((icon_name, width, height, 0, 1)) + # Create array of images: + self.logger.debug(f"Finalizing source file") + icons_c.write(ICONS_TEMPLATE_C_ICONS_ARRAY_START) + for name, width, height, frame_rate, frame_count in icons: + icons_c.write( + ICONS_TEMPLATE_C_ICONS_ITEM.format( + name=name, + width=width, + height=height, + frame_rate=frame_rate, + frame_count=frame_count, + ) + ) + icons_c.write(ICONS_TEMPLATE_C_ICONS_ARRAY_END) + icons_c.write(ICONS_TEMPLATE_C_FOOTER) + icons_c.write("\n") + # Create Header + self.logger.debug(f"Creating header") + icons_h = open(os.path.join(self.args.output_directory, "assets_icons.h"), "w") + icons_h.write(ICONS_TEMPLATE_H_HEADER) + for name, width, height, frame_rate, frame_count in icons: + icons_h.write(ICONS_TEMPLATE_H_ICON_NAME.format(name=name)) + icons_h.write(ICONS_TEMPLATE_H_FOOTER) + self.logger.debug(f"Done") + + def icon2header(self, file): + output = subprocess.check_output(["convert", file, "xbm:-"]) + assert output + f = io.StringIO(output.decode().strip()) + width = int(f.readline().strip().split(" ")[2]) + height = int(f.readline().strip().split(" ")[2]) + data = f.read().strip().replace("\n", "").replace(" ", "").split("=")[1][:-1] + return width, height, data + + def iconIsSupported(self, filename): + extension = filename.lower().split(".")[-1] + return extension in ICONS_SUPPORTED_FORMATS + + +if __name__ == "__main__": + Assets()() diff --git a/assets/icons/MainMenu/125khz_14/frame_01.png b/assets/icons/MainMenu/125khz_14/frame_01.png new file mode 100644 index 00000000..783689b9 --- /dev/null +++ b/assets/icons/MainMenu/125khz_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e3b8745f1c3cf2b3b5023d40cb2fde21afdb44f4eff3e456e2bd4eafbccb17f1 +size 257 diff --git a/assets/icons/MainMenu/125khz_14/frame_02.png b/assets/icons/MainMenu/125khz_14/frame_02.png new file mode 100644 index 00000000..e5aa9059 --- /dev/null +++ b/assets/icons/MainMenu/125khz_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6d24e445214cfc96ed699ad7f6fc5966e6fef08a7fe36add479e7b02e1458b4c +size 257 diff --git a/assets/icons/MainMenu/125khz_14/frame_03.png b/assets/icons/MainMenu/125khz_14/frame_03.png new file mode 100644 index 00000000..8e6e821c --- /dev/null +++ b/assets/icons/MainMenu/125khz_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:27f19713ab1d7b6113fb2f8a0402c93a763652e6b2c28693a858f26cce1acb6d +size 249 diff --git a/assets/icons/MainMenu/125khz_14/frame_04.png b/assets/icons/MainMenu/125khz_14/frame_04.png new file mode 100644 index 00000000..f312414e --- /dev/null +++ b/assets/icons/MainMenu/125khz_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:37271fbd71ebe1561fb4a292504d8692367c588688c534c3b9ce7122439bdca0 +size 255 diff --git a/assets/icons/MainMenu/125khz_14/frame_rate b/assets/icons/MainMenu/125khz_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/125khz_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_01.png b/assets/icons/MainMenu/Bluetooth_14/frame_01.png new file mode 100644 index 00000000..dfb03c57 --- /dev/null +++ b/assets/icons/MainMenu/Bluetooth_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:470df999ccb281350e21e86f5f21235f23ceed5fd2391d435af3b073403962ad +size 252 diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_02.png b/assets/icons/MainMenu/Bluetooth_14/frame_02.png new file mode 100644 index 00000000..5224d101 --- /dev/null +++ b/assets/icons/MainMenu/Bluetooth_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22b29a0bc9a2aa4c5258edd18def520813eefe6a028036b0f95629217565e814 +size 251 diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_03.png b/assets/icons/MainMenu/Bluetooth_14/frame_03.png new file mode 100644 index 00000000..d2bae2c9 --- /dev/null +++ b/assets/icons/MainMenu/Bluetooth_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:67fd7032e3b6bad02a2d8e58b1f9c3d10a77e3c8ed48b5819047ae35e98b405e +size 251 diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_04.png b/assets/icons/MainMenu/Bluetooth_14/frame_04.png new file mode 100644 index 00000000..4a3bbe5a --- /dev/null +++ b/assets/icons/MainMenu/Bluetooth_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:969215f7462ad2d4fdf053bf67ee3a912d46debe87815e10554b58399f2c4d20 +size 248 diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_05.png b/assets/icons/MainMenu/Bluetooth_14/frame_05.png new file mode 100644 index 00000000..9e8936a0 --- /dev/null +++ b/assets/icons/MainMenu/Bluetooth_14/frame_05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c1154e6634b065ab40849236a3172284ce1e7dd4fd7212a1ca4bdc5b48a26ffa +size 249 diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_06.png b/assets/icons/MainMenu/Bluetooth_14/frame_06.png new file mode 100644 index 00000000..f7fd714d --- /dev/null +++ b/assets/icons/MainMenu/Bluetooth_14/frame_06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:811a93e5b8770c2578be16c5cedce9663aa8608f7061c29cba949daf94a93b48 +size 251 diff --git a/assets/icons/MainMenu/Bluetooth_14/frame_rate b/assets/icons/MainMenu/Bluetooth_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/Bluetooth_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/FileManager_14/frame_01.png b/assets/icons/MainMenu/FileManager_14/frame_01.png new file mode 100644 index 00000000..761bee63 --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dbe853e0056d3b93e7beba725a660a6a8186562c2be20745aea3b2f30bcbbf91 +size 254 diff --git a/assets/icons/MainMenu/FileManager_14/frame_02.png b/assets/icons/MainMenu/FileManager_14/frame_02.png new file mode 100644 index 00000000..2df6a39d --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7076f51c03ad1e5f2f9ab00679b1142a37224caa3a44b3ea272fec94a806cf5 +size 255 diff --git a/assets/icons/MainMenu/FileManager_14/frame_03.png b/assets/icons/MainMenu/FileManager_14/frame_03.png new file mode 100644 index 00000000..158d121b --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db95faeadfd4aeb9d7b56cb10f67a945d56f6d3c7199d066903d436ef2f0ceaa +size 249 diff --git a/assets/icons/MainMenu/FileManager_14/frame_04.png b/assets/icons/MainMenu/FileManager_14/frame_04.png new file mode 100644 index 00000000..924a533c --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:267da4a3a640c4a75aa2d06ffd057c9ec10308137e0f73378a638ce96c3e9f19 +size 249 diff --git a/assets/icons/MainMenu/FileManager_14/frame_05.png b/assets/icons/MainMenu/FileManager_14/frame_05.png new file mode 100644 index 00000000..f2a0a502 --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c88f44fcffc7ade9cfb1bcfc9dbd687776211a3d57e8278e75fbf19376d462fa +size 249 diff --git a/assets/icons/MainMenu/FileManager_14/frame_06.png b/assets/icons/MainMenu/FileManager_14/frame_06.png new file mode 100644 index 00000000..b0f38746 --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:160e99941884fd6ac6ce19830a3b39cdc7197881689b8cbc0b3761be561c1cf7 +size 237 diff --git a/assets/icons/MainMenu/FileManager_14/frame_07.png b/assets/icons/MainMenu/FileManager_14/frame_07.png new file mode 100644 index 00000000..f2a0a502 --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_07.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c88f44fcffc7ade9cfb1bcfc9dbd687776211a3d57e8278e75fbf19376d462fa +size 249 diff --git a/assets/icons/MainMenu/FileManager_14/frame_08.png b/assets/icons/MainMenu/FileManager_14/frame_08.png new file mode 100644 index 00000000..924a533c --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_08.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:267da4a3a640c4a75aa2d06ffd057c9ec10308137e0f73378a638ce96c3e9f19 +size 249 diff --git a/assets/icons/MainMenu/FileManager_14/frame_09.png b/assets/icons/MainMenu/FileManager_14/frame_09.png new file mode 100644 index 00000000..158d121b --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_09.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:db95faeadfd4aeb9d7b56cb10f67a945d56f6d3c7199d066903d436ef2f0ceaa +size 249 diff --git a/assets/icons/MainMenu/FileManager_14/frame_10.png b/assets/icons/MainMenu/FileManager_14/frame_10.png new file mode 100644 index 00000000..2df6a39d --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_10.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f7076f51c03ad1e5f2f9ab00679b1142a37224caa3a44b3ea272fec94a806cf5 +size 255 diff --git a/assets/icons/MainMenu/FileManager_14/frame_rate b/assets/icons/MainMenu/FileManager_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/FileManager_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/GPIO_14/frame_01.png b/assets/icons/MainMenu/GPIO_14/frame_01.png new file mode 100644 index 00000000..2fe46fb4 --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9ab102ccd1b92236bed296eb3cdb4dc088fca6fa7e32e72d752b49e4012ffcff +size 242 diff --git a/assets/icons/MainMenu/GPIO_14/frame_02.png b/assets/icons/MainMenu/GPIO_14/frame_02.png new file mode 100644 index 00000000..3f4b2cab --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:588fabc1c63bd8815aaf61c8b8b6a7e88ef12a210f8ce04ecec6a75c4eaa48dd +size 237 diff --git a/assets/icons/MainMenu/GPIO_14/frame_03.png b/assets/icons/MainMenu/GPIO_14/frame_03.png new file mode 100644 index 00000000..a2797675 --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:66d2f7c971c180f7ea27c90aaf1ffeb8f62584c8fbd7c390fcda3165ecd9cdb2 +size 236 diff --git a/assets/icons/MainMenu/GPIO_14/frame_04.png b/assets/icons/MainMenu/GPIO_14/frame_04.png new file mode 100644 index 00000000..67112fbb --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d4a40f59194adb698cac9472a14ac34a7e0b56e6251f157d11982bdff0f88745 +size 235 diff --git a/assets/icons/MainMenu/GPIO_14/frame_05.png b/assets/icons/MainMenu/GPIO_14/frame_05.png new file mode 100644 index 00000000..02932255 --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4ad47da62b20627fd428ec857cbadb14803d41702b639c72e820aa8759fbf424 +size 231 diff --git a/assets/icons/MainMenu/GPIO_14/frame_06.png b/assets/icons/MainMenu/GPIO_14/frame_06.png new file mode 100644 index 00000000..ef0266b0 --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ededf42eb58de6082fc9f97abc73b053417f2421c547cd2f3aa9814d0eb985ab +size 235 diff --git a/assets/icons/MainMenu/GPIO_14/frame_07.png b/assets/icons/MainMenu/GPIO_14/frame_07.png new file mode 100644 index 00000000..263102c8 --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_07.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44ef494e78d60728791a632dedad8a374fcd863e4a1d409c565bd7f11e142e52 +size 235 diff --git a/assets/icons/MainMenu/GPIO_14/frame_08.png b/assets/icons/MainMenu/GPIO_14/frame_08.png new file mode 100644 index 00000000..88070aac --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_08.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:05e946f15d71eae155c5a6438cea4f5ad56ef310577fb894ebe5c3b41f9e2e24 +size 237 diff --git a/assets/icons/MainMenu/GPIO_14/frame_rate b/assets/icons/MainMenu/GPIO_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/GPIO_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/Infrared_14/frame_01.png b/assets/icons/MainMenu/Infrared_14/frame_01.png new file mode 100644 index 00000000..0937f9da --- /dev/null +++ b/assets/icons/MainMenu/Infrared_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b101d691964aa96546bb70bb08f638b48c6000230ded6597ac533b0bd36a8c86 +size 250 diff --git a/assets/icons/MainMenu/Infrared_14/frame_02.png b/assets/icons/MainMenu/Infrared_14/frame_02.png new file mode 100644 index 00000000..b053b0a5 --- /dev/null +++ b/assets/icons/MainMenu/Infrared_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5322b1c4366b8931d132292c71318f02e6756536dd38165a1f65dea5c9dfb7b2 +size 247 diff --git a/assets/icons/MainMenu/Infrared_14/frame_03.png b/assets/icons/MainMenu/Infrared_14/frame_03.png new file mode 100644 index 00000000..0f61802d --- /dev/null +++ b/assets/icons/MainMenu/Infrared_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:da8a0d2055a7a835be42bde6f71ba2d17710ad308201946fb07d97207c32e3c4 +size 243 diff --git a/assets/icons/MainMenu/Infrared_14/frame_04.png b/assets/icons/MainMenu/Infrared_14/frame_04.png new file mode 100644 index 00000000..356d3ca7 --- /dev/null +++ b/assets/icons/MainMenu/Infrared_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:04bb17687f4b0572b4ffd7c7220cb0070456b95df9849fb55e620d02fd7fee94 +size 235 diff --git a/assets/icons/MainMenu/Infrared_14/frame_05.png b/assets/icons/MainMenu/Infrared_14/frame_05.png new file mode 100644 index 00000000..ffe9aeef --- /dev/null +++ b/assets/icons/MainMenu/Infrared_14/frame_05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:1eafe712679be62faa958b2a648a514a461c08ae846ae942888cf7f22d6c3deb +size 235 diff --git a/assets/icons/MainMenu/Infrared_14/frame_06.png b/assets/icons/MainMenu/Infrared_14/frame_06.png new file mode 100644 index 00000000..5d7cd0ce --- /dev/null +++ b/assets/icons/MainMenu/Infrared_14/frame_06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e58c3bbcfec585b2f920b06b7464dba32686571156c59a46265d599222c7331a +size 243 diff --git a/assets/icons/MainMenu/Infrared_14/frame_rate b/assets/icons/MainMenu/Infrared_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/Infrared_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/NFC_14/frame_01.png b/assets/icons/MainMenu/NFC_14/frame_01.png new file mode 100644 index 00000000..2e916723 --- /dev/null +++ b/assets/icons/MainMenu/NFC_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3430783069a7fa3763bc1cbe6d251540128237249ab8268c666ee180715b6d36 +size 256 diff --git a/assets/icons/MainMenu/NFC_14/frame_02.png b/assets/icons/MainMenu/NFC_14/frame_02.png new file mode 100644 index 00000000..5b881202 --- /dev/null +++ b/assets/icons/MainMenu/NFC_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:95ed4aa304cb3e7de4aa536fb67df8cd5b6413cb67f77924729d31015f298262 +size 250 diff --git a/assets/icons/MainMenu/NFC_14/frame_03.png b/assets/icons/MainMenu/NFC_14/frame_03.png new file mode 100644 index 00000000..450cd323 --- /dev/null +++ b/assets/icons/MainMenu/NFC_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2cb767e8560b1b7f25226aa1a0fc2c46625bbf94df77fcdbdb4b14834616e762 +size 244 diff --git a/assets/icons/MainMenu/NFC_14/frame_04.png b/assets/icons/MainMenu/NFC_14/frame_04.png new file mode 100644 index 00000000..77259b9f --- /dev/null +++ b/assets/icons/MainMenu/NFC_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:00cac0303198a2baa9243b0466e755d98a408587d73c1899532a86aeb75a80c5 +size 247 diff --git a/assets/icons/MainMenu/NFC_14/frame_rate b/assets/icons/MainMenu/NFC_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/NFC_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_01.png b/assets/icons/MainMenu/Sub1ghz_14/frame_01.png new file mode 100644 index 00000000..f587edb5 --- /dev/null +++ b/assets/icons/MainMenu/Sub1ghz_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:227acbe3f7482e1efefc11b0cf8734f01062540db99accb969a521907d58c693 +size 249 diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_02.png b/assets/icons/MainMenu/Sub1ghz_14/frame_02.png new file mode 100644 index 00000000..e29cb625 --- /dev/null +++ b/assets/icons/MainMenu/Sub1ghz_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ebe14fca1ff8d5093a05d4d452c9ee55eb7bf48d8b8fc71f98a74476e703d030 +size 248 diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_03.png b/assets/icons/MainMenu/Sub1ghz_14/frame_03.png new file mode 100644 index 00000000..6354b4a8 --- /dev/null +++ b/assets/icons/MainMenu/Sub1ghz_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7b1b5373cf67c493b77dfcc5821754c8ec0c41eee633f81059e9507ce8102a27 +size 242 diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_04.png b/assets/icons/MainMenu/Sub1ghz_14/frame_04.png new file mode 100644 index 00000000..4a50926f --- /dev/null +++ b/assets/icons/MainMenu/Sub1ghz_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b12e03c09e699a5446bac1ad67bdf34e299b65e49995664e30bc8e14500dd26f +size 228 diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_05.png b/assets/icons/MainMenu/Sub1ghz_14/frame_05.png new file mode 100644 index 00000000..96d37101 --- /dev/null +++ b/assets/icons/MainMenu/Sub1ghz_14/frame_05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9592833f1c810b9939e5a213f448c090f86dbf75bf7721ca85a6c166ebc79a6c +size 231 diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_06.png b/assets/icons/MainMenu/Sub1ghz_14/frame_06.png new file mode 100644 index 00000000..b8f5c712 --- /dev/null +++ b/assets/icons/MainMenu/Sub1ghz_14/frame_06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:950f24058fd92684f1665e280f740ce662e078d03c0e59a546d21d4569f691a8 +size 242 diff --git a/assets/icons/MainMenu/Sub1ghz_14/frame_rate b/assets/icons/MainMenu/Sub1ghz_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/Sub1ghz_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_01.png b/assets/icons/MainMenu/Tamagotchi_14/frame_01.png new file mode 100644 index 00000000..24c325d7 --- /dev/null +++ b/assets/icons/MainMenu/Tamagotchi_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:68bda2a589f180b9e5231d74eab098cdaedc08ad44d74b37f3a69e6570799c42 +size 258 diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_02.png b/assets/icons/MainMenu/Tamagotchi_14/frame_02.png new file mode 100644 index 00000000..dd06feb5 --- /dev/null +++ b/assets/icons/MainMenu/Tamagotchi_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dfd4f583da99e73e11abb5acbb1235cf49acf6d61e337ad6c702cba1d8ff5ed6 +size 258 diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_03.png b/assets/icons/MainMenu/Tamagotchi_14/frame_03.png new file mode 100644 index 00000000..1fddec3d --- /dev/null +++ b/assets/icons/MainMenu/Tamagotchi_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:77ba2d0d27048bdc0d1b8faaef530e019c5ca2a7966c6d2e84bc4206c220a3a4 +size 258 diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_04.png b/assets/icons/MainMenu/Tamagotchi_14/frame_04.png new file mode 100644 index 00000000..1d70d93e --- /dev/null +++ b/assets/icons/MainMenu/Tamagotchi_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bcb7b3c96a531cea583ec917a26037bce04e1704c0e96c096d88bd164891d3b8 +size 258 diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_05.png b/assets/icons/MainMenu/Tamagotchi_14/frame_05.png new file mode 100644 index 00000000..675c439f --- /dev/null +++ b/assets/icons/MainMenu/Tamagotchi_14/frame_05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2ee856a02fb0c0b7e9f59825ce80d008bbdfde10d733db25ae2accac3cae7fb4 +size 258 diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_06.png b/assets/icons/MainMenu/Tamagotchi_14/frame_06.png new file mode 100644 index 00000000..e953a157 --- /dev/null +++ b/assets/icons/MainMenu/Tamagotchi_14/frame_06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:159ed78bae7c6ba8b91dbd5fc72475478852c667bdece15f68f318bfdfd7a0fc +size 258 diff --git a/assets/icons/MainMenu/Tamagotchi_14/frame_rate b/assets/icons/MainMenu/Tamagotchi_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/Tamagotchi_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/U2F_14/frame_01.png b/assets/icons/MainMenu/U2F_14/frame_01.png new file mode 100644 index 00000000..1b8d0a0c --- /dev/null +++ b/assets/icons/MainMenu/U2F_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:11043601935b50e020ea672ed8aa8dddbec56a6925abd2cb6cfedf965c54e73b +size 256 diff --git a/assets/icons/MainMenu/U2F_14/frame_02.png b/assets/icons/MainMenu/U2F_14/frame_02.png new file mode 100644 index 00000000..0e971469 --- /dev/null +++ b/assets/icons/MainMenu/U2F_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abd8be6bfec3facb698a2c248f6ef75f0411d4ee75a0fc653959c5d07b4dab5e +size 255 diff --git a/assets/icons/MainMenu/U2F_14/frame_03.png b/assets/icons/MainMenu/U2F_14/frame_03.png new file mode 100644 index 00000000..9f52d3e6 --- /dev/null +++ b/assets/icons/MainMenu/U2F_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:75000555e5119e163d9b3afd28861e78347acfb1bf2f704e731a26d994edd1ff +size 254 diff --git a/assets/icons/MainMenu/U2F_14/frame_04.png b/assets/icons/MainMenu/U2F_14/frame_04.png new file mode 100644 index 00000000..0e971469 --- /dev/null +++ b/assets/icons/MainMenu/U2F_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abd8be6bfec3facb698a2c248f6ef75f0411d4ee75a0fc653959c5d07b4dab5e +size 255 diff --git a/assets/icons/MainMenu/U2F_14/frame_rate b/assets/icons/MainMenu/U2F_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/U2F_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/MainMenu/iButton_14/frame_01.png b/assets/icons/MainMenu/iButton_14/frame_01.png new file mode 100644 index 00000000..df89fe82 --- /dev/null +++ b/assets/icons/MainMenu/iButton_14/frame_01.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:22cbd3b5f4c41d2ede7b89d1d4212f3da0b7da815d2bc219f95106d06424f3f2 +size 256 diff --git a/assets/icons/MainMenu/iButton_14/frame_02.png b/assets/icons/MainMenu/iButton_14/frame_02.png new file mode 100644 index 00000000..dfb76d91 --- /dev/null +++ b/assets/icons/MainMenu/iButton_14/frame_02.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6f75d8bb8a4c2c67855053ca7eedf2ce724937b246a3b5a5cf95b8df6122116c +size 260 diff --git a/assets/icons/MainMenu/iButton_14/frame_03.png b/assets/icons/MainMenu/iButton_14/frame_03.png new file mode 100644 index 00000000..954f879a --- /dev/null +++ b/assets/icons/MainMenu/iButton_14/frame_03.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:527ebea445642be096f4bd5209af3b7b74c53e688cea5d29de6d40dad31d08ca +size 256 diff --git a/assets/icons/MainMenu/iButton_14/frame_04.png b/assets/icons/MainMenu/iButton_14/frame_04.png new file mode 100644 index 00000000..94e0effe --- /dev/null +++ b/assets/icons/MainMenu/iButton_14/frame_04.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee6e95dbe9aae5a16504d42d94b24f8c3ef44108ddb726c43faec09d3cbedb7e +size 260 diff --git a/assets/icons/MainMenu/iButton_14/frame_05.png b/assets/icons/MainMenu/iButton_14/frame_05.png new file mode 100644 index 00000000..c877ddb3 --- /dev/null +++ b/assets/icons/MainMenu/iButton_14/frame_05.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:2b12ea1162db6e239562eff4cc434f4aaf86fe00b5c371805d801780a1e54258 +size 252 diff --git a/assets/icons/MainMenu/iButton_14/frame_06.png b/assets/icons/MainMenu/iButton_14/frame_06.png new file mode 100644 index 00000000..349102af --- /dev/null +++ b/assets/icons/MainMenu/iButton_14/frame_06.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93c876d79ec21c394233392f6356d24078904a81f46e354ae591757287f074e7 +size 255 diff --git a/assets/icons/MainMenu/iButton_14/frame_07.png b/assets/icons/MainMenu/iButton_14/frame_07.png new file mode 100644 index 00000000..09084806 --- /dev/null +++ b/assets/icons/MainMenu/iButton_14/frame_07.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:901b67368cd1df6f767200c021e180427830168496fe5dcc48b05bf51fcc0f38 +size 262 diff --git a/assets/icons/MainMenu/iButton_14/frame_rate b/assets/icons/MainMenu/iButton_14/frame_rate new file mode 100644 index 00000000..e440e5c8 --- /dev/null +++ b/assets/icons/MainMenu/iButton_14/frame_rate @@ -0,0 +1 @@ +3 \ No newline at end of file diff --git a/assets/icons/StatusBar/BadUsb_9x8.png b/assets/icons/StatusBar/BadUsb_9x8.png new file mode 100644 index 00000000..06cd7957 --- /dev/null +++ b/assets/icons/StatusBar/BadUsb_9x8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bead5a67650297f99797447f7b2cb4260cb13e8310da8ae57de6e42fa39e9cf6 +size 235 diff --git a/assets/icons/StatusBar/Battery_19x8.png b/assets/icons/StatusBar/Battery_19x8.png new file mode 100644 index 00000000..f2c1fb40 --- /dev/null +++ b/assets/icons/StatusBar/Battery_19x8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:763ddd423ae9f32b3f49f8cb5b6cbc9ffe0663462bebb8d41a4777bd6bf2922e +size 233 diff --git a/assets/icons/StatusBar/Bluetooth_5x8.png b/assets/icons/StatusBar/Bluetooth_5x8.png new file mode 100644 index 00000000..b3cf7335 --- /dev/null +++ b/assets/icons/StatusBar/Bluetooth_5x8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a01140f9e3bf9354d755f6bbc733e7b25757bae52dc5f0ecfeab0f82a7fab67f +size 231 diff --git a/assets/icons/StatusBar/SDcardFail_11x8.png b/assets/icons/StatusBar/SDcardFail_11x8.png new file mode 100644 index 00000000..8ce1ba07 --- /dev/null +++ b/assets/icons/StatusBar/SDcardFail_11x8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5099612a708c449fc633effc4ad5bda68b5f507f17d4f7cd410ae6ce9388c2d9 +size 233 diff --git a/assets/icons/StatusBar/SDcardMounted_11x8.png b/assets/icons/StatusBar/SDcardMounted_11x8.png new file mode 100644 index 00000000..8eb9282c --- /dev/null +++ b/assets/icons/StatusBar/SDcardMounted_11x8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c6fb3a5877db7d36e2056d48a577896aa6c58524e079a2e8d8b8c5bcf1b55892 +size 226 diff --git a/assets/icons/StatusBar/USBConnected_15x8.png b/assets/icons/StatusBar/USBConnected_15x8.png new file mode 100644 index 00000000..b8860343 --- /dev/null +++ b/assets/icons/StatusBar/USBConnected_15x8.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd239b159734ddb22a2efd940c83f819384be18aca1a51e16341cfe55d989109 +size 237 diff --git a/assets/output/.gitignore b/assets/output/.gitignore new file mode 100644 index 00000000..72e8ffc0 --- /dev/null +++ b/assets/output/.gitignore @@ -0,0 +1 @@ +* diff --git a/core/api-basic/valuemutex.h b/core/api-basic/valuemutex.h index 5309cb9b..aff5ffe4 100644 --- a/core/api-basic/valuemutex.h +++ b/core/api-basic/valuemutex.h @@ -40,6 +40,20 @@ static inline void* acquire_mutex_block(ValueMutex* valuemutex) { return acquire_mutex(valuemutex, osWaitForever); } +/* + * With statement for value mutex, acts as lambda + * @param name a resource name, const char* + * @param function_body a (){} lambda declaration, + * executed within you parent function context. +*/ +#define with_value_mutex(value_mutex, function_body) \ + { \ + void* p = acquire_mutex_block(value_mutex); \ + assert(p); \ + ({ void __fn__ function_body __fn__; })(p); \ + release_mutex(value_mutex, p); \ + } + /* Release mutex after end of work with data. Call `release_mutex` and pass ValueData instance and pointer to data. diff --git a/docker/Dockerfile b/docker/Dockerfile index 22174fbc..2b2ca430 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -20,6 +20,8 @@ RUN apt update && \ build-essential \ python \ python-pip \ + python3 \ + imagemagick \ libstdc++-arm-none-eabi-newlib \ git \ && apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* diff --git a/docker/syntax_check.sh b/docker/syntax_check.sh index e7be6a8e..85f2dde9 100755 --- a/docker/syntax_check.sh +++ b/docker/syntax_check.sh @@ -13,6 +13,7 @@ echo "RUN C\C++ SYNTAX CHECK" C_FILES=$(find . \ -not \( -path './firmware/.obj' -prune \) \ -not \( -path './firmware/targets' -prune \) \ + -not \( -path './assets' -prune \) \ -not \( -path ./lib -prune \) \ -name *.c -o -name *.h -o -name *.cpp) diff --git a/firmware/Makefile b/firmware/Makefile index 587fa7df..1562c735 100644 --- a/firmware/Makefile +++ b/firmware/Makefile @@ -2,6 +2,7 @@ PROJECT_ROOT = $(abspath $(dir $(abspath $(firstword $(MAKEFILE_LIST))))..) PROJECT = firmware include $(PROJECT_ROOT)/make/base.mk +include $(PROJECT_ROOT)/assets/assets.mk include $(PROJECT_ROOT)/core/core.mk include $(PROJECT_ROOT)/applications/applications.mk include $(PROJECT_ROOT)/lib/lib.mk diff --git a/lib/lib.mk b/lib/lib.mk index 69083e00..e7670f0c 100644 --- a/lib/lib.mk +++ b/lib/lib.mk @@ -20,6 +20,7 @@ C_SOURCES += $(U8G2_DIR)/u8x8_gpio.c C_SOURCES += $(U8G2_DIR)/u8x8_display.c C_SOURCES += $(U8G2_DIR)/u8x8_setup.c C_SOURCES += $(U8G2_DIR)/u8g2_hvline.c +C_SOURCES += $(U8G2_DIR)/u8g2_line.c C_SOURCES += $(U8G2_DIR)/u8g2_ll_hvline.c C_SOURCES += $(U8G2_DIR)/u8g2_circle.c C_SOURCES += $(U8G2_DIR)/u8g2_box.c diff --git a/lib/u8g2/u8g2_line.c b/lib/u8g2/u8g2_line.c new file mode 100644 index 00000000..727f1db3 --- /dev/null +++ b/lib/u8g2/u8g2_line.c @@ -0,0 +1,92 @@ +/* + + u8g2_box.c + + Universal 8bit Graphics Library (https://github.com/olikraus/u8g2/) + + Copyright (c) 2016, olikraus@gmail.com + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#include "u8g2.h" + + +void u8g2_DrawLine(u8g2_t *u8g2, u8g2_uint_t x1, u8g2_uint_t y1, u8g2_uint_t x2, u8g2_uint_t y2) +{ + u8g2_uint_t tmp; + u8g2_uint_t x,y; + u8g2_uint_t dx, dy; + u8g2_int_t err; + u8g2_int_t ystep; + + uint8_t swapxy = 0; + + /* no intersection check at the moment, should be added... */ + + if ( x1 > x2 ) dx = x1-x2; else dx = x2-x1; + if ( y1 > y2 ) dy = y1-y2; else dy = y2-y1; + + if ( dy > dx ) + { + swapxy = 1; + tmp = dx; dx =dy; dy = tmp; + tmp = x1; x1 =y1; y1 = tmp; + tmp = x2; x2 =y2; y2 = tmp; + } + if ( x1 > x2 ) + { + tmp = x1; x1 =x2; x2 = tmp; + tmp = y1; y1 =y2; y2 = tmp; + } + err = dx >> 1; + if ( y2 > y1 ) ystep = 1; else ystep = -1; + y = y1; + +#ifndef U8G2_16BIT + if ( x2 == 255 ) + x2--; +#else + if ( x2 == 0xffff ) + x2--; +#endif + + for( x = x1; x <= x2; x++ ) + { + if ( swapxy == 0 ) + u8g2_DrawPixel(u8g2, x, y); + else + u8g2_DrawPixel(u8g2, y, x); + err -= (uint8_t)dy; + if ( err < 0 ) + { + y += (u8g2_uint_t)ystep; + err += (u8g2_uint_t)dx; + } + } +} + diff --git a/make/base.mk b/make/base.mk index e71d7a1c..332671fb 100644 --- a/make/base.mk +++ b/make/base.mk @@ -2,3 +2,4 @@ OBJ_DIR = .obj ASM_SOURCES = C_SOURCES = CPP_SOURCES = +ASSETS = \ No newline at end of file diff --git a/make/rules.mk b/make/rules.mk index 98dab848..a018ec80 100644 --- a/make/rules.mk +++ b/make/rules.mk @@ -42,15 +42,15 @@ $(OBJ_DIR)/$(PROJECT).bin: $(OBJ_DIR)/$(PROJECT).elf @echo "\tBIN\t" $@ @$(BIN) $< $@ -$(OBJ_DIR)/%.o: %.c $(OBJ_DIR)/BUILD_FLAGS +$(OBJ_DIR)/%.o: %.c $(OBJ_DIR)/BUILD_FLAGS $(ASSETS) @echo "\tCC\t" $@ @$(CC) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o: %.s $(OBJ_DIR)/BUILD_FLAGS +$(OBJ_DIR)/%.o: %.s $(OBJ_DIR)/BUILD_FLAGS $(ASSETS) @echo "\tASM\t" $@ @$(AS) $(CFLAGS) -c $< -o $@ -$(OBJ_DIR)/%.o: %.cpp $(OBJ_DIR)/BUILD_FLAGS +$(OBJ_DIR)/%.o: %.cpp $(OBJ_DIR)/BUILD_FLAGS $(ASSETS) @echo "\tCPP\t" $@ @$(CPP) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ @@ -59,9 +59,13 @@ $(OBJ_DIR)/flash: $(OBJ_DIR)/$(PROJECT).bin touch $@ $(OBJ_DIR)/upload: $(OBJ_DIR)/$(PROJECT).bin - dfu-util -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS) + dfu-util -D $(OBJ_DIR)/$(PROJECT).bin -a 0 -s $(FLASH_ADDRESS):leave touch $@ +$(ASSETS): $(ASSETS_SOURCES) + @echo "\tASSETS\t" $@ + @$(ASSETS_COMPILLER) icons -s $(ASSETS_SOURCE_DIR) -o $(ASSETS_OUTPUT_DIR) + flash: $(OBJ_DIR)/flash upload: $(OBJ_DIR)/upload @@ -79,6 +83,7 @@ debug: flash clean: @echo "\tCLEAN\t" @$(RM) $(OBJ_DIR)/* + @$(RM) $(ASSETS) z: clean $(MAKE) all