diff --git a/.DS_Store b/.DS_Store index 28f067c..3e8916f 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/CMakeLists.txt b/CMakeLists.txt index bf2fd06..2b712cd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,7 +36,7 @@ else() endif() # Main include files of the project -include_directories(${PROJECT_SOURCE_DIR}/main/inc) +include_directories(${PROJECT_SOURCE_DIR}/src) # Define options for LVGL with default values (OFF) option(LV_USE_DRAW_SDL "Use SDL draw unit" OFF) @@ -70,38 +70,25 @@ target_include_directories(lvgl PUBLIC ${PROJECT_SOURCE_DIR} ${SDL2_INCLUDE_DIRS # Create the main executable, depending on the FreeRTOS option if(USE_FREERTOS) add_executable(main - ${PROJECT_SOURCE_DIR}/main/src/main.c - ${PROJECT_SOURCE_DIR}/main/src/freertos_main.cpp - ${PROJECT_SOURCE_DIR}/main/src/mouse_cursor_icon.c - ${PROJECT_SOURCE_DIR}/main/src/FreeRTOS_Posix_Port.c + ${PROJECT_SOURCE_DIR}/src/main_sim.c + ${PROJECT_SOURCE_DIR}/src/freertos_main.cpp + ${PROJECT_SOURCE_DIR}/src/mouse_cursor_icon.c + ${PROJECT_SOURCE_DIR}/src/FreeRTOS_Posix_Port.c ${FREERTOS_SOURCES} # Add only if USE_FREERTOS is enabled ) # Link FreeRTOS libraries target_link_libraries(main freertos_config FreeRTOS) else() add_executable(main - ${PROJECT_SOURCE_DIR}/main/src/main.c - ${PROJECT_SOURCE_DIR}/main/src/mouse_cursor_icon.c + ${PROJECT_SOURCE_DIR}/src/main_sim.c + ${PROJECT_SOURCE_DIR}/src/mouse_cursor_icon.c ) endif() # Add sources for custom application target_sources(main PRIVATE - ${PROJECT_SOURCE_DIR}/rec-ui/main.c - ${PROJECT_SOURCE_DIR}/rec-ui/utility_objects.c - ${PROJECT_SOURCE_DIR}/rec-ui/utility_functions.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_16_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_20_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_24_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_28_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_32_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_semibold_20_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_semibold_24_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_semibold_28_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/montserrat_semibold_32_ru_en.c - ${PROJECT_SOURCE_DIR}/rec-ui/arrow.c - ${PROJECT_SOURCE_DIR}/rec-ui/moon_purple.c - ${PROJECT_SOURCE_DIR}/rec-ui/sun_yellow.c + ${PROJECT_SOURCE_DIR}/src/gui_generated.c + ${PROJECT_SOURCE_DIR}/assets/montserrat_16_ru_en.c ) # Define LVGL configuration as a simple include diff --git a/assets/montserrat_16_ru_en.c b/assets/montserrat_16_ru_en.c new file mode 100755 index 0000000..6ab8e16 --- /dev/null +++ b/assets/montserrat_16_ru_en.c @@ -0,0 +1,1188 @@ +/******************************************************************************* + * Size: 16 px + * Bpp: 2 + * Opts: --bpp 2 --size 16 --no-compress --font Montserrat-Regular.ttf --range 32-127,1040-1103 --format lvgl -o montserrat_16_ru_en.c + ******************************************************************************/ + +#ifdef LV_LVGL_H_INCLUDE_SIMPLE + #include "lvgl.h" +#else + #include "S:\esp_projects\recuperator_ui\components\lvgl__lvgl\lvgl.h" +#endif + + +#ifndef MONTSERRAT_16_RU_EN +#define MONTSERRAT_16_RU_EN 1 +#endif + +#if MONTSERRAT_16_RU_EN + +/*----------------- + * BITMAPS + *----------------*/ + +/*Store the image of the glyphs*/ +static LV_ATTRIBUTE_LARGE_CONST const uint8_t glyph_bitmap[] = { + /* U+0020 " " */ + + /* U+0021 "!" */ + 0xaa, 0xaa, 0x66, 0x66, 0x0, 0x6a, + + /* U+0022 "\"" */ + 0xc3, 0xc3, 0xc3, 0xc3, 0x41, + + /* U+0023 "#" */ + 0x1, 0x80, 0x80, 0x5, 0x6, 0x0, 0x24, 0x14, + 0xf, 0xff, 0xfe, 0x3, 0x2, 0x40, 0xc, 0x8, + 0x0, 0x30, 0x30, 0x0, 0xc0, 0xc0, 0xbf, 0xff, + 0xf0, 0x18, 0x8, 0x0, 0x50, 0x60, 0x2, 0x41, + 0x40, + + /* U+0024 "$" */ + 0x0, 0x50, 0x0, 0x5, 0x0, 0x7, 0xfe, 0x1, + 0xd9, 0x64, 0x34, 0x50, 0x3, 0x5, 0x0, 0x28, + 0x50, 0x0, 0xbe, 0x0, 0x0, 0xbe, 0x0, 0x5, + 0x2c, 0x0, 0x50, 0xc0, 0x5, 0xc, 0x39, 0x97, + 0x80, 0xbf, 0xd0, 0x0, 0x50, 0x0, 0x5, 0x0, + + /* U+0025 "%" */ + 0x1a, 0x80, 0x18, 0xc, 0x24, 0xc, 0x2, 0x2, + 0x9, 0x1, 0x40, 0x86, 0x0, 0x20, 0x23, 0x0, + 0xc, 0x26, 0x40, 0x0, 0xb4, 0xc6, 0xd0, 0x0, + 0xc3, 0x9, 0x0, 0x61, 0x41, 0x80, 0x30, 0x50, + 0x20, 0x20, 0x8, 0x24, 0x18, 0x1, 0xa8, + + /* U+0026 "&" */ + 0x2, 0xf8, 0x0, 0x28, 0x24, 0x0, 0xd0, 0x60, + 0x2, 0x83, 0x40, 0x3, 0x78, 0x0, 0xf, 0x40, + 0x0, 0xd7, 0x1, 0xd, 0x7, 0x18, 0x30, 0xb, + 0x90, 0xc0, 0xb, 0x2, 0x80, 0x7a, 0x2, 0xfe, + 0x9, 0x0, 0x0, 0x0, + + /* U+0027 "'" */ + 0xcc, 0xcc, 0x40, + + /* U+0028 "(" */ + 0x9, 0xc, 0x28, 0x34, 0x30, 0x30, 0x70, 0x70, + 0x70, 0x70, 0x30, 0x30, 0x34, 0x28, 0xc, 0x9, + + /* U+0029 ")" */ + 0x30, 0x24, 0x1c, 0xc, 0xd, 0x9, 0xa, 0xa, + 0xa, 0xa, 0x9, 0xd, 0xc, 0x1c, 0x24, 0x30, + + /* U+002A "*" */ + 0x5, 0x5, 0x51, 0x2f, 0x81, 0xf8, 0x55, 0x60, + 0x50, 0x0, 0x0, + + /* U+002B "+" */ + 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, 0xff, 0xfc, + 0x3, 0x0, 0x3, 0x0, 0x3, 0x0, + + /* U+002C "," */ + 0x24, 0xd2, 0xc, 0x10, + + /* U+002D "-" */ + 0x3f, 0xc0, 0x0, + + /* U+002E "." */ + 0x34, 0xd0, + + /* U+002F "/" */ + 0x0, 0x1c, 0x0, 0x90, 0x3, 0x0, 0x1c, 0x0, + 0x90, 0x3, 0x0, 0x1c, 0x0, 0x90, 0x3, 0x0, + 0x1c, 0x0, 0x90, 0x3, 0x0, 0x1c, 0x0, 0x90, + 0x3, 0x0, 0xc, 0x0, + + /* U+0030 "0" */ + 0x2, 0xfd, 0x0, 0xf4, 0x74, 0x1c, 0x1, 0xc3, + 0x40, 0xd, 0x30, 0x0, 0xa3, 0x0, 0x7, 0x30, + 0x0, 0x73, 0x0, 0xa, 0x34, 0x0, 0xd1, 0xc0, + 0x1c, 0xf, 0x47, 0x40, 0x2f, 0xd0, + + /* U+0031 "1" */ + 0xff, 0x7, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, + 0x3, 0x3, 0x3, 0x3, + + /* U+0032 "2" */ + 0x1b, 0xf4, 0x1d, 0x7, 0x40, 0x0, 0x70, 0x0, + 0xc, 0x0, 0x6, 0x0, 0x3, 0x40, 0x3, 0x80, + 0x3, 0x80, 0x3, 0x80, 0x3, 0x80, 0x2, 0xc0, + 0x1, 0xff, 0xfd, + + /* U+0033 "3" */ + 0x7f, 0xff, 0x0, 0x3, 0x40, 0x2, 0x80, 0x1, + 0xc0, 0x0, 0xc0, 0x0, 0xbd, 0x0, 0x1, 0xe0, + 0x0, 0xc, 0x0, 0x3, 0x0, 0x0, 0xcb, 0x41, + 0xe0, 0x7f, 0xd0, + + /* U+0034 "4" */ + 0x0, 0xe, 0x0, 0x0, 0xb0, 0x0, 0x3, 0x0, + 0x0, 0x34, 0x0, 0x2, 0x80, 0x0, 0x1c, 0xc, + 0x0, 0xc0, 0x30, 0xe, 0x0, 0xc0, 0x7f, 0xff, + 0xf4, 0x0, 0xc, 0x0, 0x0, 0x30, 0x0, 0x0, + 0xc0, + + /* U+0035 "5" */ + 0x1f, 0xff, 0x6, 0x0, 0x2, 0x80, 0x0, 0x90, + 0x0, 0x24, 0x0, 0xf, 0xfd, 0x0, 0x1, 0xf0, + 0x0, 0xd, 0x0, 0x3, 0x40, 0x0, 0xd7, 0x41, + 0xf0, 0x6f, 0xe0, + + /* U+0036 "6" */ + 0x1, 0xff, 0x40, 0xb4, 0x10, 0x1c, 0x0, 0x3, + 0x40, 0x0, 0x30, 0x0, 0x3, 0x1f, 0xd0, 0x3a, + 0x7, 0x83, 0x80, 0xc, 0x34, 0x0, 0xc2, 0x80, + 0xc, 0xe, 0x3, 0x80, 0x2f, 0xd0, + + /* U+0037 "7" */ + 0x7f, 0xff, 0x98, 0x0, 0xd6, 0x0, 0x30, 0x0, + 0x28, 0x0, 0xc, 0x0, 0x7, 0x0, 0x3, 0x40, + 0x1, 0xc0, 0x0, 0xa0, 0x0, 0x30, 0x0, 0x28, + 0x0, 0xd, 0x0, + + /* U+0038 "8" */ + 0x7, 0xfd, 0x1, 0xd0, 0x78, 0x34, 0x0, 0xc3, + 0x40, 0xc, 0x1c, 0x3, 0x80, 0xbf, 0xf0, 0x2c, + 0x2, 0xc3, 0x0, 0xd, 0x30, 0x0, 0xd3, 0x0, + 0xd, 0x2d, 0x7, 0xc0, 0x7f, 0xe0, + + /* U+0039 "9" */ + 0xb, 0xf4, 0xe, 0x2, 0x87, 0x0, 0x35, 0x80, + 0xa, 0x70, 0x3, 0xce, 0x2, 0xb0, 0xbf, 0x5c, + 0x0, 0x7, 0x0, 0x2, 0x80, 0x0, 0xc1, 0x41, + 0xd0, 0x7f, 0x90, + + /* U+003A ":" */ + 0x34, 0xd0, 0x0, 0x0, 0x0, 0xd, 0x34, + + /* U+003B ";" */ + 0x34, 0xd0, 0x0, 0x0, 0x0, 0x9, 0x34, 0x83, + 0x4, + + /* U+003C "<" */ + 0x0, 0x0, 0x0, 0x7c, 0xb, 0x90, 0xb8, 0x0, + 0xb4, 0x0, 0xb, 0x80, 0x0, 0x78, 0x0, 0x4, + + /* U+003D "=" */ + 0xff, 0xfc, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xfc, + + /* U+003E ">" */ + 0x0, 0x0, 0xb4, 0x0, 0xb, 0x80, 0x0, 0x78, + 0x0, 0x6c, 0x7, 0x90, 0xb8, 0x0, 0x40, 0x0, + + /* U+003F "?" */ + 0x1f, 0xf4, 0x74, 0x1d, 0x0, 0x7, 0x0, 0x7, + 0x0, 0xd, 0x0, 0x28, 0x0, 0xa0, 0x0, 0xc0, + 0x0, 0x40, 0x0, 0x0, 0x0, 0x80, 0x1, 0xc0, + + /* U+0040 "@" */ + 0x0, 0x2f, 0xf9, 0x0, 0x1, 0xd0, 0x2, 0xc0, + 0x6, 0x0, 0x0, 0x30, 0xc, 0xb, 0xe3, 0x58, + 0x24, 0x34, 0xf, 0x48, 0x30, 0xa0, 0x3, 0x45, + 0x30, 0xc0, 0x3, 0x42, 0x20, 0xc0, 0x3, 0x42, + 0x30, 0xd0, 0x3, 0x42, 0x30, 0xa0, 0x7, 0x45, + 0x24, 0x38, 0x1f, 0x4c, 0xc, 0xb, 0xe0, 0xf4, + 0x6, 0x0, 0x0, 0x0, 0x1, 0xd0, 0x0, 0x0, + 0x0, 0x2f, 0xf8, 0x0, + + /* U+0041 "A" */ + 0x0, 0x38, 0x0, 0x0, 0x7c, 0x0, 0x0, 0xcd, + 0x0, 0x1, 0xc7, 0x0, 0x3, 0x43, 0x0, 0x3, + 0x2, 0x80, 0xa, 0x0, 0xc0, 0xc, 0x0, 0xa0, + 0x1f, 0xff, 0xf0, 0x34, 0x0, 0x34, 0x70, 0x0, + 0x1c, 0xd0, 0x0, 0xc, + + /* U+0042 "B" */ + 0x3f, 0xfe, 0x40, 0xc0, 0x7, 0x3, 0x0, 0xa, + 0xc, 0x0, 0x28, 0x30, 0x1, 0xc0, 0xff, 0xfd, + 0x3, 0x0, 0x1d, 0xc, 0x0, 0xc, 0x30, 0x0, + 0x30, 0xc0, 0x0, 0xc3, 0x0, 0x1e, 0xf, 0xff, + 0xe0, + + /* U+0043 "C" */ + 0x0, 0xbf, 0x90, 0x1e, 0x41, 0xd0, 0xd0, 0x0, + 0xa, 0x0, 0x0, 0x30, 0x0, 0x0, 0xc0, 0x0, + 0x3, 0x0, 0x0, 0xc, 0x0, 0x0, 0x28, 0x0, + 0x0, 0x34, 0x0, 0x0, 0x79, 0x7, 0x40, 0x2f, + 0xe4, + + /* U+0044 "D" */ + 0x3f, 0xfe, 0x0, 0x30, 0x2, 0xe0, 0x30, 0x0, + 0x34, 0x30, 0x0, 0x1c, 0x30, 0x0, 0xc, 0x30, + 0x0, 0xd, 0x30, 0x0, 0xd, 0x30, 0x0, 0xc, + 0x30, 0x0, 0x1c, 0x30, 0x0, 0x34, 0x30, 0x2, + 0xe0, 0x3f, 0xfe, 0x0, + + /* U+0045 "E" */ + 0x3f, 0xff, 0x8c, 0x0, 0x3, 0x0, 0x0, 0xc0, + 0x0, 0x30, 0x0, 0xf, 0xff, 0x83, 0x0, 0x0, + 0xc0, 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, + 0x0, 0xff, 0xff, + + /* U+0046 "F" */ + 0x3f, 0xff, 0x8c, 0x0, 0x3, 0x0, 0x0, 0xc0, + 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0xff, 0xe0, + 0xc0, 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, + 0x0, 0xc0, 0x0, + + /* U+0047 "G" */ + 0x0, 0xbf, 0xd0, 0x1e, 0x41, 0xe0, 0xd0, 0x0, + 0xa, 0x0, 0x0, 0x30, 0x0, 0x0, 0xc0, 0x0, + 0x3, 0x0, 0x1, 0xcc, 0x0, 0x7, 0x28, 0x0, + 0x1c, 0x34, 0x0, 0x70, 0x79, 0x7, 0x80, 0x2f, + 0xf4, + + /* U+0048 "H" */ + 0x30, 0x0, 0x30, 0xc0, 0x0, 0xc3, 0x0, 0x3, + 0xc, 0x0, 0xc, 0x30, 0x0, 0x30, 0xff, 0xff, + 0xc3, 0x0, 0x3, 0xc, 0x0, 0xc, 0x30, 0x0, + 0x30, 0xc0, 0x0, 0xc3, 0x0, 0x3, 0xc, 0x0, + 0xc, + + /* U+0049 "I" */ + 0x30, 0xc3, 0xc, 0x30, 0xc3, 0xc, 0x30, 0xc3, + 0xc, + + /* U+004A "J" */ + 0xf, 0xfd, 0x0, 0xd, 0x0, 0xd, 0x0, 0xd, + 0x0, 0xd, 0x0, 0xd, 0x0, 0xd, 0x0, 0xd, + 0x0, 0xd, 0x10, 0xc, 0x38, 0x2c, 0xb, 0xe0, + + /* U+004B "K" */ + 0x30, 0x0, 0xd0, 0xc0, 0xe, 0x3, 0x0, 0xa0, + 0xc, 0xb, 0x0, 0x30, 0xb0, 0x0, 0xc7, 0x40, + 0x3, 0x7b, 0x0, 0xf, 0x4a, 0x0, 0x34, 0xe, + 0x0, 0xc0, 0xd, 0x3, 0x0, 0x1c, 0xc, 0x0, + 0x2c, + + /* U+004C "L" */ + 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, 0x0, 0xc0, + 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, 0x0, + 0xc0, 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, + 0x0, 0xff, 0xfd, + + /* U+004D "M" */ + 0x30, 0x0, 0x3, 0x4e, 0x0, 0x1, 0xd3, 0xc0, + 0x0, 0xf4, 0xe8, 0x0, 0x79, 0x33, 0x40, 0x32, + 0x4c, 0x70, 0x18, 0x93, 0xd, 0xc, 0x24, 0xc1, + 0xca, 0x9, 0x30, 0x2b, 0x2, 0x4c, 0x3, 0x40, + 0x93, 0x0, 0x40, 0x24, 0xc0, 0x0, 0x9, + + /* U+004E "N" */ + 0x30, 0x0, 0x30, 0xf0, 0x0, 0xc3, 0xe0, 0x3, + 0xc, 0xd0, 0xc, 0x31, 0xc0, 0x30, 0xc2, 0xc0, + 0xc3, 0x3, 0x83, 0xc, 0x3, 0x4c, 0x30, 0x7, + 0x30, 0xc0, 0xb, 0xc3, 0x0, 0xf, 0xc, 0x0, + 0xc, + + /* U+004F "O" */ + 0x0, 0xbf, 0x90, 0x1, 0xe4, 0x1e, 0x0, 0xd0, + 0x0, 0xe0, 0xa0, 0x0, 0xc, 0x30, 0x0, 0x3, + 0x4c, 0x0, 0x0, 0xa3, 0x0, 0x0, 0x28, 0xc0, + 0x0, 0xd, 0x28, 0x0, 0x3, 0x3, 0x40, 0x3, + 0x80, 0x79, 0x7, 0x80, 0x2, 0xfe, 0x40, + + /* U+0050 "P" */ + 0x3f, 0xfd, 0x3, 0x0, 0x78, 0x30, 0x0, 0xd3, + 0x0, 0xa, 0x30, 0x0, 0xa3, 0x0, 0xd, 0x30, + 0x2, 0xc3, 0xff, 0xe0, 0x30, 0x0, 0x3, 0x0, + 0x0, 0x30, 0x0, 0x3, 0x0, 0x0, + + /* U+0051 "Q" */ + 0x0, 0xbf, 0x90, 0x0, 0x79, 0x7, 0x80, 0xd, + 0x0, 0xe, 0x2, 0x80, 0x0, 0x30, 0x30, 0x0, + 0x3, 0x43, 0x0, 0x0, 0x28, 0x30, 0x0, 0x2, + 0x83, 0x0, 0x0, 0x34, 0x28, 0x0, 0x3, 0x0, + 0xd0, 0x0, 0xe0, 0x7, 0x90, 0x78, 0x0, 0xb, + 0xf9, 0x0, 0x0, 0x3, 0x80, 0x80, 0x0, 0xb, + 0xf4, + + /* U+0052 "R" */ + 0x3f, 0xfd, 0x3, 0x0, 0x78, 0x30, 0x0, 0xd3, + 0x0, 0xa, 0x30, 0x0, 0xa3, 0x0, 0xd, 0x30, + 0x2, 0xc3, 0xff, 0xe0, 0x30, 0xd, 0x3, 0x0, + 0x30, 0x30, 0x2, 0xc3, 0x0, 0xd, + + /* U+0053 "S" */ + 0x7, 0xfe, 0x1, 0xd0, 0x64, 0x34, 0x0, 0x3, + 0x0, 0x0, 0x28, 0x0, 0x0, 0xb9, 0x0, 0x0, + 0x6e, 0x0, 0x0, 0x2c, 0x0, 0x0, 0xc0, 0x0, + 0xc, 0x39, 0x7, 0x80, 0xbf, 0xd0, + + /* U+0054 "T" */ + 0xff, 0xff, 0xc0, 0xd, 0x0, 0x0, 0xc0, 0x0, + 0xc, 0x0, 0x0, 0xc0, 0x0, 0xc, 0x0, 0x0, + 0xc0, 0x0, 0xc, 0x0, 0x0, 0xc0, 0x0, 0xc, + 0x0, 0x0, 0xc0, 0x0, 0xc, 0x0, + + /* U+0055 "U" */ + 0x70, 0x0, 0x37, 0x0, 0x3, 0x70, 0x0, 0x37, + 0x0, 0x3, 0x70, 0x0, 0x37, 0x0, 0x3, 0x70, + 0x0, 0x33, 0x0, 0x7, 0x30, 0x0, 0x73, 0x80, + 0xd, 0xe, 0x7, 0xc0, 0x2f, 0xe0, + + /* U+0056 "V" */ + 0xe0, 0x0, 0x1c, 0x70, 0x0, 0x28, 0x34, 0x0, + 0x30, 0x2c, 0x0, 0xa0, 0xc, 0x0, 0xd0, 0xa, + 0x1, 0xc0, 0x7, 0x3, 0x40, 0x3, 0x43, 0x0, + 0x1, 0xca, 0x0, 0x0, 0xdc, 0x0, 0x0, 0xbc, + 0x0, 0x0, 0x34, 0x0, + + /* U+0057 "W" */ + 0x30, 0x0, 0xe0, 0x0, 0xc3, 0x40, 0xf, 0x0, + 0x18, 0x28, 0x1, 0xb4, 0x2, 0x41, 0xc0, 0x26, + 0x80, 0x30, 0xc, 0x3, 0xc, 0x7, 0x0, 0xa0, + 0x60, 0xc0, 0x90, 0x7, 0x9, 0xa, 0xc, 0x0, + 0x30, 0xc0, 0x71, 0xc0, 0x2, 0x58, 0x3, 0x28, + 0x0, 0x1e, 0x40, 0x2b, 0x0, 0x0, 0xf0, 0x1, + 0xf0, 0x0, 0xf, 0x0, 0xe, 0x0, + + /* U+0058 "X" */ + 0x34, 0x0, 0xa0, 0x70, 0x7, 0x0, 0xa0, 0x30, + 0x0, 0xd3, 0x80, 0x1, 0xec, 0x0, 0x2, 0xc0, + 0x0, 0xf, 0x40, 0x0, 0xa7, 0x0, 0x7, 0xb, + 0x0, 0x34, 0xe, 0x2, 0x80, 0xc, 0x1c, 0x0, + 0x2c, + + /* U+0059 "Y" */ + 0xa0, 0x0, 0x70, 0xc0, 0x3, 0x42, 0x80, 0x18, + 0x3, 0x40, 0xc0, 0x7, 0xa, 0x0, 0xd, 0x30, + 0x0, 0x1f, 0x40, 0x0, 0x2c, 0x0, 0x0, 0xa0, + 0x0, 0x2, 0x80, 0x0, 0xa, 0x0, 0x0, 0x28, + 0x0, + + /* U+005A "Z" */ + 0x3f, 0xff, 0xe0, 0x0, 0x1d, 0x0, 0x3, 0x80, + 0x0, 0xb0, 0x0, 0x1c, 0x0, 0x3, 0x40, 0x0, + 0xe0, 0x0, 0x2c, 0x0, 0x7, 0x0, 0x0, 0xd0, + 0x0, 0x38, 0x0, 0x7, 0xff, 0xff, + + /* U+005B "[" */ + 0x3f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3f, + + /* U+005C "\\" */ + 0x60, 0x0, 0xc0, 0x2, 0x40, 0x6, 0x0, 0xc, + 0x0, 0x24, 0x0, 0x60, 0x0, 0xc0, 0x3, 0x40, + 0x6, 0x0, 0xc, 0x0, 0x34, 0x0, 0x60, 0x0, + 0xc0, 0x3, 0x40, 0x6, + + /* U+005D "]" */ + 0xbd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, + 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xd, 0xbd, + + /* U+005E "^" */ + 0x3, 0x40, 0x1a, 0x0, 0xcc, 0x6, 0x18, 0x24, + 0x30, 0xc0, 0x95, 0x1, 0x80, + + /* U+005F "_" */ + 0xff, 0xff, + + /* U+0060 "`" */ + 0x74, 0xd, + + /* U+0061 "a" */ + 0xb, 0xf8, 0x28, 0x1d, 0x0, 0x7, 0x0, 0x3, + 0xb, 0xff, 0x34, 0x3, 0x30, 0x7, 0x34, 0xf, + 0xb, 0xe7, + + /* U+0062 "b" */ + 0x60, 0x0, 0x6, 0x0, 0x0, 0x60, 0x0, 0x6, + 0x0, 0x0, 0x62, 0xf8, 0x7, 0xd0, 0xb0, 0x70, + 0x2, 0x87, 0x0, 0xc, 0x70, 0x0, 0xc7, 0x0, + 0xc, 0x70, 0x2, 0x87, 0xd0, 0xb0, 0x62, 0xf8, + 0x0, + + /* U+0063 "c" */ + 0x2, 0xfc, 0x7, 0x41, 0xc3, 0x40, 0x0, 0xc0, + 0x0, 0x70, 0x0, 0xc, 0x0, 0x3, 0x40, 0x0, + 0x34, 0x1c, 0x2, 0xfc, 0x0, + + /* U+0064 "d" */ + 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, 0x0, 0xd0, + 0x0, 0xd, 0x3, 0xf8, 0xd1, 0xd0, 0x7d, 0x34, + 0x1, 0xd3, 0x0, 0xd, 0x70, 0x0, 0xd3, 0x0, + 0xd, 0x34, 0x1, 0xd1, 0xd0, 0x7d, 0x3, 0xf8, + 0xd0, + + /* U+0065 "e" */ + 0x3, 0xf8, 0x7, 0x42, 0xc3, 0x40, 0x28, 0xc0, + 0x7, 0x7f, 0xff, 0xcc, 0x0, 0x3, 0x40, 0x0, + 0x34, 0x1c, 0x2, 0xfd, 0x0, + + /* U+0066 "f" */ + 0x7, 0xe0, 0xd0, 0xc, 0x0, 0xc0, 0xbf, 0xd0, + 0xc0, 0xc, 0x0, 0xc0, 0xc, 0x0, 0xc0, 0xc, + 0x0, 0xc0, 0xc, 0x0, + + /* U+0067 "g" */ + 0x2, 0xf8, 0x91, 0xd0, 0x7d, 0x34, 0x1, 0xd3, + 0x0, 0xd, 0x70, 0x0, 0xd3, 0x0, 0xd, 0x34, + 0x1, 0xd1, 0xd0, 0x7d, 0x2, 0xf8, 0xd0, 0x0, + 0xc, 0x19, 0x7, 0x80, 0x7f, 0xe0, + + /* U+0068 "h" */ + 0x60, 0x0, 0x18, 0x0, 0x6, 0x0, 0x1, 0x80, + 0x0, 0x63, 0xf8, 0x1f, 0x43, 0xc7, 0x0, 0x31, + 0xc0, 0xd, 0x60, 0x3, 0x58, 0x0, 0xd6, 0x0, + 0x35, 0x80, 0xd, 0x60, 0x3, 0x40, + + /* U+0069 "i" */ + 0xb6, 0x0, 0x66, 0x66, 0x66, 0x66, 0x60, + + /* U+006A "j" */ + 0x1, 0xc0, 0x18, 0x0, 0x0, 0x0, 0x1, 0xc0, + 0x1c, 0x1, 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x1, + 0xc0, 0x1c, 0x1, 0xc0, 0x1c, 0x2, 0x83, 0xe0, + + /* U+006B "k" */ + 0x60, 0x0, 0x18, 0x0, 0x6, 0x0, 0x1, 0x80, + 0x0, 0x60, 0xa, 0x18, 0xa, 0x6, 0xe, 0x1, + 0x8f, 0x0, 0x7f, 0xc0, 0x1e, 0x2c, 0x7, 0x3, + 0x81, 0x80, 0x34, 0x60, 0x7, 0x0, + + /* U+006C "l" */ + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x60, + + /* U+006D "m" */ + 0x67, 0xf8, 0x2f, 0x81, 0xf0, 0x3b, 0x42, 0xc7, + 0x0, 0x74, 0x3, 0x5c, 0x0, 0xc0, 0x9, 0x60, + 0x3, 0x0, 0x25, 0x80, 0xc, 0x0, 0x96, 0x0, + 0x30, 0x2, 0x58, 0x0, 0xc0, 0x9, 0x60, 0x3, + 0x0, 0x24, + + /* U+006E "n" */ + 0x67, 0xf8, 0x1f, 0x2, 0xc7, 0x0, 0x31, 0xc0, + 0xd, 0x60, 0x3, 0x58, 0x0, 0xd6, 0x0, 0x35, + 0x80, 0xd, 0x60, 0x3, 0x40, + + /* U+006F "o" */ + 0x2, 0xf8, 0x1, 0xd0, 0x74, 0x34, 0x1, 0xc3, + 0x0, 0xc, 0x70, 0x0, 0xd3, 0x0, 0xc, 0x34, + 0x1, 0xc0, 0xd0, 0x74, 0x2, 0xf8, 0x0, + + /* U+0070 "p" */ + 0x62, 0xf8, 0x7, 0xd0, 0xb0, 0x74, 0x2, 0x87, + 0x0, 0xc, 0x70, 0x0, 0xc7, 0x0, 0xc, 0x70, + 0x2, 0x87, 0xd0, 0xb0, 0x62, 0xf8, 0x6, 0x0, + 0x0, 0x60, 0x0, 0x6, 0x0, 0x0, + + /* U+0071 "q" */ + 0x3, 0xf8, 0xd1, 0xd0, 0x7d, 0x34, 0x1, 0xd3, + 0x0, 0xd, 0x70, 0x0, 0xd3, 0x0, 0xd, 0x34, + 0x1, 0xd1, 0xd0, 0x7d, 0x3, 0xf8, 0xd0, 0x0, + 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, + + /* U+0072 "r" */ + 0x67, 0xdf, 0x47, 0x1, 0xc0, 0x60, 0x18, 0x6, + 0x1, 0x80, 0x60, 0x0, + + /* U+0073 "s" */ + 0xf, 0xf4, 0x34, 0x18, 0x70, 0x0, 0x34, 0x0, + 0xb, 0xe0, 0x0, 0x2c, 0x0, 0xd, 0x64, 0x1c, + 0x2f, 0xe0, + + /* U+0074 "t" */ + 0xc, 0x0, 0x30, 0xb, 0xfd, 0x3, 0x0, 0xc, + 0x0, 0x30, 0x0, 0xc0, 0x3, 0x0, 0xc, 0x0, + 0x34, 0x0, 0x7e, 0x0, + + /* U+0075 "u" */ + 0xa0, 0x3, 0x28, 0x0, 0xca, 0x0, 0x32, 0x80, + 0xc, 0xa0, 0x3, 0x18, 0x0, 0xc7, 0x0, 0x70, + 0xe0, 0x7c, 0xb, 0xe3, 0x0, + + /* U+0076 "v" */ + 0xd0, 0x2, 0x5c, 0x0, 0xc3, 0x0, 0xa0, 0xa0, + 0x30, 0xc, 0x1c, 0x2, 0x4d, 0x0, 0x73, 0x0, + 0xf, 0x80, 0x1, 0xc0, 0x0, + + /* U+0077 "w" */ + 0x90, 0xa, 0x0, 0x76, 0x0, 0xf0, 0x9, 0x30, + 0x1a, 0x40, 0xc2, 0x42, 0x5c, 0x18, 0x1c, 0x30, + 0xc2, 0x40, 0xc6, 0x9, 0x30, 0x9, 0x90, 0x36, + 0x0, 0x3c, 0x3, 0xd0, 0x3, 0x80, 0x1c, 0x0, + + /* U+0078 "x" */ + 0x30, 0xa, 0x7, 0x7, 0x0, 0xa3, 0x40, 0xf, + 0x80, 0x2, 0xc0, 0x0, 0xe8, 0x0, 0xd3, 0x40, + 0xa0, 0x30, 0x70, 0x7, 0x0, + + /* U+0079 "y" */ + 0x34, 0x0, 0x91, 0xc0, 0xc, 0xd, 0x2, 0x80, + 0xa0, 0x30, 0x3, 0x6, 0x0, 0x28, 0xd0, 0x0, + 0xdc, 0x0, 0xf, 0x40, 0x0, 0x70, 0x0, 0xa, + 0x0, 0x11, 0xc0, 0x3, 0xf4, 0x0, + + /* U+007A "z" */ + 0x3f, 0xfd, 0x0, 0x1c, 0x0, 0x30, 0x0, 0xd0, + 0x2, 0x80, 0x7, 0x0, 0xc, 0x0, 0x34, 0x0, + 0x7f, 0xfe, + + /* U+007B "{" */ + 0x3, 0xc0, 0xa0, 0xd, 0x0, 0xd0, 0xd, 0x0, + 0xd0, 0xd, 0x3, 0xc0, 0xd, 0x0, 0xd0, 0xd, + 0x0, 0xd0, 0xd, 0x0, 0xd0, 0xa, 0x0, 0x3c, + + /* U+007C "|" */ + 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, + + /* U+007D "}" */ + 0xb4, 0x7, 0x0, 0xc0, 0x30, 0xc, 0x3, 0x0, + 0xc0, 0x2d, 0xd, 0x3, 0x0, 0xc0, 0x30, 0xc, + 0x3, 0x1, 0xc2, 0xd0, + + /* U+007E "~" */ + 0xf, 0x2, 0xc, 0x34, 0xc3, 0x3, 0xd0, + + /* U+0410 "А" */ + 0x0, 0x38, 0x0, 0x0, 0x7c, 0x0, 0x0, 0x9a, + 0x0, 0x0, 0xc3, 0x0, 0x2, 0x82, 0x40, 0x3, + 0x1, 0xc0, 0x7, 0x0, 0xd0, 0xd, 0x0, 0x60, + 0x1f, 0xff, 0xf0, 0x28, 0x0, 0x28, 0x30, 0x0, + 0xc, 0xa0, 0x0, 0xd, + + /* U+0411 "Б" */ + 0x3f, 0xff, 0xc3, 0x0, 0x0, 0x30, 0x0, 0x3, + 0x0, 0x0, 0x30, 0x0, 0x3, 0xff, 0xe4, 0x30, + 0x1, 0xd3, 0x0, 0xa, 0x30, 0x0, 0x73, 0x0, + 0xa, 0x30, 0x1, 0xc3, 0xff, 0xe0, + + /* U+0412 "В" */ + 0x3f, 0xfe, 0x3, 0x0, 0x2c, 0x30, 0x0, 0xd3, + 0x0, 0xd, 0x30, 0x2, 0xc3, 0xff, 0xf0, 0x30, + 0x1, 0xd3, 0x0, 0x7, 0x30, 0x0, 0x73, 0x0, + 0x7, 0x30, 0x1, 0xd3, 0xff, 0xf4, + + /* U+0413 "Г" */ + 0x3f, 0xff, 0xc, 0x0, 0x3, 0x0, 0x0, 0xc0, + 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, 0x0, + 0xc0, 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, + 0x0, 0xc0, 0x0, + + /* U+0414 "Д" */ + 0x3, 0xff, 0xf8, 0x0, 0xc0, 0xa, 0x0, 0x30, + 0x2, 0x80, 0xc, 0x0, 0xa0, 0x3, 0x0, 0x28, + 0x1, 0xc0, 0xa, 0x0, 0x60, 0x2, 0x80, 0x18, + 0x0, 0xa0, 0x9, 0x0, 0x28, 0x3, 0x0, 0xa, + 0x2, 0xc0, 0x2, 0x83, 0xff, 0xff, 0xfc, 0xd0, + 0x0, 0x3, 0x34, 0x0, 0x0, 0xc8, 0x0, 0x0, + 0x20, + + /* U+0415 "Е" */ + 0x3f, 0xff, 0x8c, 0x0, 0x3, 0x0, 0x0, 0xc0, + 0x0, 0x30, 0x0, 0xf, 0xff, 0xc3, 0x0, 0x0, + 0xc0, 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x0, + 0x0, 0xff, 0xff, + + /* U+0416 "Ж" */ + 0x34, 0x1, 0x80, 0xc, 0x1c, 0x1, 0x80, 0x28, + 0xa, 0x1, 0x80, 0x70, 0x3, 0x1, 0x80, 0xc0, + 0x1, 0xc1, 0x82, 0x80, 0x0, 0xff, 0xff, 0x0, + 0x1, 0xc2, 0x83, 0x80, 0x3, 0x41, 0x80, 0xc0, + 0xb, 0x1, 0x80, 0xa0, 0xc, 0x1, 0x80, 0x34, + 0x28, 0x1, 0x80, 0x1c, 0x70, 0x1, 0x80, 0xe, + + /* U+0417 "З" */ + 0x1b, 0xf8, 0x3, 0x40, 0xb0, 0x0, 0x3, 0x40, + 0x0, 0x24, 0x0, 0x7, 0x0, 0xbf, 0xd0, 0x0, + 0x7, 0x40, 0x0, 0x1c, 0x0, 0x0, 0xc0, 0x0, + 0x1c, 0xb4, 0x7, 0x41, 0xff, 0x80, + + /* U+0418 "И" */ + 0x30, 0x0, 0x34, 0xc0, 0x3, 0xd3, 0x0, 0x2f, + 0x4c, 0x1, 0xcd, 0x30, 0xd, 0x34, 0xc0, 0xa0, + 0xd3, 0x7, 0x3, 0x4c, 0x30, 0xd, 0x33, 0x40, + 0x34, 0xe8, 0x0, 0xd3, 0xc0, 0x3, 0x4d, 0x0, + 0xd, + + /* U+0419 "Й" */ + 0x3, 0x3, 0x0, 0x2, 0xa4, 0x0, 0x0, 0x0, + 0xc, 0x0, 0xd, 0x30, 0x0, 0xf4, 0xc0, 0xb, + 0xd3, 0x0, 0x73, 0x4c, 0x3, 0x4d, 0x30, 0x28, + 0x34, 0xc1, 0xc0, 0xd3, 0xc, 0x3, 0x4c, 0xd0, + 0xd, 0x3a, 0x0, 0x34, 0xf0, 0x0, 0xd3, 0x40, + 0x3, 0x40, + + /* U+041A "К" */ + 0x30, 0x0, 0xd3, 0x0, 0x28, 0x30, 0x7, 0x3, + 0x0, 0xc0, 0x30, 0x34, 0x3, 0xfe, 0x0, 0x30, + 0x70, 0x3, 0x2, 0xc0, 0x30, 0xe, 0x3, 0x0, + 0x30, 0x30, 0x1, 0xc3, 0x0, 0xe, + + /* U+041B "Л" */ + 0x3, 0xff, 0xf8, 0xc, 0x0, 0xa0, 0x30, 0x2, + 0x80, 0xc0, 0xa, 0x3, 0x0, 0x28, 0xc, 0x0, + 0xa0, 0x30, 0x2, 0x81, 0xc0, 0xa, 0x6, 0x0, + 0x28, 0x24, 0x0, 0xa1, 0xc0, 0x2, 0xbd, 0x0, + 0xa, + + /* U+041C "М" */ + 0x30, 0x0, 0x2, 0x8e, 0x0, 0x1, 0xe3, 0xc0, + 0x0, 0xf8, 0xdc, 0x0, 0x7a, 0x33, 0x40, 0x36, + 0x8c, 0x70, 0x18, 0xa3, 0xd, 0xc, 0x28, 0xc0, + 0xca, 0xa, 0x30, 0x2b, 0x2, 0x8c, 0x3, 0x80, + 0xa3, 0x0, 0x40, 0x28, 0xc0, 0x0, 0xa, + + /* U+041D "Н" */ + 0x30, 0x0, 0x34, 0xc0, 0x0, 0xd3, 0x0, 0x3, + 0x4c, 0x0, 0xd, 0x30, 0x0, 0x34, 0xff, 0xff, + 0xd3, 0x0, 0x3, 0x4c, 0x0, 0xd, 0x30, 0x0, + 0x34, 0xc0, 0x0, 0xd3, 0x0, 0x3, 0x4c, 0x0, + 0xd, + + /* U+041E "О" */ + 0x0, 0xbf, 0xd0, 0x0, 0xe4, 0x1e, 0x0, 0xd0, + 0x0, 0xe0, 0xa0, 0x0, 0xc, 0x34, 0x0, 0x2, + 0x4c, 0x0, 0x0, 0xa3, 0x0, 0x0, 0x28, 0xd0, + 0x0, 0x9, 0x28, 0x0, 0x3, 0x3, 0x40, 0x3, + 0x80, 0x39, 0x7, 0x80, 0x2, 0xff, 0x40, + + /* U+041F "П" */ + 0x3f, 0xff, 0xf4, 0xc0, 0x0, 0xd3, 0x0, 0x3, + 0x4c, 0x0, 0xd, 0x30, 0x0, 0x34, 0xc0, 0x0, + 0xd3, 0x0, 0x3, 0x4c, 0x0, 0xd, 0x30, 0x0, + 0x34, 0xc0, 0x0, 0xd3, 0x0, 0x3, 0x4c, 0x0, + 0xd, + + /* U+0420 "Р" */ + 0x3f, 0xfe, 0x3, 0x0, 0x7c, 0x30, 0x0, 0xd3, + 0x0, 0xa, 0x30, 0x0, 0xa3, 0x0, 0xd, 0x30, + 0x2, 0xc3, 0xff, 0xe0, 0x30, 0x0, 0x3, 0x0, + 0x0, 0x30, 0x0, 0x3, 0x0, 0x0, + + /* U+0421 "С" */ + 0x0, 0xbf, 0xd0, 0xe, 0x41, 0xe0, 0xe0, 0x0, + 0xa, 0x0, 0x0, 0x34, 0x0, 0x0, 0xc0, 0x0, + 0x3, 0x0, 0x0, 0xd, 0x0, 0x0, 0x28, 0x0, + 0x0, 0x38, 0x0, 0x0, 0x39, 0x7, 0x80, 0x2f, + 0xf4, + + /* U+0422 "Т" */ + 0xff, 0xff, 0xc0, 0xd, 0x0, 0x0, 0xd0, 0x0, + 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, 0x0, + 0xd0, 0x0, 0xd, 0x0, 0x0, 0xd0, 0x0, 0xd, + 0x0, 0x0, 0xd0, 0x0, 0xd, 0x0, + + /* U+0423 "У" */ + 0x70, 0x0, 0x34, 0xd0, 0x1, 0xc1, 0xc0, 0xd, + 0x3, 0x40, 0x70, 0x7, 0x3, 0x40, 0xd, 0x1c, + 0x0, 0x1c, 0xd0, 0x0, 0x37, 0x0, 0x0, 0x74, + 0x0, 0x1, 0xc0, 0x0, 0x1d, 0x0, 0x7, 0xd0, + 0x0, + + /* U+0424 "Ф" */ + 0x0, 0xbf, 0xf8, 0x0, 0xb8, 0x71, 0xb4, 0x1c, + 0x3, 0x1, 0xc3, 0x40, 0x30, 0xa, 0x30, 0x3, + 0x0, 0x73, 0x0, 0x30, 0x7, 0x30, 0x3, 0x0, + 0x73, 0x40, 0x30, 0xa, 0x1c, 0x3, 0x1, 0xc0, + 0xb4, 0x30, 0xb4, 0x0, 0xbf, 0xf8, 0x0, 0x0, + 0x30, 0x0, + + /* U+0425 "Х" */ + 0x34, 0x0, 0xd0, 0x70, 0xb, 0x0, 0xa0, 0x70, + 0x0, 0xd3, 0x40, 0x1, 0xec, 0x0, 0x3, 0xc0, + 0x0, 0xf, 0x40, 0x0, 0xa7, 0x0, 0x7, 0xa, + 0x0, 0x34, 0xd, 0x2, 0x80, 0x1c, 0x1c, 0x0, + 0x28, + + /* U+0426 "Ц" */ + 0x30, 0x0, 0x30, 0x30, 0x0, 0x30, 0x30, 0x0, + 0x30, 0x30, 0x0, 0x30, 0x30, 0x0, 0x30, 0x30, + 0x0, 0x30, 0x30, 0x0, 0x30, 0x30, 0x0, 0x30, + 0x30, 0x0, 0x30, 0x30, 0x0, 0x30, 0x30, 0x0, + 0x70, 0x3f, 0xff, 0xff, 0x0, 0x0, 0x7, 0x0, + 0x0, 0x7, 0x0, 0x0, 0x7, + + /* U+0427 "Ч" */ + 0x70, 0x0, 0xa7, 0x0, 0xa, 0x70, 0x0, 0xa7, + 0x0, 0xa, 0x70, 0x0, 0xa3, 0x0, 0xa, 0x2c, + 0x1, 0xe0, 0xbf, 0xee, 0x0, 0x0, 0xa0, 0x0, + 0xa, 0x0, 0x0, 0xa0, 0x0, 0xa, + + /* U+0428 "Ш" */ + 0x30, 0x3, 0x40, 0x28, 0xc0, 0xd, 0x0, 0xa3, + 0x0, 0x34, 0x2, 0x8c, 0x0, 0xd0, 0xa, 0x30, + 0x3, 0x40, 0x28, 0xc0, 0xd, 0x0, 0xa3, 0x0, + 0x34, 0x2, 0x8c, 0x0, 0xd0, 0xa, 0x30, 0x3, + 0x40, 0x28, 0xc0, 0xd, 0x0, 0xa3, 0x0, 0x34, + 0x2, 0x8f, 0xff, 0xff, 0xfe, + + /* U+0429 "Щ" */ + 0x30, 0x3, 0x40, 0x28, 0xc, 0x0, 0xd0, 0xa, + 0x3, 0x0, 0x34, 0x2, 0x80, 0xc0, 0xd, 0x0, + 0xa0, 0x30, 0x3, 0x40, 0x28, 0xc, 0x0, 0xd0, + 0xa, 0x3, 0x0, 0x34, 0x2, 0x80, 0xc0, 0xd, + 0x0, 0xa0, 0x30, 0x3, 0x40, 0x28, 0xc, 0x0, + 0xd0, 0xa, 0x3, 0x0, 0x34, 0x2, 0x80, 0xff, + 0xff, 0xff, 0xfd, 0x0, 0x0, 0x0, 0x3, 0x40, + 0x0, 0x0, 0x0, 0xd0, 0x0, 0x0, 0x0, 0x10, + + /* U+042A "Ъ" */ + 0xff, 0xc0, 0x0, 0x0, 0x70, 0x0, 0x0, 0x1c, + 0x0, 0x0, 0x7, 0x0, 0x0, 0x1, 0xff, 0xf4, + 0x0, 0x70, 0x7, 0x80, 0x1c, 0x0, 0x30, 0x7, + 0x0, 0xd, 0x1, 0xc0, 0x3, 0x40, 0x70, 0x0, + 0xc0, 0x1c, 0x0, 0xe0, 0x7, 0xff, 0xe0, + + /* U+042B "Ы" */ + 0x30, 0x0, 0x1, 0xcc, 0x0, 0x0, 0x73, 0x0, + 0x0, 0x1c, 0xc0, 0x0, 0x7, 0x3f, 0xfe, 0x1, + 0xcc, 0x0, 0xb0, 0x73, 0x0, 0xd, 0x1c, 0xc0, + 0x2, 0x87, 0x30, 0x0, 0xa1, 0xcc, 0x0, 0x34, + 0x73, 0x0, 0x2c, 0x1c, 0xff, 0xf8, 0x7, + + /* U+042C "Ь" */ + 0x30, 0x0, 0x3, 0x0, 0x0, 0x30, 0x0, 0x3, + 0x0, 0x0, 0x3f, 0xfe, 0x3, 0x0, 0x2c, 0x30, + 0x0, 0xd3, 0x0, 0xa, 0x30, 0x0, 0xa3, 0x0, + 0xd, 0x30, 0x2, 0xc3, 0xff, 0xe0, + + /* U+042D "Э" */ + 0xb, 0xf9, 0x0, 0xe4, 0x2e, 0x0, 0x0, 0xd, + 0x0, 0x0, 0x1c, 0x0, 0x0, 0x30, 0xb, 0xff, + 0xd0, 0x0, 0x3, 0x40, 0x0, 0xc, 0x0, 0x0, + 0x70, 0x40, 0x3, 0x43, 0x90, 0xb8, 0x2, 0xfe, + 0x40, + + /* U+042E "Ю" */ + 0x30, 0x1, 0xff, 0x40, 0x30, 0xf, 0x41, 0xe0, + 0x30, 0x2c, 0x0, 0x38, 0x30, 0x30, 0x0, 0x1c, + 0x30, 0x60, 0x0, 0xd, 0x3f, 0xe0, 0x0, 0xa, + 0x30, 0xa0, 0x0, 0xa, 0x30, 0x60, 0x0, 0xd, + 0x30, 0x30, 0x0, 0x1c, 0x30, 0x2c, 0x0, 0x38, + 0x30, 0xf, 0x41, 0xe0, 0x30, 0x1, 0xff, 0x40, + + /* U+042F "Я" */ + 0xb, 0xff, 0xce, 0x0, 0x7a, 0x0, 0x1f, 0x40, + 0x7, 0xd0, 0x1, 0xe8, 0x0, 0x77, 0x40, 0x1c, + 0x7f, 0xff, 0xe, 0x1, 0xc7, 0x0, 0x73, 0x0, + 0x1e, 0x80, 0x7, + + /* U+0430 "а" */ + 0xb, 0xf8, 0x28, 0x1d, 0x0, 0x7, 0x0, 0x3, + 0xb, 0xff, 0x34, 0x3, 0x30, 0x7, 0x34, 0xf, + 0xf, 0xe7, + + /* U+0431 "б" */ + 0x0, 0x0, 0x0, 0x1b, 0xc0, 0xb9, 0x0, 0xa0, + 0x0, 0x70, 0x0, 0x24, 0xbe, 0xe, 0xd1, 0xe3, + 0xc0, 0xd, 0xe0, 0x2, 0xb4, 0x0, 0x6a, 0x0, + 0x29, 0xc0, 0xd, 0x3c, 0xe, 0x2, 0xfe, 0x0, + + /* U+0432 "в" */ + 0x7f, 0xf4, 0x60, 0xc, 0x60, 0xd, 0x60, 0xc, + 0x7f, 0xf8, 0x60, 0xd, 0x60, 0x6, 0x60, 0xe, + 0x7f, 0xf8, + + /* U+0433 "г" */ + 0x7f, 0xf9, 0xc0, 0x7, 0x0, 0x1c, 0x0, 0x70, + 0x1, 0xc0, 0x7, 0x0, 0x1c, 0x0, 0x70, 0x0, + + /* U+0434 "д" */ + 0xb, 0xff, 0x80, 0xd0, 0x28, 0xd, 0x2, 0x80, + 0xc0, 0x28, 0xc, 0x2, 0x80, 0xc0, 0x28, 0xc, + 0x2, 0x82, 0x80, 0x28, 0xff, 0xff, 0xfc, 0x0, + 0x7, 0xc0, 0x0, 0x70, + + /* U+0435 "е" */ + 0x2, 0xf8, 0x3, 0x42, 0xc3, 0x40, 0x28, 0xc0, + 0x3, 0x3f, 0xff, 0xcc, 0x0, 0x3, 0x40, 0x0, + 0x38, 0x1d, 0x2, 0xfd, 0x0, + + /* U+0436 "ж" */ + 0x30, 0xc, 0x3, 0x4a, 0x3, 0x1, 0xc0, 0xd0, + 0xc0, 0xc0, 0x1c, 0x30, 0xa0, 0x3, 0xff, 0xf0, + 0x1, 0xc3, 0x4e, 0x0, 0xd0, 0xc0, 0xd0, 0xa0, + 0x30, 0x1c, 0x70, 0xc, 0x3, 0x80, + + /* U+0437 "з" */ + 0x1f, 0xe0, 0x24, 0x2c, 0x0, 0xd, 0x0, 0x1c, + 0x7, 0xf4, 0x0, 0xd, 0x0, 0xa, 0x60, 0x1d, + 0x2f, 0xe4, + + /* U+0438 "и" */ + 0x70, 0x3, 0x5c, 0x3, 0xd7, 0x2, 0xb5, 0xc1, + 0xcd, 0x70, 0xc3, 0x5c, 0xd0, 0xd7, 0xa0, 0x35, + 0xf0, 0xd, 0x70, 0x3, 0x40, + + /* U+0439 "й" */ + 0x4, 0x4, 0x2, 0x6, 0x0, 0x2e, 0x0, 0x0, + 0x0, 0x70, 0x3, 0x5c, 0x3, 0xd7, 0x2, 0xb5, + 0xc1, 0xcd, 0x70, 0xc3, 0x5c, 0xd0, 0xd7, 0xa0, + 0x35, 0xf0, 0xd, 0x70, 0x3, 0x40, + + /* U+043A "к" */ + 0x70, 0xa, 0x1c, 0x7, 0x7, 0x3, 0x1, 0xc3, + 0x40, 0x7f, 0xc0, 0x1c, 0x34, 0x7, 0x3, 0x1, + 0xc0, 0x70, 0x70, 0xa, 0x0, + + /* U+043B "л" */ + 0xb, 0xff, 0x82, 0x40, 0xa0, 0xd0, 0x28, 0x30, + 0xa, 0xc, 0x2, 0x83, 0x0, 0xa0, 0xc0, 0x28, + 0xa0, 0xa, 0xf0, 0x2, 0x80, + + /* U+043C "м" */ + 0x70, 0x0, 0x71, 0xe0, 0x3, 0xc6, 0xc0, 0x1b, + 0x19, 0x80, 0xcc, 0x63, 0x49, 0x31, 0x87, 0x30, + 0xc6, 0xb, 0x43, 0x18, 0x8, 0xc, 0x60, 0x0, + 0x30, + + /* U+043D "н" */ + 0x70, 0x3, 0x1c, 0x0, 0xc7, 0x0, 0x31, 0xc0, + 0xc, 0x7f, 0xff, 0x1c, 0x0, 0xc7, 0x0, 0x31, + 0xc0, 0xc, 0x70, 0x3, 0x0, + + /* U+043E "о" */ + 0x2, 0xfd, 0x0, 0xe0, 0x74, 0x38, 0x1, 0xc3, + 0x0, 0xd, 0x30, 0x0, 0xd3, 0x0, 0xd, 0x38, + 0x1, 0xc0, 0xe0, 0x74, 0x2, 0xfd, 0x0, + + /* U+043F "п" */ + 0x7f, 0xff, 0x1c, 0x0, 0xc7, 0x0, 0x31, 0xc0, + 0xc, 0x70, 0x3, 0x1c, 0x0, 0xc7, 0x0, 0x31, + 0xc0, 0xc, 0x70, 0x3, 0x0, + + /* U+0440 "р" */ + 0x62, 0xf8, 0x7, 0xd0, 0xb0, 0x74, 0x2, 0x87, + 0x0, 0xc, 0x70, 0x0, 0xc7, 0x0, 0xc, 0x74, + 0x2, 0xc7, 0xd0, 0xb0, 0x72, 0xf8, 0x7, 0x0, + 0x0, 0x70, 0x0, 0x7, 0x0, 0x0, + + /* U+0441 "с" */ + 0x2, 0xfd, 0x3, 0x81, 0xc3, 0x80, 0x0, 0xc0, + 0x0, 0x30, 0x0, 0xc, 0x0, 0x3, 0x80, 0x0, + 0x38, 0x1c, 0x2, 0xfd, 0x0, + + /* U+0442 "т" */ + 0xff, 0xfe, 0x3, 0x40, 0x3, 0x40, 0x3, 0x40, + 0x3, 0x40, 0x3, 0x40, 0x3, 0x40, 0x3, 0x40, + 0x3, 0x40, + + /* U+0443 "у" */ + 0x28, 0x0, 0xa0, 0xc0, 0xc, 0xd, 0x1, 0x80, + 0x70, 0x34, 0x3, 0x7, 0x0, 0x28, 0x90, 0x0, + 0xcc, 0x0, 0xb, 0x80, 0x0, 0x70, 0x0, 0x6, + 0x0, 0x10, 0xc0, 0x2, 0xf4, 0x0, + + /* U+0444 "ф" */ + 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, + 0x0, 0x0, 0x1c, 0x0, 0x2, 0xff, 0x90, 0xe, + 0x5c, 0x78, 0x38, 0x1c, 0xd, 0x30, 0x1c, 0x6, + 0x30, 0x1c, 0x7, 0x30, 0x1c, 0x6, 0x38, 0x1c, + 0xd, 0xe, 0x5c, 0x78, 0x2, 0xff, 0x90, 0x0, + 0x1c, 0x0, 0x0, 0x1c, 0x0, 0x0, 0x1c, 0x0, + + /* U+0445 "х" */ + 0x30, 0xa, 0xb, 0x7, 0x0, 0xd3, 0x0, 0xf, + 0x40, 0x2, 0xc0, 0x1, 0xe8, 0x0, 0xd3, 0x40, + 0xa0, 0x30, 0x70, 0x7, 0x0, + + /* U+0446 "ц" */ + 0x70, 0x3, 0x7, 0x0, 0x30, 0x70, 0x3, 0x7, + 0x0, 0x30, 0x70, 0x3, 0x7, 0x0, 0x30, 0x70, + 0x3, 0x7, 0x0, 0x30, 0x7f, 0xff, 0xd0, 0x0, + 0x9, 0x0, 0x0, 0x90, + + /* U+0447 "ч" */ + 0x70, 0x3, 0x70, 0x3, 0x70, 0x3, 0x30, 0x3, + 0x38, 0xb, 0xb, 0xfb, 0x0, 0x3, 0x0, 0x3, + 0x0, 0x3, + + /* U+0448 "ш" */ + 0x70, 0xc, 0x3, 0x1c, 0x3, 0x0, 0xc7, 0x0, + 0xc0, 0x31, 0xc0, 0x30, 0xc, 0x70, 0xc, 0x3, + 0x1c, 0x3, 0x0, 0xc7, 0x0, 0xc0, 0x31, 0xc0, + 0x30, 0xc, 0x7f, 0xff, 0xff, 0x0, + + /* U+0449 "щ" */ + 0x70, 0xc, 0x3, 0x7, 0x0, 0xc0, 0x30, 0x70, + 0xc, 0x3, 0x7, 0x0, 0xc0, 0x30, 0x70, 0xc, + 0x3, 0x7, 0x0, 0xc0, 0x30, 0x70, 0xc, 0x3, + 0x7, 0x0, 0xc0, 0x34, 0x7f, 0xff, 0xff, 0xe0, + 0x0, 0x0, 0xa, 0x0, 0x0, 0x0, 0xa0, + + /* U+044A "ъ" */ + 0xff, 0x0, 0x0, 0x70, 0x0, 0x7, 0x0, 0x0, + 0x7f, 0xf4, 0x7, 0x1, 0xc0, 0x70, 0xd, 0x7, + 0x0, 0xd0, 0x70, 0x1c, 0x7, 0xff, 0x0, + + /* U+044B "ы" */ + 0x70, 0x0, 0x37, 0x0, 0x3, 0x70, 0x0, 0x37, + 0xfe, 0x3, 0x70, 0x1c, 0x37, 0x0, 0xd3, 0x70, + 0xd, 0x37, 0x1, 0xc3, 0x7f, 0xf0, 0x30, + + /* U+044C "ь" */ + 0x70, 0x0, 0x70, 0x0, 0x70, 0x0, 0x7f, 0xf4, + 0x70, 0x1c, 0x70, 0x9, 0x70, 0xd, 0x70, 0x1c, + 0x7f, 0xf4, + + /* U+044D "э" */ + 0x1f, 0xe0, 0x1c, 0x7, 0x40, 0x0, 0x70, 0x0, + 0xd, 0x3, 0xff, 0x40, 0x0, 0xd0, 0x0, 0x71, + 0x90, 0x74, 0x1f, 0xe0, 0x0, + + /* U+044E "ю" */ + 0x70, 0x1f, 0xe0, 0x1c, 0x1d, 0xb, 0x7, 0xd, + 0x0, 0xa1, 0xc3, 0x0, 0xc, 0x7f, 0xc0, 0x3, + 0x1c, 0x70, 0x0, 0xc7, 0xd, 0x0, 0xa1, 0xc1, + 0xd0, 0xb0, 0x70, 0x1f, 0xe0, 0x0, + + /* U+044F "я" */ + 0xb, 0xff, 0xb, 0x0, 0xc3, 0x0, 0x30, 0xc0, + 0xc, 0x28, 0x3, 0x2, 0xff, 0xc0, 0x60, 0x30, + 0x30, 0xc, 0x34, 0x3, 0x0 +}; + + +/*--------------------- + * GLYPH DESCRIPTION + *--------------------*/ + +static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 67, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 0, .adv_w = 67, .box_w = 2, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 6, .adv_w = 95, .box_w = 4, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 11, .adv_w = 178, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 44, .adv_w = 157, .box_w = 10, .box_h = 16, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 84, .adv_w = 212, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 123, .adv_w = 171, .box_w = 11, .box_h = 13, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 159, .adv_w = 52, .box_w = 2, .box_h = 5, .ofs_x = 1, .ofs_y = 7}, + {.bitmap_index = 162, .adv_w = 84, .box_w = 4, .box_h = 16, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 178, .adv_w = 84, .box_w = 4, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 194, .adv_w = 99, .box_w = 6, .box_h = 7, .ofs_x = 0, .ofs_y = 6}, + {.bitmap_index = 205, .adv_w = 147, .box_w = 8, .box_h = 7, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 219, .adv_w = 54, .box_w = 3, .box_h = 5, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 223, .adv_w = 98, .box_w = 6, .box_h = 2, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 226, .adv_w = 54, .box_w = 3, .box_h = 2, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 228, .adv_w = 86, .box_w = 7, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 256, .adv_w = 169, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 286, .adv_w = 92, .box_w = 4, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 298, .adv_w = 145, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 325, .adv_w = 144, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 352, .adv_w = 169, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 385, .adv_w = 145, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 412, .adv_w = 156, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 442, .adv_w = 151, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 469, .adv_w = 163, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 499, .adv_w = 156, .box_w = 9, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 526, .adv_w = 54, .box_w = 3, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 533, .adv_w = 54, .box_w = 3, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 542, .adv_w = 147, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 558, .adv_w = 147, .box_w = 8, .box_h = 5, .ofs_x = 1, .ofs_y = 3}, + {.bitmap_index = 568, .adv_w = 147, .box_w = 8, .box_h = 8, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 584, .adv_w = 145, .box_w = 8, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 608, .adv_w = 264, .box_w = 16, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 668, .adv_w = 184, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 704, .adv_w = 193, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 737, .adv_w = 182, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 770, .adv_w = 211, .box_w = 12, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 806, .adv_w = 171, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 833, .adv_w = 162, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 860, .adv_w = 198, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 893, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 926, .adv_w = 77, .box_w = 3, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 935, .adv_w = 128, .box_w = 8, .box_h = 12, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 959, .adv_w = 182, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 992, .adv_w = 151, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1019, .adv_w = 244, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1058, .adv_w = 208, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1091, .adv_w = 215, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1130, .adv_w = 184, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1160, .adv_w = 215, .box_w = 14, .box_h = 14, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 1209, .adv_w = 185, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1239, .adv_w = 157, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1269, .adv_w = 147, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1299, .adv_w = 203, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1329, .adv_w = 179, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1365, .adv_w = 284, .box_w = 18, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1419, .adv_w = 168, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1452, .adv_w = 163, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1485, .adv_w = 167, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1515, .adv_w = 81, .box_w = 4, .box_h = 16, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1531, .adv_w = 86, .box_w = 7, .box_h = 16, .ofs_x = -1, .ofs_y = -2}, + {.bitmap_index = 1559, .adv_w = 81, .box_w = 4, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1575, .adv_w = 147, .box_w = 7, .box_h = 7, .ofs_x = 1, .ofs_y = 2}, + {.bitmap_index = 1588, .adv_w = 128, .box_w = 8, .box_h = 1, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 1590, .adv_w = 154, .box_w = 4, .box_h = 2, .ofs_x = 2, .ofs_y = 10}, + {.bitmap_index = 1592, .adv_w = 151, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1610, .adv_w = 174, .box_w = 10, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1643, .adv_w = 144, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1664, .adv_w = 174, .box_w = 10, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1697, .adv_w = 155, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1718, .adv_w = 87, .box_w = 6, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1738, .adv_w = 175, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1768, .adv_w = 173, .box_w = 9, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1798, .adv_w = 69, .box_w = 2, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1805, .adv_w = 70, .box_w = 6, .box_h = 16, .ofs_x = -2, .ofs_y = -3}, + {.bitmap_index = 1829, .adv_w = 153, .box_w = 9, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1859, .adv_w = 69, .box_w = 2, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1866, .adv_w = 272, .box_w = 15, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1900, .adv_w = 173, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 1921, .adv_w = 161, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1944, .adv_w = 174, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 1974, .adv_w = 174, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2004, .adv_w = 103, .box_w = 5, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2016, .adv_w = 125, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2034, .adv_w = 104, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2054, .adv_w = 172, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2075, .adv_w = 139, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2096, .adv_w = 225, .box_w = 14, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2128, .adv_w = 137, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2149, .adv_w = 139, .box_w = 10, .box_h = 12, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 2179, .adv_w = 131, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2197, .adv_w = 86, .box_w = 6, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2221, .adv_w = 75, .box_w = 2, .box_h = 16, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 2229, .adv_w = 86, .box_w = 5, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2249, .adv_w = 147, .box_w = 9, .box_h = 3, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 2256, .adv_w = 190, .box_w = 12, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2292, .adv_w = 186, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2322, .adv_w = 192, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2352, .adv_w = 146, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2379, .adv_w = 203, .box_w = 13, .box_h = 15, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2428, .adv_w = 169, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2455, .adv_w = 259, .box_w = 16, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2503, .adv_w = 159, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2533, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2566, .adv_w = 211, .box_w = 11, .box_h = 15, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2608, .adv_w = 180, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2638, .adv_w = 201, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2671, .adv_w = 247, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2710, .adv_w = 210, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2743, .adv_w = 218, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2782, .adv_w = 211, .box_w = 11, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2815, .adv_w = 182, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2845, .adv_w = 183, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2878, .adv_w = 151, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2908, .adv_w = 174, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2941, .adv_w = 235, .box_w = 14, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2983, .adv_w = 166, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3016, .adv_w = 212, .box_w = 12, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 3061, .adv_w = 183, .box_w = 10, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3091, .adv_w = 280, .box_w = 15, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3136, .adv_w = 286, .box_w = 17, .box_h = 15, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 3200, .adv_w = 210, .box_w = 13, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3239, .adv_w = 250, .box_w = 13, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3278, .adv_w = 182, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3308, .adv_w = 181, .box_w = 11, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3341, .adv_w = 280, .box_w = 16, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3389, .adv_w = 187, .box_w = 9, .box_h = 12, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3416, .adv_w = 149, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3434, .adv_w = 169, .box_w = 9, .box_h = 14, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3466, .adv_w = 156, .box_w = 8, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3484, .adv_w = 122, .box_w = 7, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3500, .adv_w = 167, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 3528, .adv_w = 158, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3549, .adv_w = 211, .box_w = 13, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3579, .adv_w = 137, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3597, .adv_w = 176, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3618, .adv_w = 176, .box_w = 9, .box_h = 13, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3648, .adv_w = 149, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3669, .adv_w = 162, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3690, .adv_w = 202, .box_w = 11, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3715, .adv_w = 173, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3736, .adv_w = 163, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3759, .adv_w = 173, .box_w = 9, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 3780, .adv_w = 176, .box_w = 10, .box_h = 12, .ofs_x = 1, .ofs_y = -3}, + {.bitmap_index = 3810, .adv_w = 144, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3831, .adv_w = 121, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3849, .adv_w = 143, .box_w = 10, .box_h = 12, .ofs_x = -1, .ofs_y = -3}, + {.bitmap_index = 3879, .adv_w = 201, .box_w = 12, .box_h = 16, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3927, .adv_w = 135, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3948, .adv_w = 175, .box_w = 10, .box_h = 11, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 3976, .adv_w = 153, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3994, .adv_w = 238, .box_w = 13, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4024, .adv_w = 238, .box_w = 14, .box_h = 11, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 4063, .adv_w = 159, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4086, .adv_w = 201, .box_w = 10, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4109, .adv_w = 144, .box_w = 8, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4127, .adv_w = 146, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4148, .adv_w = 221, .box_w = 13, .box_h = 9, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 4178, .adv_w = 155, .box_w = 9, .box_h = 9, .ofs_x = 0, .ofs_y = 0} +}; + +/*--------------------- + * CHARACTER MAPPING + *--------------------*/ + + + +/*Collect the unicode lists and glyph_id offsets*/ +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ + { + .range_start = 32, .range_length = 95, .glyph_id_start = 1, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 1040, .range_length = 64, .glyph_id_start = 96, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + } +}; + + + +/*-------------------- + * ALL CUSTOM DATA + *--------------------*/ + +#if LVGL_VERSION_MAJOR == 8 +/*Store all the custom data of the font*/ +static lv_font_fmt_txt_glyph_cache_t cache; +#endif + +#if LVGL_VERSION_MAJOR >= 8 +static const lv_font_fmt_txt_dsc_t font_dsc = { +#else +static lv_font_fmt_txt_dsc_t font_dsc = { +#endif + .glyph_bitmap = glyph_bitmap, + .glyph_dsc = glyph_dsc, + .cmaps = cmaps, + .kern_dsc = NULL, + .kern_scale = 0, + .cmap_num = 2, + .bpp = 2, + .kern_classes = 0, + .bitmap_format = 0, +#if LVGL_VERSION_MAJOR == 8 + .cache = &cache +#endif +}; + +extern const lv_font_t lv_font_montserrat_16; + + +/*----------------- + * PUBLIC FONT + *----------------*/ + +/*Initialize a public general font descriptor*/ +#if LVGL_VERSION_MAJOR >= 8 +const lv_font_t montserrat_16_ru_en = { +#else +lv_font_t montserrat_16_ru_en = { +#endif + .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ + .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ + .line_height = 18, /*The maximum line height required by the font*/ + .base_line = 3, /*Baseline measured from the bottom of the line*/ +#if !(LVGL_VERSION_MAJOR == 6 && LVGL_VERSION_MINOR == 0) + .subpx = LV_FONT_SUBPX_NONE, +#endif +#if LV_VERSION_CHECK(7, 4, 0) || LVGL_VERSION_MAJOR >= 8 + .underline_position = -2, + .underline_thickness = 1, +#endif + .dsc = &font_dsc, /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ +#if LV_VERSION_CHECK(8, 2, 0) || LVGL_VERSION_MAJOR >= 9 + .fallback = &lv_font_montserrat_16, +#endif + .user_data = NULL, +}; + + + +#endif /*#if MONTSERRAT_16_RU_EN*/ diff --git a/src/FreeRTOS_Posix_Port.c b/src/FreeRTOS_Posix_Port.c new file mode 100644 index 0000000..5a98ec9 --- /dev/null +++ b/src/FreeRTOS_Posix_Port.c @@ -0,0 +1,92 @@ +/** + * @file Event management with pthreads + * @brief Implementation of an event mechanism using POSIX threads. + * @date 2024-09-03 + */ + +#include +#include +#include + +/* Structure representing an event, consisting of a condition variable and a mutex */ +typedef struct Event +{ + pthread_cond_t cond; /* Condition variable used to signal the event */ + pthread_mutex_t mutex; /* Mutex to protect access to the condition variable */ +} Event_t; + +/** + * @brief Create an event object + * + * Allocates memory for an Event_t structure and initializes its condition variable and mutex. + * + * @param None + * @return Pointer to the created Event_t object, or NULL if memory allocation fails + */ +Event_t *event_create(void) +{ + Event_t *event = (Event_t *)malloc(sizeof(Event_t)); /* Allocate memory for the event */ + if (event) /* Check if allocation was successful */ + { + pthread_cond_init(&event->cond, NULL); /* Initialize the condition variable */ + pthread_mutex_init(&event->mutex, NULL); /* Initialize the mutex */ + } + return event; /* Return the created event object */ +} + +// ........................................................................................................ +/** + * @brief Delete an event object + * + * Destroys the condition variable and mutex associated with the event, then frees the memory. + * + * @param event Pointer to the Event_t object to be deleted + * @return None + */ +void event_delete(Event_t *event) +{ + if (event) /* Check if the event object is valid */ + { + pthread_cond_destroy(&event->cond); /* Destroy the condition variable */ + pthread_mutex_destroy(&event->mutex); /* Destroy the mutex */ + free(event); /* Free the memory allocated for the event object */ + } +} + +// ........................................................................................................ +/** + * @brief Signal an event + * + * Signals the condition variable associated with the event, waking up any waiting threads. + * + * @param event Pointer to the Event_t object to be signaled + * @return None + */ +void event_signal(Event_t *event) +{ + if (event) /* Check if the event object is valid */ + { + pthread_mutex_lock(&event->mutex); /* Lock the mutex before signaling */ + pthread_cond_signal(&event->cond); /* Signal the condition variable */ + pthread_mutex_unlock(&event->mutex); /* Unlock the mutex after signaling */ + } +} + +// ........................................................................................................ +/** + * @brief Wait for an event + * + * Waits for the condition variable associated with the event to be signaled. + * + * @param event Pointer to the Event_t object to wait for + * @return None + */ +void event_wait(Event_t *event) +{ + if (event) /* Check if the event object is valid */ + { + pthread_mutex_lock(&event->mutex); /* Lock the mutex before waiting */ + pthread_cond_wait(&event->cond, &event->mutex); /* Wait for the condition variable to be signaled */ + pthread_mutex_unlock(&event->mutex); /* Unlock the mutex after waiting */ + } +} diff --git a/src/freertos_main.cpp b/src/freertos_main.cpp new file mode 100644 index 0000000..8c76ad5 --- /dev/null +++ b/src/freertos_main.cpp @@ -0,0 +1,179 @@ +/** + * @file Freertos main file + * @author MootSeeker + * @date 2024-09-02 + * @brief Main file for FreeRTOS tasks and hooks. + * @license MIT License + */ + +#include "lvgl/src/osal/lv_os.h" + +#if LV_USE_OS == LV_OS_FREERTOS + +#include "lvgl.h" +#include // For printf in C++ + +// ........................................................................................................ +/** + * @brief Malloc failed hook + * + * This function is called when a memory allocation (malloc) fails. It logs the available heap size and enters + * an infinite loop to halt the system. + * + * @param None + * @return None + */ +extern "C" void vApplicationMallocFailedHook(void) +{ + printf("Malloc failed! Available heap: %ld bytes\n", xPortGetFreeHeapSize()); + for( ;; ); +} + +// ........................................................................................................ +/** + * @brief Idle hook + * + * This function is called when the system is idle. It can be used for low-power mode operations or other + * maintenance tasks that need to run when the CPU is not busy. + * + * @param None + * @return None + */ +extern "C" void vApplicationIdleHook(void) {} + +// ........................................................................................................ +/** + * @brief Stack overflow hook + * + * This function is called when a stack overflow is detected in a task. It logs the task name and enters + * an infinite loop to halt the system. + * + * @param xTask Handle of the task that caused the stack overflow + * @param pcTaskName Name of the task that caused the stack overflow + * @return None + */ +extern "C" void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) +{ + printf("Stack overflow in task %s\n", pcTaskName); + for(;;); +} + +// ........................................................................................................ +/** + * @brief Tick hook + * + * This function is called on each tick interrupt. It can be used to execute periodic operations + * that need to occur at a fixed time interval. + * + * @param None + * @return None + */ +extern "C" void vApplicationTickHook(void) {} + +// ........................................................................................................ +/** + * @brief Create Hello World screen + * + * This function creates a simple LVGL screen with a "Hello, World!" label centered on the screen. + * + * @param None + * @return None + */ +void create_hello_world_screen() +{ + /* Create a new screen object */ + lv_obj_t *screen = lv_obj_create(NULL); + if (screen == NULL){ + printf("Error: Failed to create screen object\n"); + /* Return if screen creation fails */ + return; + } + + /* Create a new label object on the screen */ + lv_obj_t *label = lv_label_create(screen); + if (label == NULL){ + printf("Error: Failed to create label object\n"); + /* Return if label creation fails */ + return; + } + + /* Set the text of the label to "Hello, World!" */ + lv_label_set_text(label, "Hello, World!"); + + /* Align the label to the center of the screen */ + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + + /* Load the created screen and make it visible */ + lv_scr_load(screen); +} + +// ........................................................................................................ +/** + * @brief LVGL task + * + * This task initializes LVGL and runs the main loop, periodically calling the LVGL task handler. + * It is responsible for managing the LVGL state and rendering updates. + * + * @param pvParameters Task parameters (not used in this example) + * @return None + */ +void lvgl_task(void *pvParameters) +{ + /* Show simple hello world screen */ + create_hello_world_screen(); + + while (true){ + lv_timer_handler(); /* Handle LVGL tasks */ + vTaskDelay(pdMS_TO_TICKS(5)); /* Short delay for the RTOS scheduler */ + } +} + +// ........................................................................................................ +/** + * @brief Another task + * + * This task simulates some background work by periodically printing a message. + * + * @param pvParameters Task parameters (not used in this example) + * @return None + */ +void another_task(void *pvParameters) +{ + /* Create some load in an infinite loop */ + while (true){ + printf("Second Task is running :)\n"); + /* Delay the task for 500 milliseconds */ + vTaskDelay(pdMS_TO_TICKS(500)); + } +} + +// ........................................................................................................ +/** + * @brief FreeRTOS main function + * + * This function sets up and starts the FreeRTOS tasks, including the LVGL task and another demo task. + * + * @param None + * @return None + */ +extern "C" void freertos_main() +{ + /* Initialize LVGL (Light and Versatile Graphics Library) and other resources */ + + /* Create the LVGL task */ + if (xTaskCreate(lvgl_task, "LVGL Task", 4096, nullptr, 1, nullptr) != pdPASS) { + printf("Error creating LVGL task\n"); + /* Error handling */ + } + + /* Create another task */ + if (xTaskCreate(another_task, "Another Task", 1024, nullptr, 1, nullptr) != pdPASS) { + printf("Error creating another task\n"); + /* Error handling */ + } + + /* Start the scheduler */ + vTaskStartScheduler(); +} + +#endif diff --git a/src/gui_generated.c b/src/gui_generated.c new file mode 100644 index 0000000..1da7487 --- /dev/null +++ b/src/gui_generated.c @@ -0,0 +1,1654 @@ +/* AUTO-GENERATED by GUI Editor — do not edit manually */ +#include "gui_generated.h" +#include "lvgl.h" +#include +#include +#include +#include + +/* Fonts */ +LV_FONT_DECLARE(montserrat_16_ru_en) + +lv_obj_t *scr_main = NULL; +lv_obj_t *scr_screen1 = NULL; +lv_obj_t *scr_screen2 = NULL; +lv_obj_t *scr_screen3 = NULL; + + +/* Runtime variable values */ +static int32_t var_temp_room = 22; +static int32_t var_hum_room = 45; +static int32_t var_temp_channel = 20; +static int32_t var_hum_channel = 50; +static int32_t var_room_num = 101; +static int32_t var_is_master = 1; +static int32_t var_season = 0; // 0=Зима, 1=Лето, 2=Переход +static int32_t var_mode = 1; // 0=Остановка, 1=Дежурный, 2=Рабочий + +/* Equipment module states */ +static int32_t var_valve_inlet = 75; // Входной клапан 0-100% +static int32_t var_valve_recirc = 25; // Клапан рециркуляции 0-100% +static int32_t var_filter_g4 = 1; // 0=Грязный, 1=Чистый +static int32_t var_kws_valve = 50; // KWS клапан 0-100% +static int32_t var_pww_valve = 30; // PWW клапан 0-100% +static int32_t var_heater_on = 0; // Электронагреватель 0=Выкл, 1=Вкл +static int32_t var_fan_on = 1; // Вентилятор 0=Выкл, 1=Вкл +static int32_t var_filter_h13 = 1; // 0=Грязный, 1=Чистый + +/* Module configuration for drag&drop */ +typedef enum { + MODULE_VALVE_INLET = 0, + MODULE_VALVE_RECIRC, + MODULE_FILTER_G4, + MODULE_KWS, + MODULE_PWW, + MODULE_HEATER, + MODULE_FAN, + MODULE_FILTER_H13, + MODULE_COUNT +} module_type_t; + +typedef struct { + module_type_t type; + int enabled; // 1=показывать, 0=скрыть + int position; // позиция в ряду (0-7) + lv_obj_t *obj; // указатель на объект (для будущего drag&drop) +} module_config_t; + +static module_config_t modules[MODULE_COUNT] = { + {MODULE_VALVE_INLET, 1, 0, NULL}, + {MODULE_VALVE_RECIRC, 1, 1, NULL}, + {MODULE_FILTER_G4, 1, 2, NULL}, + {MODULE_KWS, 1, 3, NULL}, + {MODULE_PWW, 1, 4, NULL}, + {MODULE_HEATER, 1, 5, NULL}, + {MODULE_FAN, 1, 6, NULL}, + {MODULE_FILTER_H13, 1, 7, NULL}, +}; + +/* Alarm log structure */ +#define MAX_ALARMS 10 +typedef struct { + char message[100]; + char timestamp[20]; + int active; +} alarm_entry_t; + +static alarm_entry_t alarm_log[MAX_ALARMS]; +static int alarm_count = 0; + +/* Settings/Setpoints for Work and Standby modes */ +static float setpoint_work_temp = 22.0; +static float setpoint_work_hum = 50.0; +static float setpoint_standby_temp = 18.0; +static float setpoint_standby_hum = 45.0; + +/* Password and settings */ +#define PASSWORD "1234" +static char password_input[10] = ""; +static lv_obj_t *popup_password = NULL; +static lv_obj_t *lbl_password_display = NULL; + +/* Parameter editor */ +static lv_obj_t *popup_param_editor = NULL; +static lv_obj_t *lbl_param_value = NULL; +static char param_value_str[20] = ""; +static float *param_being_edited = NULL; +static char param_name[50] = ""; + +/* Configuration parameters */ +static float config_temp_room_offset = 0.0; +static float config_hum_room_offset = 0.0; +static float config_temp_channel_offset = 0.0; +static float config_hum_channel_offset = 0.0; + +/* UI element references for updates */ +static lv_obj_t *lbl_temp_room = NULL; +static lv_obj_t *lbl_hum_room = NULL; +static lv_obj_t *lbl_temp_channel = NULL; +static lv_obj_t *lbl_hum_channel = NULL; +static lv_obj_t *lbl_room_num = NULL; +static lv_obj_t *lbl_master_slave = NULL; +static lv_obj_t *lbl_season = NULL; +static lv_obj_t *lbl_mode = NULL; +static lv_obj_t *lbl_datetime = NULL; + +/* Equipment UI references */ +static lv_obj_t *lbl_valve_inlet = NULL; +static lv_obj_t *lbl_valve_recirc = NULL; +static lv_obj_t *lbl_filter_g4 = NULL; +static lv_obj_t *lbl_kws = NULL; +static lv_obj_t *lbl_pww = NULL; +static lv_obj_t *lbl_heater = NULL; +static lv_obj_t *lbl_fan = NULL; +static lv_obj_t *lbl_filter_h13 = NULL; + +/* Popup windows */ +static lv_obj_t *popup_readings = NULL; +static lv_obj_t *popup_alarm = NULL; + +/* Forward declarations */ +static void create_popup_readings(void); +static void create_popup_alarm(const char *message); +static void add_alarm_to_log(const char *message, int active); +static void btn_log_cb(lv_event_t *e); +static void btn_settings_cb(lv_event_t *e); +static void btn_config_cb(lv_event_t *e); +static void create_popup_password(void); +static void password_keypad_cb(lv_event_t *e); +static void create_popup_param_editor(const char *name, float *param_ptr); +static void param_keypad_cb(lv_event_t *e); +static void close_popup_cb(lv_event_t *e); +static void btn_back_to_main_cb(lv_event_t *e); + +/* Button callbacks */ +static void btn_stop_cb(lv_event_t *e) { + (void)e; + var_mode = 0; + gui_update_values(); +} + +static void btn_standby_cb(lv_event_t *e) { + (void)e; + var_mode = 1; + gui_update_values(); +} + +static void btn_work_cb(lv_event_t *e) { + (void)e; + var_mode = 2; + gui_update_values(); +} + +static void btn_menu_cb(lv_event_t *e) { + (void)e; + if (scr_screen1) lv_scr_load(scr_screen1); +} + +static void btn_back_to_main_cb(lv_event_t *e) { + (void)e; + if (scr_main) lv_scr_load(scr_main); +} + +static void btn_readings_cb(lv_event_t *e) { + (void)e; + create_popup_readings(); +} + +static void close_popup_cb(lv_event_t *e) { + lv_obj_t *popup = lv_event_get_user_data(e); + if (popup) { + lv_obj_del(popup); + } + if (popup == popup_readings) popup_readings = NULL; + if (popup == popup_alarm) popup_alarm = NULL; + if (popup == popup_password) { + popup_password = NULL; + memset(password_input, 0, sizeof(password_input)); + } + if (popup == popup_param_editor) { + popup_param_editor = NULL; + memset(param_value_str, 0, sizeof(param_value_str)); + param_being_edited = NULL; + } +} + +static void btn_log_cb(lv_event_t *e) { + (void)e; + if (scr_screen2) lv_scr_load(scr_screen2); +} + +static void btn_settings_cb(lv_event_t *e) { + (void)e; + if (scr_screen3) lv_scr_load(scr_screen3); +} + +static void btn_config_cb(lv_event_t *e) { + (void)e; + create_popup_password(); +} + +/* Edit parameter callbacks */ +static void edit_work_temp_cb(lv_event_t *e) { + (void)e; + create_popup_param_editor("Температура (Рабочий)", &setpoint_work_temp); +} + +static void edit_work_hum_cb(lv_event_t *e) { + (void)e; + create_popup_param_editor("Влажность (Рабочий)", &setpoint_work_hum); +} + +static void edit_standby_temp_cb(lv_event_t *e) { + (void)e; + create_popup_param_editor("Температура (Дежурный)", &setpoint_standby_temp); +} + +static void edit_standby_hum_cb(lv_event_t *e) { + (void)e; + create_popup_param_editor("Влажность (Дежурный)", &setpoint_standby_hum); +} + +/* Password keypad callback */ +static void password_keypad_cb(lv_event_t *e) { + const char *key = lv_event_get_user_data(e); + int len = strlen(password_input); + + if (strcmp(key, "C") == 0) { + // Clear + memset(password_input, 0, sizeof(password_input)); + } else if (strcmp(key, "OK") == 0) { + // Check password + if (strcmp(password_input, PASSWORD) == 0) { + // Correct password - close popup and show success message + if (popup_password) { + lv_obj_del(popup_password); + popup_password = NULL; + lbl_password_display = NULL; + } + memset(password_input, 0, sizeof(password_input)); + + // Show success popup + lv_obj_t *popup_success = lv_obj_create(lv_screen_active()); + lv_obj_set_size(popup_success, 450, 200); + lv_obj_center(popup_success); + lv_obj_set_style_bg_color(popup_success, lv_color_hex(0x27AE60), 0); + lv_obj_set_style_radius(popup_success, 12, 0); + + lv_obj_t *lbl = lv_label_create(popup_success); + lv_label_set_text(lbl, "✓ ДОСТУП РАЗРЕШЁН\n\nЭкран настроек будет\nдобавлен в следующей версии"); + lv_obj_center(lbl); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_set_style_text_align(lbl, LV_TEXT_ALIGN_CENTER, 0); + + // Auto-close after showing message (we'll just leave X button for now) + lv_obj_t *btn_close = lv_btn_create(popup_success); + lv_obj_set_pos(btn_close, 405, 10); + lv_obj_set_size(btn_close, 35, 35); + lv_obj_set_style_bg_color(btn_close, lv_color_hex(0x1E8449), 0); + lv_obj_set_style_radius(btn_close, 6, 0); + lbl = lv_label_create(btn_close); + lv_label_set_text(lbl, "X"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_success); + } else { + // Wrong password + if (lbl_password_display) { + lv_label_set_text(lbl_password_display, "НЕВЕРНЫЙ ПАРОЛЬ!"); + lv_obj_set_style_text_color(lbl_password_display, lv_color_hex(0xE74C3C), 0); + } + memset(password_input, 0, sizeof(password_input)); + } + } else if (len < 8) { + // Add digit + strcat(password_input, key); + } + + // Update display + if (lbl_password_display) { + char display[20] = ""; + for (int i = 0; i < (int)strlen(password_input); i++) { + strcat(display, "*"); + } + if (strlen(display) == 0) { + lv_label_set_text(lbl_password_display, "Введите пароль"); + lv_obj_set_style_text_color(lbl_password_display, lv_color_hex(0xBDC3C7), 0); + } else { + lv_label_set_text(lbl_password_display, display); + lv_obj_set_style_text_color(lbl_password_display, lv_color_hex(0x2ECC71), 0); + } + } +} + +/* Create password popup with keypad */ +static void create_popup_password(void) { + if (popup_password) return; // Already open + + memset(password_input, 0, sizeof(password_input)); + + popup_password = lv_obj_create(lv_screen_active()); + lv_obj_set_size(popup_password, 400, 400); + lv_obj_center(popup_password); + lv_obj_set_style_bg_color(popup_password, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(popup_password, 12, 0); + lv_obj_set_style_border_width(popup_password, 3, 0); + lv_obj_set_style_border_color(popup_password, lv_color_hex(0xE67E22), 0); + + /* Title */ + lv_obj_t *lbl = lv_label_create(popup_password); + lv_label_set_text(lbl, "Введите пароль"); + lv_obj_set_pos(lbl, 130, 15); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Close button (X) */ + lv_obj_t *btn_close = lv_btn_create(popup_password); + lv_obj_set_pos(btn_close, 355, 10); + lv_obj_set_size(btn_close, 35, 35); + lv_obj_set_style_bg_color(btn_close, lv_color_hex(0xC0392B), 0); + lv_obj_set_style_radius(btn_close, 6, 0); + lbl = lv_label_create(btn_close); + lv_label_set_text(lbl, "X"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_password); + + /* Password display */ + lbl_password_display = lv_label_create(popup_password); + lv_label_set_text(lbl_password_display, "Введите пароль"); + lv_obj_set_pos(lbl_password_display, 130, 60); + lv_obj_set_style_text_color(lbl_password_display, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl_password_display, &montserrat_16_ru_en, 0); + + /* Numeric keypad 3x4 */ + const char *keys[12] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "C", "0", "OK"}; + int key_size = 70; + int key_spacing = 10; + int start_x = 40; + int start_y = 110; + + for (int i = 0; i < 12; i++) { + int row = i / 3; + int col = i % 3; + + lv_obj_t *btn = lv_btn_create(popup_password); + lv_obj_set_pos(btn, start_x + col * (key_size + key_spacing), + start_y + row * (key_size + key_spacing)); + lv_obj_set_size(btn, key_size, key_size); + + // Color coding + if (strcmp(keys[i], "C") == 0) { + lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); + } else if (strcmp(keys[i], "OK") == 0) { + lv_obj_set_style_bg_color(btn, lv_color_hex(0x2ECC71), 0); + } else { + lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); + } + lv_obj_set_style_radius(btn, 8, 0); + + lbl = lv_label_create(btn); + lv_label_set_text(lbl, keys[i]); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + + lv_obj_add_event_cb(btn, password_keypad_cb, LV_EVENT_CLICKED, (void*)keys[i]); + } +} + +/* Parameter editor keypad callback */ +static void param_keypad_cb(lv_event_t *e) { + const char *key = lv_event_get_user_data(e); + int len = strlen(param_value_str); + + if (strcmp(key, "C") == 0) { + memset(param_value_str, 0, sizeof(param_value_str)); + } else if (strcmp(key, ".") == 0) { + if (len > 0 && strchr(param_value_str, '.') == NULL) { + strcat(param_value_str, "."); + } + } else if (strcmp(key, "OK") == 0) { + if (param_being_edited && strlen(param_value_str) > 0) { + *param_being_edited = atof(param_value_str); + } + if (popup_param_editor) { + lv_obj_del(popup_param_editor); + popup_param_editor = NULL; + lbl_param_value = NULL; + } + memset(param_value_str, 0, sizeof(param_value_str)); + param_being_edited = NULL; + return; + } else if (len < 18) { + strcat(param_value_str, key); + } + + if (lbl_param_value) { + if (strlen(param_value_str) == 0) { + lv_label_set_text(lbl_param_value, "0.0"); + } else { + lv_label_set_text(lbl_param_value, param_value_str); + } + } +} + +/* Create parameter editor popup */ +static void create_popup_param_editor(const char *name, float *param_ptr) { + if (popup_param_editor) return; + + param_being_edited = param_ptr; + strncpy(param_name, name, 49); + param_name[49] = '\0'; + memset(param_value_str, 0, sizeof(param_value_str)); + snprintf(param_value_str, sizeof(param_value_str), "%.1f", *param_ptr); + + popup_param_editor = lv_obj_create(lv_screen_active()); + lv_obj_set_size(popup_param_editor, 400, 430); + lv_obj_center(popup_param_editor); + lv_obj_set_style_bg_color(popup_param_editor, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(popup_param_editor, 12, 0); + lv_obj_set_style_border_width(popup_param_editor, 3, 0); + lv_obj_set_style_border_color(popup_param_editor, lv_color_hex(0x3498DB), 0); + + /* Title */ + lv_obj_t *lbl = lv_label_create(popup_param_editor); + lv_label_set_text(lbl, param_name); + lv_obj_set_pos(lbl, 20, 15); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Close button (X) */ + lv_obj_t *btn_close = lv_btn_create(popup_param_editor); + lv_obj_set_pos(btn_close, 355, 10); + lv_obj_set_size(btn_close, 35, 35); + lv_obj_set_style_bg_color(btn_close, lv_color_hex(0xC0392B), 0); + lv_obj_set_style_radius(btn_close, 6, 0); + lbl = lv_label_create(btn_close); + lv_label_set_text(lbl, "X"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_param_editor); + + /* Value display */ + lbl_param_value = lv_label_create(popup_param_editor); + lv_label_set_text(lbl_param_value, param_value_str); + lv_obj_set_pos(lbl_param_value, 150, 60); + lv_obj_set_style_text_color(lbl_param_value, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_text_font(lbl_param_value, &montserrat_16_ru_en, 0); + + /* Numeric keypad with decimal point */ + const char *keys[12] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", "C", "0", "."}; + int key_size = 70; + int key_spacing = 10; + int start_x = 40; + int start_y = 110; + + for (int i = 0; i < 12; i++) { + int row = i / 3; + int col = i % 3; + + lv_obj_t *btn = lv_btn_create(popup_param_editor); + lv_obj_set_pos(btn, start_x + col * (key_size + key_spacing), + start_y + row * (key_size + key_spacing)); + lv_obj_set_size(btn, key_size, key_size); + + if (strcmp(keys[i], "C") == 0) { + lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); + } else if (strcmp(keys[i], ".") == 0) { + lv_obj_set_style_bg_color(btn, lv_color_hex(0xF39C12), 0); + } else { + lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); + } + lv_obj_set_style_radius(btn, 8, 0); + + lbl = lv_label_create(btn); + lv_label_set_text(lbl, keys[i]); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + + lv_obj_add_event_cb(btn, param_keypad_cb, LV_EVENT_CLICKED, (void*)keys[i]); + } + + /* OK button (wider) */ + lv_obj_t *btn_ok = lv_btn_create(popup_param_editor); + lv_obj_set_pos(btn_ok, 130, 390); + lv_obj_set_size(btn_ok, 160, 35); + lv_obj_set_style_bg_color(btn_ok, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_radius(btn_ok, 8, 0); + lbl = lv_label_create(btn_ok); + lv_label_set_text(lbl, "OK"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn_ok, param_keypad_cb, LV_EVENT_CLICKED, (void*)"OK"); +} + +/* Create popup window for sensor readings */ +static void create_popup_readings(void) { + if (popup_readings) return; // Already open + + popup_readings = lv_obj_create(lv_screen_active()); + lv_obj_set_size(popup_readings, 400, 280); + lv_obj_center(popup_readings); + lv_obj_set_style_bg_color(popup_readings, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(popup_readings, 12, 0); + lv_obj_set_style_border_width(popup_readings, 3, 0); + lv_obj_set_style_border_color(popup_readings, lv_color_hex(0x3498DB), 0); + + /* Title */ + lv_obj_t *lbl = lv_label_create(popup_readings); + lv_label_set_text(lbl, "ПОКАЗАНИЯ ДАТЧИКОВ"); + lv_obj_set_pos(lbl, 20, 15); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Close button (X) */ + lv_obj_t *btn_close = lv_btn_create(popup_readings); + lv_obj_set_pos(btn_close, 355, 10); + lv_obj_set_size(btn_close, 35, 35); + lv_obj_set_style_bg_color(btn_close, lv_color_hex(0xC0392B), 0); + lv_obj_set_style_radius(btn_close, 6, 0); + lbl = lv_label_create(btn_close); + lv_label_set_text(lbl, "X"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_readings); + + /* Room sensors */ + int y = 60; + lbl = lv_label_create(popup_readings); + lv_label_set_text(lbl, "КОМНАТА:"); + lv_obj_set_pos(lbl, 30, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xF39C12), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 30; + lbl = lv_label_create(popup_readings); + char buf[64]; + snprintf(buf, sizeof(buf), "Температура комнаты: %.1f°C", var_temp_room / 1.0); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 40, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xE74C3C), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 30; + lbl = lv_label_create(popup_readings); + snprintf(buf, sizeof(buf), "Влажность комнаты: %d%%", (int)var_hum_room); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 40, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Channel sensors */ + y += 40; + lbl = lv_label_create(popup_readings); + lv_label_set_text(lbl, "КАНАЛ ПРИТОКА:"); + lv_obj_set_pos(lbl, 30, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xF39C12), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 30; + lbl = lv_label_create(popup_readings); + snprintf(buf, sizeof(buf), "Температура притока: %.1f°C", var_temp_channel / 1.0); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 40, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xE74C3C), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 30; + lbl = lv_label_create(popup_readings); + snprintf(buf, sizeof(buf), "Влажность притока: %d%%", (int)var_hum_channel); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 40, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); +} + +/* Add alarm to log */ +static void add_alarm_to_log(const char *message, int active) { + if (alarm_count < MAX_ALARMS) { + strncpy(alarm_log[alarm_count].message, message, 99); + alarm_log[alarm_count].message[99] = '\0'; + snprintf(alarm_log[alarm_count].timestamp, 20, "25.02.2026 09:35"); + alarm_log[alarm_count].active = active; + alarm_count++; + } +} + +/* Create alarm popup */ +static void create_popup_alarm(const char *message) { + if (popup_alarm) { + lv_obj_del(popup_alarm); + } + + /* Add to log */ + add_alarm_to_log(message, 1); + + popup_alarm = lv_obj_create(lv_screen_active()); + lv_obj_set_size(popup_alarm, 450, 200); + lv_obj_center(popup_alarm); + lv_obj_set_style_bg_color(popup_alarm, lv_color_hex(0xC0392B), 0); + lv_obj_set_style_radius(popup_alarm, 12, 0); + lv_obj_set_style_border_width(popup_alarm, 3, 0); + lv_obj_set_style_border_color(popup_alarm, lv_color_hex(0xE74C3C), 0); + + /* Title */ + lv_obj_t *lbl = lv_label_create(popup_alarm); + lv_label_set_text(lbl, "⚠ АВАРИЯ ⚠"); + lv_obj_set_pos(lbl, 20, 15); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Close button (X) */ + lv_obj_t *btn_close = lv_btn_create(popup_alarm); + lv_obj_set_pos(btn_close, 405, 10); + lv_obj_set_size(btn_close, 35, 35); + lv_obj_set_style_bg_color(btn_close, lv_color_hex(0x2C3E50), 0); + lv_obj_set_style_radius(btn_close, 6, 0); + lbl = lv_label_create(btn_close); + lv_label_set_text(lbl, "X"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn_close, close_popup_cb, LV_EVENT_CLICKED, popup_alarm); + + /* Message */ + lbl = lv_label_create(popup_alarm); + lv_label_set_text(lbl, message); + lv_obj_set_pos(lbl, 30, 70); + lv_obj_set_width(lbl, 390); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_label_set_long_mode(lbl, LV_LABEL_LONG_WRAP); +} + +static void create_screen_main(void) { + lv_obj_t *scr = lv_obj_create(NULL); + scr_main = scr; + lv_obj_set_style_bg_color(scr, lv_color_hex(0x2C3E50), 0); + lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); + lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); + + /* === STATUS PANEL === */ + lv_obj_t *panel_status = lv_obj_create(scr); + lv_obj_set_pos(panel_status, 10, 320); + lv_obj_set_size(panel_status, 230, 150); + lv_obj_set_style_bg_color(panel_status, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(panel_status, 8, 0); + lv_obj_set_style_border_width(panel_status, 0, 0); + + lv_obj_t *lbl = lv_label_create(panel_status); + lv_label_set_text(lbl, "Состояние системы"); + lv_obj_set_pos(lbl, 10, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + lbl_room_num = lv_label_create(panel_status); + lv_label_set_text(lbl_room_num, "Комната: 101"); + lv_obj_set_pos(lbl_room_num, 10, 30); + lv_obj_set_style_text_color(lbl_room_num, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl_room_num, &montserrat_16_ru_en, 0); + + lbl_master_slave = lv_label_create(panel_status); + lv_label_set_text(lbl_master_slave, "Мастер"); + lv_obj_set_pos(lbl_master_slave, 10, 50); + lv_obj_set_style_text_color(lbl_master_slave, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_text_font(lbl_master_slave, &montserrat_16_ru_en, 0); + + lbl_season = lv_label_create(panel_status); + lv_label_set_text(lbl_season, "Сезон: Зима"); + lv_obj_set_pos(lbl_season, 10, 70); + lv_obj_set_style_text_color(lbl_season, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_text_font(lbl_season, &montserrat_16_ru_en, 0); + + lbl_mode = lv_label_create(panel_status); + lv_label_set_text(lbl_mode, "Режим: Дежурный"); + lv_obj_set_pos(lbl_mode, 10, 90); + lv_obj_set_style_text_color(lbl_mode, lv_color_hex(0xF39C12), 0); + lv_obj_set_style_text_font(lbl_mode, &montserrat_16_ru_en, 0); + + lbl_datetime = lv_label_create(panel_status); + lv_label_set_text(lbl_datetime, "25.02.2025 09:25"); + lv_obj_set_pos(lbl_datetime, 10, 115); + lv_obj_set_style_text_color(lbl_datetime, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl_datetime, &montserrat_16_ru_en, 0); + + /* === CLIMATE PANEL === */ + lv_obj_t *panel_climate = lv_obj_create(scr); + lv_obj_set_pos(panel_climate, 250, 320); + lv_obj_set_size(panel_climate, 220, 150); + lv_obj_set_style_bg_color(panel_climate, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(panel_climate, 8, 0); + lv_obj_set_style_border_width(panel_climate, 0, 0); + + lbl = lv_label_create(panel_climate); + lv_label_set_text(lbl, "Климат в помещении"); + lv_obj_set_pos(lbl, 10, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + lbl = lv_label_create(panel_climate); + lv_label_set_text(lbl, "Температура:"); + lv_obj_set_pos(lbl, 10, 40); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + lbl_temp_room = lv_label_create(panel_climate); + lv_label_set_text(lbl_temp_room, "22.0°C"); + lv_obj_set_pos(lbl_temp_room, 130, 40); + lv_obj_set_style_text_color(lbl_temp_room, lv_color_hex(0xE74C3C), 0); + lv_obj_set_style_text_font(lbl_temp_room, &montserrat_16_ru_en, 0); + + lbl = lv_label_create(panel_climate); + lv_label_set_text(lbl, "Влажность:"); + lv_obj_set_pos(lbl, 10, 70); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + lbl_hum_room = lv_label_create(panel_climate); + lv_label_set_text(lbl_hum_room, "45%"); + lv_obj_set_pos(lbl_hum_room, 130, 70); + lv_obj_set_style_text_color(lbl_hum_room, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_text_font(lbl_hum_room, &montserrat_16_ru_en, 0); + + /* === CONTROL BUTTONS === */ + /* Stop button */ + lv_obj_t *btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 480, 320); + lv_obj_set_size(btn, 100, 80); + lv_obj_set_style_bg_color(btn, lv_color_hex(0xC0392B), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Останов"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_stop_cb, LV_EVENT_CLICKED, NULL); + + /* Standby button */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 590, 320); + lv_obj_set_size(btn, 100, 36); + lv_obj_set_style_bg_color(btn, lv_color_hex(0xF39C12), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Дежурный"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_standby_cb, LV_EVENT_CLICKED, NULL); + + /* Work button */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 590, 364); + lv_obj_set_size(btn, 100, 36); + lv_obj_set_style_bg_color(btn, lv_color_hex(0x27AE60), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Рабочий"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_work_cb, LV_EVENT_CLICKED, NULL); + + /* Menu button */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 700, 320); + lv_obj_set_size(btn, 90, 36); + lv_obj_set_style_bg_color(btn, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Меню"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_menu_cb, LV_EVENT_CLICKED, NULL); + + /* Readings button */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 700, 364); + lv_obj_set_size(btn, 90, 36); + lv_obj_set_style_bg_color(btn, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Показания"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_readings_cb, LV_EVENT_CLICKED, NULL); + + /* === EQUIPMENT SCHEMA AREA === */ + lv_obj_t *panel_schema = lv_obj_create(scr); + lv_obj_set_pos(panel_schema, 10, 10); + lv_obj_set_size(panel_schema, 780, 300); + lv_obj_set_style_bg_color(panel_schema, lv_color_hex(0x1A252F), 0); + lv_obj_set_style_radius(panel_schema, 8, 0); + lv_obj_set_style_border_width(panel_schema, 2, 0); + lv_obj_set_style_border_color(panel_schema, lv_color_hex(0x34495E), 0); + + int x_pos = 15; + int y_pos = 20; + int module_width = 70; + int module_height = 60; + int spacing = 10; + + /* Title */ + lbl = lv_label_create(panel_schema); + lv_label_set_text(lbl, "Схема установки"); + lv_obj_set_pos(lbl, 10, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Module 1: Входной клапан */ + if (modules[MODULE_VALVE_INLET].enabled) { + lv_obj_t *mod1 = lv_obj_create(panel_schema); + modules[MODULE_VALVE_INLET].obj = mod1; + lv_obj_set_pos(mod1, x_pos, y_pos); + lv_obj_set_size(mod1, module_width, module_height); + lv_obj_set_style_bg_color(mod1, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod1, 5, 0); + lv_obj_set_style_border_width(mod1, 1, 0); + lv_obj_set_style_border_color(mod1, lv_color_hex(0x7F8C8D), 0); + // TODO: Add image here - lv_image_set_src(img, &img_valve); + lbl = lv_label_create(mod1); + lv_label_set_text(lbl, "Вход.\nклапан"); + lv_obj_set_pos(lbl, 5, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_valve_inlet = lv_label_create(mod1); + lv_label_set_text(lbl_valve_inlet, "75%"); + lv_obj_set_pos(lbl_valve_inlet, 20, 38); + lv_obj_set_style_text_color(lbl_valve_inlet, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_text_font(lbl_valve_inlet, &montserrat_16_ru_en, 0); + x_pos += module_width + spacing; + } + + /* Module 2: Клапан рециркуляции */ + if (modules[MODULE_VALVE_RECIRC].enabled) { + lv_obj_t *mod2 = lv_obj_create(panel_schema); + modules[MODULE_VALVE_RECIRC].obj = mod2; + lv_obj_set_pos(mod2, x_pos, y_pos); + lv_obj_set_size(mod2, module_width, module_height); + lv_obj_set_style_bg_color(mod2, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod2, 5, 0); + lv_obj_set_style_border_width(mod2, 1, 0); + lv_obj_set_style_border_color(mod2, lv_color_hex(0x7F8C8D), 0); + // TODO: Add image here - lv_image_set_src(img, &img_valve_recirc); + lbl = lv_label_create(mod2); + lv_label_set_text(lbl, "Рецирк.\nклапан"); + lv_obj_set_pos(lbl, 5, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_valve_recirc = lv_label_create(mod2); + lv_label_set_text(lbl_valve_recirc, "25%"); + lv_obj_set_pos(lbl_valve_recirc, 20, 38); + lv_obj_set_style_text_color(lbl_valve_recirc, lv_color_hex(0xF39C12), 0); + lv_obj_set_style_text_font(lbl_valve_recirc, &montserrat_16_ru_en, 0); + x_pos += module_width + spacing; + } + + /* Module 3: Фильтр G4 */ + if (modules[MODULE_FILTER_G4].enabled) { + lv_obj_t *mod3 = lv_obj_create(panel_schema); + modules[MODULE_FILTER_G4].obj = mod3; + lv_obj_set_pos(mod3, x_pos, y_pos); + lv_obj_set_size(mod3, module_width, module_height); + lv_obj_set_style_bg_color(mod3, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod3, 5, 0); + lv_obj_set_style_border_width(mod3, 1, 0); + lv_obj_set_style_border_color(mod3, lv_color_hex(0x7F8C8D), 0); + // TODO: Add image here - lv_image_set_src(img, &img_filter); + lbl = lv_label_create(mod3); + lv_label_set_text(lbl, "Фильтр\nG4"); + lv_obj_set_pos(lbl, 10, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_filter_g4 = lv_label_create(mod3); + lv_label_set_text(lbl_filter_g4, "Чистый"); + lv_obj_set_pos(lbl_filter_g4, 8, 38); + lv_obj_set_style_text_color(lbl_filter_g4, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_text_font(lbl_filter_g4, &montserrat_16_ru_en, 0); + x_pos += module_width + spacing; + } + + /* Module 4: KWS */ + if (modules[MODULE_KWS].enabled) { + lv_obj_t *mod4 = lv_obj_create(panel_schema); + modules[MODULE_KWS].obj = mod4; + lv_obj_set_pos(mod4, x_pos, y_pos); + lv_obj_set_size(mod4, module_width, module_height); + lv_obj_set_style_bg_color(mod4, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod4, 5, 0); + lv_obj_set_style_border_width(mod4, 1, 0); + lv_obj_set_style_border_color(mod4, lv_color_hex(0x7F8C8D), 0); + // TODO: Add image here - lv_image_set_src(img, &img_heater_cooler); + lbl = lv_label_create(mod4); + lv_label_set_text(lbl, "KWS"); + lv_obj_set_pos(lbl, 20, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_kws = lv_label_create(mod4); + lv_label_set_text(lbl_kws, "50%"); + lv_obj_set_pos(lbl_kws, 20, 25); + lv_obj_set_style_text_color(lbl_kws, lv_color_hex(0xE74C3C), 0); + lv_obj_set_style_text_font(lbl_kws, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod4); + lv_label_set_text(lbl, "Нагрев"); + lv_obj_set_pos(lbl, 10, 42); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xE67E22), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + x_pos += module_width + spacing; + } + + /* Module 5: PWW */ + if (modules[MODULE_PWW].enabled) { + lv_obj_t *mod5 = lv_obj_create(panel_schema); + modules[MODULE_PWW].obj = mod5; + lv_obj_set_pos(mod5, x_pos, y_pos); + lv_obj_set_size(mod5, module_width, module_height); + lv_obj_set_style_bg_color(mod5, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod5, 5, 0); + lv_obj_set_style_border_width(mod5, 1, 0); + lv_obj_set_style_border_color(mod5, lv_color_hex(0x7F8C8D), 0); + // TODO: Add image here - lv_image_set_src(img, &img_heater_cooler); + lbl = lv_label_create(mod5); + lv_label_set_text(lbl, "PWW"); + lv_obj_set_pos(lbl, 20, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_pww = lv_label_create(mod5); + lv_label_set_text(lbl_pww, "30%"); + lv_obj_set_pos(lbl_pww, 20, 25); + lv_obj_set_style_text_color(lbl_pww, lv_color_hex(0xE74C3C), 0); + lv_obj_set_style_text_font(lbl_pww, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod5); + lv_label_set_text(lbl, "Нагрев"); + lv_obj_set_pos(lbl, 10, 42); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xE67E22), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + x_pos += module_width + spacing; + } + + /* Module 6: Электронагреватель */ + if (modules[MODULE_HEATER].enabled) { + lv_obj_t *mod6 = lv_obj_create(panel_schema); + modules[MODULE_HEATER].obj = mod6; + lv_obj_set_pos(mod6, x_pos, y_pos); + lv_obj_set_size(mod6, module_width, module_height); + lv_obj_set_style_bg_color(mod6, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod6, 5, 0); + lv_obj_set_style_border_width(mod6, 1, 0); + lv_obj_set_style_border_color(mod6, lv_color_hex(0x7F8C8D), 0); + // TODO: Add image here - lv_image_set_src(img, &img_electric_heater); + lbl = lv_label_create(mod6); + lv_label_set_text(lbl, "Электро\nнагрев"); + lv_obj_set_pos(lbl, 5, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_heater = lv_label_create(mod6); + lv_label_set_text(lbl_heater, "ВЫКЛ"); + lv_obj_set_pos(lbl_heater, 15, 38); + lv_obj_set_style_text_color(lbl_heater, lv_color_hex(0x7F8C8D), 0); + lv_obj_set_style_text_font(lbl_heater, &montserrat_16_ru_en, 0); + x_pos += module_width + spacing; + } + + /* Module 7: Вентилятор */ + if (modules[MODULE_FAN].enabled) { + lv_obj_t *mod7 = lv_obj_create(panel_schema); + modules[MODULE_FAN].obj = mod7; + lv_obj_set_pos(mod7, x_pos, y_pos); + lv_obj_set_size(mod7, module_width, module_height); + lv_obj_set_style_bg_color(mod7, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod7, 5, 0); + lv_obj_set_style_border_width(mod7, 1, 0); + lv_obj_set_style_border_color(mod7, lv_color_hex(0x7F8C8D), 0); + // TODO: Add image here - lv_image_set_src(img, &img_fan); + lbl = lv_label_create(mod7); + lv_label_set_text(lbl, "Вентил."); + lv_obj_set_pos(lbl, 5, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_fan = lv_label_create(mod7); + lv_label_set_text(lbl_fan, "ВКЛ"); + lv_obj_set_pos(lbl_fan, 20, 38); + lv_obj_set_style_text_color(lbl_fan, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_text_font(lbl_fan, &montserrat_16_ru_en, 0); + x_pos += module_width + spacing; + } + + /* Module 8: Фильтр H13 */ + if (modules[MODULE_FILTER_H13].enabled) { + lv_obj_t *mod8 = lv_obj_create(panel_schema); + modules[MODULE_FILTER_H13].obj = mod8; + lv_obj_set_pos(mod8, x_pos, y_pos); + lv_obj_set_size(mod8, module_width, module_height); + lv_obj_set_style_bg_color(mod8, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod8, 5, 0); + lv_obj_set_style_border_width(mod8, 1, 0); + lv_obj_set_style_border_color(mod8, lv_color_hex(0x7F8C8D), 0); + // TODO: Add image here - lv_image_set_src(img, &img_filter); + lbl = lv_label_create(mod8); + lv_label_set_text(lbl, "Фильтр\nH13"); + lv_obj_set_pos(lbl, 10, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_filter_h13 = lv_label_create(mod8); + lv_label_set_text(lbl_filter_h13, "Чистый"); + lv_obj_set_pos(lbl_filter_h13, 8, 38); + lv_obj_set_style_text_color(lbl_filter_h13, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_text_font(lbl_filter_h13, &montserrat_16_ru_en, 0); + } + + /* Bottom row: Канал и Комната */ + y_pos = 100; + x_pos = 15; + + /* Module 9: Канал (после установки) */ + lv_obj_t *mod9 = lv_obj_create(panel_schema); + lv_obj_set_pos(mod9, x_pos, y_pos); + lv_obj_set_size(mod9, 120, 80); + lv_obj_set_style_bg_color(mod9, lv_color_hex(0x2C3E50), 0); + lv_obj_set_style_radius(mod9, 8, 0); + lv_obj_set_style_border_width(mod9, 2, 0); + lv_obj_set_style_border_color(mod9, lv_color_hex(0x3498DB), 0); + lbl = lv_label_create(mod9); + lv_label_set_text(lbl, "КАНАЛ"); + lv_obj_set_pos(lbl, 10, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod9); + lv_label_set_text(lbl, "Температура:"); + lv_obj_set_pos(lbl, 5, 28); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_temp_channel = lv_label_create(mod9); + lv_label_set_text(lbl_temp_channel, "20.0°C"); + lv_obj_set_pos(lbl_temp_channel, 10, 45); + lv_obj_set_style_text_color(lbl_temp_channel, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_text_font(lbl_temp_channel, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod9); + lv_label_set_text(lbl, "Влажность:"); + lv_obj_set_pos(lbl, 5, 60); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl_hum_channel = lv_label_create(mod9); + lv_label_set_text(lbl_hum_channel, "50%"); + lv_obj_set_pos(lbl_hum_channel, 80, 60); + lv_obj_set_style_text_color(lbl_hum_channel, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_text_font(lbl_hum_channel, &montserrat_16_ru_en, 0); + + /* Module 10: Комната */ + x_pos += 140; + lv_obj_t *mod10 = lv_obj_create(panel_schema); + lv_obj_set_pos(mod10, x_pos, y_pos); + lv_obj_set_size(mod10, 250, 180); + lv_obj_set_style_bg_color(mod10, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(mod10, 10, 0); + lv_obj_set_style_border_width(mod10, 3, 0); + lv_obj_set_style_border_color(mod10, lv_color_hex(0x2ECC71), 0); + lbl = lv_label_create(mod10); + lv_label_set_text(lbl, "ПОМЕЩЕНИЕ"); + lv_obj_set_pos(lbl, 10, 10); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod10); + lv_label_set_text(lbl, "Комната 101"); + lv_obj_set_pos(lbl, 10, 35); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod10); + lv_label_set_text(lbl, "Температура: 22.0°C"); + lv_obj_set_pos(lbl, 10, 60); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xE74C3C), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod10); + lv_label_set_text(lbl, "Влажность: 45%"); + lv_obj_set_pos(lbl, 10, 85); + lv_obj_set_style_text_color(lbl, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod10); + lv_label_set_text(lbl, "Режим: Дежурный"); + lv_obj_set_pos(lbl, 10, 110); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xF39C12), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lbl = lv_label_create(mod10); + lv_label_set_text(lbl, "Уставка: 21.0°C"); + lv_obj_set_pos(lbl, 10, 135); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Air flow line (визуальная линия потока воздуха) */ + lv_obj_t *line_obj = lv_obj_create(panel_schema); + lv_obj_set_pos(line_obj, 15, 85); + lv_obj_set_size(line_obj, 670, 4); + lv_obj_set_style_bg_color(line_obj, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_radius(line_obj, 2, 0); + lv_obj_set_style_border_width(line_obj, 0, 0); + + /* Arrow to room */ + lv_obj_t *arrow = lv_obj_create(panel_schema); + lv_obj_set_pos(arrow, 145, 130); + lv_obj_set_size(arrow, 4, 70); + lv_obj_set_style_bg_color(arrow, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_radius(arrow, 2, 0); + lv_obj_set_style_border_width(arrow, 0, 0); +} + +static void create_screen_screen1(void) { + lv_obj_t *scr = lv_obj_create(NULL); + scr_screen1 = scr; + lv_obj_set_style_bg_color(scr, lv_color_hex(0x2C3E50), 0); + lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); + lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); + + /* Title */ + lv_obj_t *lbl = lv_label_create(scr); + lv_label_set_text(lbl, "МЕНЮ"); + lv_obj_set_pos(lbl, 350, 30); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + int btn_width = 300; + int btn_height = 50; + int x = 250; + int y = 100; + int spacing = 20; + + /* Button: Back to Main Screen */ + lv_obj_t *btn = lv_btn_create(scr); + lv_obj_set_pos(btn, x, y); + lv_obj_set_size(btn, btn_width, btn_height); + lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Главный экран"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_back_to_main_cb, LV_EVENT_CLICKED, NULL); + + y += btn_height + spacing; + + /* Button: Log (Журнал) */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, x, y); + lv_obj_set_size(btn, btn_width, btn_height); + lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Журнал аварий"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_log_cb, LV_EVENT_CLICKED, NULL); + + y += btn_height + spacing; + + /* Button: Settings Parameters (Уставка параметров) */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, x, y); + lv_obj_set_size(btn, btn_width, btn_height); + lv_obj_set_style_bg_color(btn, lv_color_hex(0x27AE60), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Уставка параметров"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_settings_cb, LV_EVENT_CLICKED, NULL); + + y += btn_height + spacing; + + /* Button: Configuration (Настройки - требует пароль) */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, x, y); + lv_obj_set_size(btn, btn_width, btn_height); + lv_obj_set_style_bg_color(btn, lv_color_hex(0xC0392B), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Настройки 🔒"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_config_cb, LV_EVENT_CLICKED, NULL); + + /* Footer info */ + lbl = lv_label_create(scr); + lv_label_set_text(lbl, "(для настроек пароль: 1234)"); + lv_obj_set_pos(lbl, 270, 420); + lv_obj_set_style_text_color(lbl, lv_color_hex(0x7F8C8D), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); +} + +static void create_screen_screen2(void) { + lv_obj_t *scr = lv_obj_create(NULL); + scr_screen2 = scr; + lv_obj_set_style_bg_color(scr, lv_color_hex(0x2C3E50), 0); + lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); + lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); + + /* Title */ + lv_obj_t *lbl = lv_label_create(scr); + lv_label_set_text(lbl, "ЖУРНАЛ АВАРИЙ"); + lv_obj_set_pos(lbl, 300, 20); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Date/Time display */ + lbl = lv_label_create(scr); + lv_label_set_text(lbl, "25.02.2026 09:35"); + lv_obj_set_pos(lbl, 650, 20); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Log panel */ + lv_obj_t *log_panel = lv_obj_create(scr); + lv_obj_set_pos(log_panel, 20, 60); + lv_obj_set_size(log_panel, 760, 300); + lv_obj_set_style_bg_color(log_panel, lv_color_hex(0x34495E), 0); + lv_obj_set_style_radius(log_panel, 8, 0); + lv_obj_set_style_border_width(log_panel, 2, 0); + lv_obj_set_style_border_color(log_panel, lv_color_hex(0x7F8C8D), 0); + + /* Display log entries */ + int y = 10; + if (alarm_count == 0) { + lbl = lv_label_create(log_panel); + lv_label_set_text(lbl, "Аварий нет"); + lv_obj_set_pos(lbl, 320, 130); + lv_obj_set_style_text_color(lbl, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + } else { + for (int i = 0; i < alarm_count && i < 8; i++) { + char buf[150]; + snprintf(buf, sizeof(buf), "%s - %s", + alarm_log[i].message, alarm_log[i].timestamp); + + lbl = lv_label_create(log_panel); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 10, y); + lv_obj_set_width(lbl, 730); + if (alarm_log[i].active) { + lv_obj_set_style_text_color(lbl, lv_color_hex(0xE74C3C), 0); + } else { + lv_obj_set_style_text_color(lbl, lv_color_hex(0xBDC3C7), 0); + } + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + y += 35; + } + } + + /* Buttons */ + int btn_y = 380; + + /* Clear Log button */ + lv_obj_t *btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 50, btn_y); + lv_obj_set_size(btn, 150, 40); + lv_obj_set_style_bg_color(btn, lv_color_hex(0xC0392B), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Очистить журнал"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + + /* Reset Alarm button */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 220, btn_y); + lv_obj_set_size(btn, 150, 40); + lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Сбросить аварию"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + + /* Back to Menu button */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 600, btn_y); + lv_obj_set_size(btn, 150, 40); + lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Меню"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_menu_cb, LV_EVENT_CLICKED, NULL); +} + +static void create_screen_screen3(void) { + lv_obj_t *scr = lv_obj_create(NULL); + scr_screen3 = scr; + lv_obj_set_style_bg_color(scr, lv_color_hex(0x2C3E50), 0); + lv_obj_set_style_bg_opa(scr, LV_OPA_COVER, 0); + lv_obj_clear_flag(scr, LV_OBJ_FLAG_SCROLLABLE); + + /* Title */ + lv_obj_t *lbl = lv_label_create(scr); + lv_label_set_text(lbl, "УСТАВКА ПАРАМЕТРОВ"); + lv_obj_set_pos(lbl, 270, 20); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xECF0F1), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Left panel - Work mode */ + lv_obj_t *panel_work = lv_obj_create(scr); + lv_obj_set_pos(panel_work, 20, 60); + lv_obj_set_size(panel_work, 360, 300); + lv_obj_set_style_bg_color(panel_work, lv_color_hex(0x27AE60), 0); + lv_obj_set_style_radius(panel_work, 8, 0); + lv_obj_set_style_border_width(panel_work, 2, 0); + + lbl = lv_label_create(panel_work); + lv_label_set_text(lbl, "РАБОЧИЙ РЕЖИМ"); + lv_obj_set_pos(lbl, 10, 10); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + int y = 50; + char buf[64]; + + /* Temperature - clickable */ + lv_obj_t *btn_temp = lv_btn_create(panel_work); + lv_obj_set_pos(btn_temp, 10, y); + lv_obj_set_size(btn_temp, 320, 30); + lv_obj_set_style_bg_color(btn_temp, lv_color_hex(0x2C3E50), 0); + lv_obj_set_style_radius(btn_temp, 5, 0); + snprintf(buf, sizeof(buf), "Температура: %.1f°C", setpoint_work_temp); + lbl = lv_label_create(btn_temp); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 10, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_add_event_cb(btn_temp, edit_work_temp_cb, LV_EVENT_CLICKED, NULL); + + y += 40; + /* Humidity - clickable */ + lv_obj_t *btn_hum = lv_btn_create(panel_work); + lv_obj_set_pos(btn_hum, 10, y); + lv_obj_set_size(btn_hum, 320, 30); + lv_obj_set_style_bg_color(btn_hum, lv_color_hex(0x2C3E50), 0); + lv_obj_set_style_radius(btn_hum, 5, 0); + snprintf(buf, sizeof(buf), "Влажность: %.1f%%", setpoint_work_hum); + lbl = lv_label_create(btn_hum); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 10, 5); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_add_event_cb(btn_hum, edit_work_hum_cb, LV_EVENT_CLICKED, NULL); + + y += 40; + lbl = lv_label_create(panel_work); + lv_label_set_text(lbl, "Клапан притока: 75%"); + lv_obj_set_pos(lbl, 20, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 40; + lbl = lv_label_create(panel_work); + lv_label_set_text(lbl, "Вентилятор: ВКЛ"); + lv_obj_set_pos(lbl, 20, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 40; + lbl = lv_label_create(panel_work); + lv_label_set_text(lbl, "KWS: АВТО"); + lv_obj_set_pos(lbl, 20, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Right panel - Standby mode */ + lv_obj_t *panel_standby = lv_obj_create(scr); + lv_obj_set_pos(panel_standby, 400, 60); + lv_obj_set_size(panel_standby, 360, 300); + lv_obj_set_style_bg_color(panel_standby, lv_color_hex(0xF39C12), 0); + lv_obj_set_style_radius(panel_standby, 8, 0); + lv_obj_set_style_border_width(panel_standby, 2, 0); + + lbl = lv_label_create(panel_standby); + lv_label_set_text(lbl, "ДЕЖУРНЫЙ РЕЖИМ"); + lv_obj_set_pos(lbl, 10, 10); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y = 50; + snprintf(buf, sizeof(buf), "Температура: %.1f°C", setpoint_standby_temp); + lbl = lv_label_create(panel_standby); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 20, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 40; + snprintf(buf, sizeof(buf), "Влажность: %.1f%%", setpoint_standby_hum); + lbl = lv_label_create(panel_standby); + lv_label_set_text(lbl, buf); + lv_obj_set_pos(lbl, 20, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 40; + lbl = lv_label_create(panel_standby); + lv_label_set_text(lbl, "Клапан притока: 35%"); + lv_obj_set_pos(lbl, 20, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 40; + lbl = lv_label_create(panel_standby); + lv_label_set_text(lbl, "Вентилятор: ВКЛ"); + lv_obj_set_pos(lbl, 20, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + y += 40; + lbl = lv_label_create(panel_standby); + lv_label_set_text(lbl, "KWS: АВТО"); + lv_obj_set_pos(lbl, 20, y); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Info */ + lbl = lv_label_create(scr); + lv_label_set_text(lbl, "(нажмите на параметр для редактирования - этап 5)"); + lv_obj_set_pos(lbl, 200, 370); + lv_obj_set_style_text_color(lbl, lv_color_hex(0x7F8C8D), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + + /* Buttons */ + int btn_y = 410; + + /* Save button */ + lv_obj_t *btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 200, btn_y); + lv_obj_set_size(btn, 120, 40); + lv_obj_set_style_bg_color(btn, lv_color_hex(0x2ECC71), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Сохранить"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + + /* Default button */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 340, btn_y); + lv_obj_set_size(btn, 140, 40); + lv_obj_set_style_bg_color(btn, lv_color_hex(0xE67E22), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "По умолчанию"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + + /* Back to Menu button */ + btn = lv_btn_create(scr); + lv_obj_set_pos(btn, 500, btn_y); + lv_obj_set_size(btn, 100, 40); + lv_obj_set_style_bg_color(btn, lv_color_hex(0x3498DB), 0); + lv_obj_set_style_radius(btn, 8, 0); + lbl = lv_label_create(btn); + lv_label_set_text(lbl, "Меню"); + lv_obj_set_style_text_color(lbl, lv_color_hex(0xFFFFFF), 0); + lv_obj_set_style_text_font(lbl, &montserrat_16_ru_en, 0); + lv_obj_center(lbl); + lv_obj_add_event_cb(btn, btn_menu_cb, LV_EVENT_CLICKED, NULL); +} + +void gui_update_values(void) { + char buf[64]; + + /* Update room climate */ + if (lbl_temp_room) { + snprintf(buf, sizeof(buf), "%.1f°C", var_temp_room / 1.0); + lv_label_set_text(lbl_temp_room, buf); + } + + if (lbl_hum_room) { + snprintf(buf, sizeof(buf), "%d%%", (int)var_hum_room); + lv_label_set_text(lbl_hum_room, buf); + } + + /* Update channel climate */ + if (lbl_temp_channel) { + snprintf(buf, sizeof(buf), "%.1f°C", var_temp_channel / 1.0); + lv_label_set_text(lbl_temp_channel, buf); + } + + if (lbl_hum_channel) { + snprintf(buf, sizeof(buf), "%d%%", (int)var_hum_channel); + lv_label_set_text(lbl_hum_channel, buf); + } + + /* Update system status */ + if (lbl_room_num) { + snprintf(buf, sizeof(buf), "Комната: %d", (int)var_room_num); + lv_label_set_text(lbl_room_num, buf); + } + + if (lbl_master_slave) { + lv_label_set_text(lbl_master_slave, var_is_master ? "Мастер" : "Слейв"); + lv_obj_set_style_text_color(lbl_master_slave, + var_is_master ? lv_color_hex(0x2ECC71) : lv_color_hex(0xE67E22), 0); + } + + if (lbl_season) { + const char *seasons[] = {"Зима", "Лето", "Переход"}; + const uint32_t colors[] = {0x3498DB, 0xE74C3C, 0xF39C12}; + snprintf(buf, sizeof(buf), "Сезон: %s", seasons[var_season % 3]); + lv_label_set_text(lbl_season, buf); + lv_obj_set_style_text_color(lbl_season, lv_color_hex(colors[var_season % 3]), 0); + } + + if (lbl_mode) { + const char *modes[] = {"Остановка", "Дежурный", "Рабочий"}; + const uint32_t colors[] = {0xC0392B, 0xF39C12, 0x27AE60}; + snprintf(buf, sizeof(buf), "Режим: %s", modes[var_mode % 3]); + lv_label_set_text(lbl_mode, buf); + lv_obj_set_style_text_color(lbl_mode, lv_color_hex(colors[var_mode % 3]), 0); + } + + /* Update equipment modules */ + if (lbl_valve_inlet) { + snprintf(buf, sizeof(buf), "%d%%", (int)var_valve_inlet); + lv_label_set_text(lbl_valve_inlet, buf); + } + + if (lbl_valve_recirc) { + snprintf(buf, sizeof(buf), "%d%%", (int)var_valve_recirc); + lv_label_set_text(lbl_valve_recirc, buf); + } + + if (lbl_filter_g4) { + lv_label_set_text(lbl_filter_g4, var_filter_g4 ? "Чистый" : "Грязный"); + lv_obj_set_style_text_color(lbl_filter_g4, + var_filter_g4 ? lv_color_hex(0x2ECC71) : lv_color_hex(0xE74C3C), 0); + } + + if (lbl_kws) { + snprintf(buf, sizeof(buf), "%d%%", (int)var_kws_valve); + lv_label_set_text(lbl_kws, buf); + } + + if (lbl_pww) { + snprintf(buf, sizeof(buf), "%d%%", (int)var_pww_valve); + lv_label_set_text(lbl_pww, buf); + } + + if (lbl_heater) { + lv_label_set_text(lbl_heater, var_heater_on ? "ВКЛ" : "ВЫКЛ"); + lv_obj_set_style_text_color(lbl_heater, + var_heater_on ? lv_color_hex(0xE74C3C) : lv_color_hex(0x7F8C8D), 0); + } + + if (lbl_fan) { + lv_label_set_text(lbl_fan, var_fan_on ? "ВКЛ" : "ВЫКЛ"); + lv_obj_set_style_text_color(lbl_fan, + var_fan_on ? lv_color_hex(0x2ECC71) : lv_color_hex(0xC0392B), 0); + } + + if (lbl_filter_h13) { + lv_label_set_text(lbl_filter_h13, var_filter_h13 ? "Чистый" : "Грязный"); + lv_obj_set_style_text_color(lbl_filter_h13, + var_filter_h13 ? lv_color_hex(0x2ECC71) : lv_color_hex(0xE74C3C), 0); + } + + /* Check for alarm conditions */ + static int alarm_check_counter = 0; + alarm_check_counter++; + + // Example: Show alarm if temperature is too low (freeze risk) + if (alarm_check_counter > 50 && var_temp_channel < 5 && var_mode != 0) { + create_popup_alarm("Угроза заморозки!\nУстановка остановлена.\n\nПроверьте журнал и примите меры."); + var_mode = 0; // Stop system + alarm_check_counter = 0; + } + + // Example: Show alarm if filter is dirty + if (alarm_check_counter > 100 && var_filter_g4 == 0) { + create_popup_alarm("Фильтр G4 засорился!\n\nЗамените фильтр для нормальной работы."); + alarm_check_counter = 0; + } +} + +void gui_init(void) { + /* Add some example alarms to the log */ + add_alarm_to_log("Система запущена", 0); + add_alarm_to_log("Фильтр G4 заменен", 0); + + create_screen_main(); + create_screen_screen1(); + create_screen_screen2(); + create_screen_screen3(); + lv_scr_load(scr_main); +} + +/* ── ModBus ──────────────────────────────────────── */ +/* ModBus disabled for simulation - use dummy values */ + +void gui_modbus_init(void) { + /* No-op for simulation */ +} + +void gui_modbus_task(void *arg) { + (void)arg; + /* Simulation: update with dummy values */ + while (1) { + var_temp_room = 22 + (rand() % 4); + var_hum_room = 45 + (rand() % 10); + var_temp_channel = 20 + (rand() % 3); + var_hum_channel = 50 + (rand() % 8); + + /* Simulate valve changes based on mode */ + if (var_mode == 2) { // Рабочий режим + var_valve_inlet = 70 + (rand() % 30); + var_valve_recirc = 10 + (rand() % 20); + var_kws_valve = 40 + (rand() % 30); + var_pww_valve = 30 + (rand() % 25); + var_fan_on = 1; + } else if (var_mode == 1) { // Дежурный + var_valve_inlet = 30 + (rand() % 20); + var_valve_recirc = 40 + (rand() % 20); + var_kws_valve = 20 + (rand() % 15); + var_pww_valve = 15 + (rand() % 15); + var_fan_on = 1; + } else { // Остановка + var_valve_inlet = 0; + var_valve_recirc = 0; + var_kws_valve = 0; + var_pww_valve = 0; + var_fan_on = 0; + var_heater_on = 0; + } + + gui_update_values(); + /* Sleep simulation - requires FreeRTOS or use SDL delay */ + } +} diff --git a/src/gui_generated.h b/src/gui_generated.h new file mode 100644 index 0000000..e87fb71 --- /dev/null +++ b/src/gui_generated.h @@ -0,0 +1,16 @@ +#ifndef GUI_GENERATED_H +#define GUI_GENERATED_H + +#include "lvgl.h" + +void gui_init(void); +void gui_update_values(void); +void gui_modbus_init(void); +void gui_modbus_task(void *arg); + +extern lv_obj_t *scr_main; +extern lv_obj_t *scr_screen1; +extern lv_obj_t *scr_screen2; +extern lv_obj_t *scr_screen3; + +#endif /* GUI_GENERATED_H */ diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..b90fe4d --- /dev/null +++ b/src/main.c @@ -0,0 +1,146 @@ + +/** + * @file main + * + */ + +/********************* + * INCLUDES + *********************/ +#ifndef _DEFAULT_SOURCE + #define _DEFAULT_SOURCE /* needed for usleep() */ +#endif + +#include +#include +#ifdef _MSC_VER + #include +#else + #include + #include +#endif +#include "lvgl/lvgl.h" +#include "lvgl/examples/lv_examples.h" +#include "lvgl/demos/lv_demos.h" +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +static lv_display_t * hal_init(int32_t w, int32_t h); + +/********************** + * STATIC VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +extern void freertos_main(void); +extern void placeWidgets(); + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * VARIABLES + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +int main(int argc, char **argv) +{ + (void)argc; /*Unused*/ + (void)argv; /*Unused*/ + + /*Initialize LVGL*/ + lv_init(); + + /*Initialize the HAL (display, input devices, tick) for LVGL*/ + hal_init(800, 480); + + #if LV_USE_OS == LV_OS_NONE + + placeWidgets(); + + while(1) { + /* Periodically call the lv_task handler. + * It could be done in a timer interrupt or an OS task too.*/ + lv_timer_handler(); +#ifdef _MSC_VER + Sleep(5); +#else + usleep(5 * 1000); +#endif + } + + #elif LV_USE_OS == LV_OS_FREERTOS + + /* Run FreeRTOS and create lvgl task */ + freertos_main(); + + #endif + + return 0; +} + +/********************** + * STATIC FUNCTIONS + **********************/ + +/** + * Initialize the Hardware Abstraction Layer (HAL) for the LVGL graphics + * library + */ +static lv_display_t * hal_init(int32_t w, int32_t h) +{ + + lv_group_set_default(lv_group_create()); + + lv_display_t * disp = lv_sdl_window_create(w, h); + + lv_indev_t * mouse = lv_sdl_mouse_create(); + lv_indev_set_group(mouse, lv_group_get_default()); + lv_indev_set_display(mouse, disp); + lv_display_set_default(disp); + + LV_IMAGE_DECLARE(mouse_cursor_icon); /*Declare the image file.*/ + lv_obj_t * cursor_obj; + cursor_obj = lv_image_create(lv_screen_active()); /*Create an image object for the cursor */ + lv_image_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/ + lv_indev_set_cursor(mouse, cursor_obj); /*Connect the image object to the driver*/ + + lv_indev_t * mousewheel = lv_sdl_mousewheel_create(); + lv_indev_set_display(mousewheel, disp); + lv_indev_set_group(mousewheel, lv_group_get_default()); + + lv_indev_t * kb = lv_sdl_keyboard_create(); + lv_indev_set_display(kb, disp); + lv_indev_set_group(kb, lv_group_get_default()); + + return disp; +} diff --git a/src/main_sim.c b/src/main_sim.c new file mode 100644 index 0000000..d3ab3fd --- /dev/null +++ b/src/main_sim.c @@ -0,0 +1,93 @@ +/** + * @file main_sim + * Simulator entry point for GUI Editor design + */ + +#ifndef _DEFAULT_SOURCE + #define _DEFAULT_SOURCE /* needed for usleep() */ +#endif + +#include +#include +#ifdef _MSC_VER + #include +#else + #include + #include +#endif +#include "lvgl/lvgl.h" +#include +#include "gui_generated.h" + +static lv_display_t * hal_init(int32_t w, int32_t h); + +extern void freertos_main(void); + +int main(int argc, char **argv) +{ + (void)argc; /*Unused*/ + (void)argv; /*Unused*/ + + /*Initialize LVGL*/ + lv_init(); + + /*Initialize the HAL (display, input devices, tick) for LVGL*/ + hal_init(800, 480); + + #if LV_USE_OS == LV_OS_NONE + + gui_init(); + + while(1) { + /* Periodically call the lv_task handler. + * It could be done in a timer interrupt or an OS task too.*/ + lv_timer_handler(); +#ifdef _MSC_VER + Sleep(5); +#else + usleep(5 * 1000); +#endif + } + + #elif LV_USE_OS == LV_OS_FREERTOS + + /* Run FreeRTOS and create lvgl task */ + freertos_main(); + + #endif + + return 0; +} + +/** + * Initialize the Hardware Abstraction Layer (HAL) for the LVGL graphics + * library + */ +static lv_display_t * hal_init(int32_t w, int32_t h) +{ + + lv_group_set_default(lv_group_create()); + + lv_display_t * disp = lv_sdl_window_create(w, h); + + lv_indev_t * mouse = lv_sdl_mouse_create(); + lv_indev_set_group(mouse, lv_group_get_default()); + lv_indev_set_display(mouse, disp); + lv_display_set_default(disp); + + LV_IMAGE_DECLARE(mouse_cursor_icon); /*Declare the image file.*/ + lv_obj_t * cursor_obj; + cursor_obj = lv_image_create(lv_screen_active()); /*Create an image object for the cursor */ + lv_image_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/ + lv_indev_set_cursor(mouse, cursor_obj); /*Connect the image object to the driver*/ + + lv_indev_t * mousewheel = lv_sdl_mousewheel_create(); + lv_indev_set_display(mousewheel, disp); + lv_indev_set_group(mousewheel, lv_group_get_default()); + + lv_indev_t * kb = lv_sdl_keyboard_create(); + lv_indev_set_display(kb, disp); + lv_indev_set_group(kb, lv_group_get_default()); + + return disp; +} diff --git a/src/mouse_cursor_icon.c b/src/mouse_cursor_icon.c new file mode 100644 index 0000000..dfc5611 --- /dev/null +++ b/src/mouse_cursor_icon.c @@ -0,0 +1,34 @@ +#include "lvgl/lvgl.h" + +const uint8_t mouse_cursor_icon_map[] = { + 0x19, 0x19, 0x19, 0xb8, 0x1e, 0x1e, 0x1e, 0xc8, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x48, 0x48, 0x48, 0xcc, 0xb2, 0xb2, 0xb2, 0xff, 0x3a, 0x3a, 0x3a, 0xcc, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3b, 0x3b, 0x3b, 0xc8, 0xf6, 0xf6, 0xf6, 0xff, 0xdc, 0xdc, 0xdc, 0xff, 0x43, 0x43, 0x43, 0xe0, 0x00, 0x00, 0x00, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3b, 0x3b, 0x3b, 0xcb, 0xe6, 0xe6, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe5, 0xe5, 0xe5, 0xff, 0x59, 0x59, 0x59, 0xf3, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3c, 0x3c, 0x3c, 0xcb, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf5, 0xf5, 0xf5, 0xff, 0x72, 0x72, 0x72, 0xff, 0x00, 0x00, 0x00, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3d, 0x3d, 0x3d, 0xcb, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8a, 0x8a, 0x8a, 0xff, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x99, 0x99, 0x99, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x3e, 0x3e, 0xcb, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa2, 0xa2, 0xa2, 0xff, 0x13, 0x13, 0x13, 0xab, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x3f, 0x3f, 0x3f, 0xcb, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xb7, 0xb7, 0xff, 0x1f, 0x1f, 0x1f, 0xbb, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x41, 0x41, 0xcc, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xca, 0xca, 0xca, 0xff, 0x3d, 0x3d, 0x3d, 0xd8, 0x00, 0x00, 0x00, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x41, 0x41, 0x41, 0xcc, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xde, 0xde, 0xde, 0xff, 0x56, 0x56, 0x56, 0xef, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, + 0x42, 0x42, 0x42, 0xcc, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0xf3, 0xf3, 0xff, 0x76, 0x76, 0x76, 0xff, 0x00, 0x00, 0x00, 0x6b, + 0x43, 0x43, 0x43, 0xcc, 0xea, 0xea, 0xea, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xce, 0xce, 0xce, 0xff, 0x80, 0x80, 0x80, 0xf7, 0x74, 0x74, 0x74, 0xf8, 0x6d, 0x6d, 0x6d, 0xfb, 0x72, 0x72, 0x72, 0xf8, 0x57, 0x57, 0x57, 0xff, 0x0c, 0x0c, 0x0c, 0xb3, + 0x44, 0x44, 0x44, 0xcc, 0xeb, 0xeb, 0xeb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xfb, 0xfb, 0xfb, 0xff, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0xc9, 0xc9, 0xff, 0x13, 0x13, 0x13, 0xb7, 0x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x0c, 0x29, 0x29, 0x29, 0x07, + 0x45, 0x45, 0x45, 0xcc, 0xe8, 0xe8, 0xe8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd9, 0xd9, 0xd9, 0xff, 0x5e, 0x5e, 0x5e, 0xff, 0xe2, 0xe2, 0xe2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x62, 0x62, 0x62, 0xf0, 0x00, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x45, 0x45, 0x45, 0xcc, 0xf9, 0xf9, 0xf9, 0xff, 0xec, 0xec, 0xec, 0xff, 0x4a, 0x4a, 0x4a, 0xd8, 0x00, 0x00, 0x00, 0x78, 0x8a, 0x8a, 0x8a, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0xc3, 0xc3, 0xff, 0x00, 0x00, 0x00, 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x58, 0x58, 0x58, 0xd3, 0xd9, 0xd9, 0xd9, 0xff, 0x5e, 0x5e, 0x5e, 0xef, 0x00, 0x00, 0x00, 0x34, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x3b, 0x3b, 0xc7, 0xe9, 0xe9, 0xe9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf4, 0xf4, 0xf4, 0xff, 0x54, 0x54, 0x54, 0xdc, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, + 0x3e, 0x3e, 0x3e, 0xe0, 0x54, 0x54, 0x54, 0xff, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, 0x8e, 0x8e, 0x8e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb0, 0xb0, 0xb0, 0xff, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x0c, 0x0c, 0x04, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x68, 0x00, 0x00, 0x00, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x4c, 0x4c, 0x4c, 0xd0, 0xec, 0xec, 0xec, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xf4, 0xf4, 0xf4, 0xff, 0x53, 0x53, 0x53, 0xd8, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x1e, 0x1e, 0x00, 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, 0xab, 0xab, 0xab, 0xff, 0xf6, 0xf6, 0xf6, 0xff, 0x80, 0x80, 0x80, 0xff, 0x31, 0x31, 0x31, 0xac, 0x00, 0x00, 0x00, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x09, 0x09, 0x09, 0x03, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x2e, 0x2e, 0x2e, 0xd7, 0x38, 0x38, 0x38, 0xc7, 0x00, 0x00, 0x00, 0x47, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +}; + +lv_img_dsc_t mouse_cursor_icon = { + .header.magic = LV_IMAGE_HEADER_MAGIC, + .header.w = 14, + .header.h = 20, + .data_size = 280 * 4, + .header.cf = LV_COLOR_FORMAT_ARGB8888, + .data = mouse_cursor_icon_map, +};