Lay the ground work for a hardware abstraction layer (#15)
* Pull out OmoteUI into its own hpp/cpp that only controls UI/UX Added HardwareAbstractionInterface to allow UI to be decoupled Add OmoteUI class/Header to visual studio solution Bump the compiler to c++17 for std::clamp * code format update visual studio solution to build all versions properly Pull pin defs into config file use config file to allow USE_SIMULATOR checks in OmoteUI this will allow the sim to compile in specific code within the UI * put pin mode config into hardwarerevX class along with some other hardware things. Still lots of work to pull everything into the HAL. Change-Id: If3cacc43d43670b0ff2233140b1cff66a4aeb48d * pull Prefrences, IMU interrupt and sleep into the hardware class Change-Id: I082ae086ed70306789df80eafce8870a5cdfd125 * pull in touch screen, IMU and slow screen wake into hardware Change-Id: I61b49a6d0551463becbc3bdf1418ac9fde9d9376 * Pull wifi and IR into Hardware RevX pull last bit of global variables into hardware rev * un public everything * clean up simulator build * rename loop handler reorder setup to better match the origional main * Add Loop Handler that updates UI * Add images to their own file to shrink OmoteUI * Allow Wifi to be turned off with the macro * Update Battery Update Task instead of a time based check and update * Clean up abstract interface move defenitions out of hardwareRevX.hpp into cpp * reorder HardwareRevX functions * Add comment blocks to top of headers --------- Co-authored-by: Matthew Colvin <35540398+Mc067415@users.noreply.github.com> Co-authored-by: Matthew Colvin <Matthew.Colvin@garmin.com>
This commit is contained in:
		
							parent
							
								
									be3a203fe5
								
							
						
					
					
						commit
						f1ff9ed3d2
					
				
					 18 changed files with 3376 additions and 1986 deletions
				
			
		
							
								
								
									
										1
									
								
								LVGL Simulator/LVGL.Simulator/HardwareSimulator.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								LVGL Simulator/LVGL.Simulator/HardwareSimulator.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | #include "HardwareSimulator.hpp" | ||||||
							
								
								
									
										30
									
								
								LVGL Simulator/LVGL.Simulator/HardwareSimulator.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								LVGL Simulator/LVGL.Simulator/HardwareSimulator.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,30 @@ | ||||||
|  | #pragma once | ||||||
|  | #include "HardwareAbstractionInterface.h" | ||||||
|  | #include <string> | ||||||
|  | #include <iostream> | ||||||
|  | 
 | ||||||
|  | class HardwareSimulator : | ||||||
|  |     public HardwareAbstractionInterface | ||||||
|  | { | ||||||
|  |     public: | ||||||
|  | 
 | ||||||
|  |     HardwareSimulator() = default; | ||||||
|  | 
 | ||||||
|  |     virtual void debugPrint(std::string message) override { | ||||||
|  |         std::cout << message; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     virtual void sendIR() override { | ||||||
|  |          | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     virtual void MQTTPublish(const char* topic, const char* payload) override { | ||||||
|  | 
 | ||||||
|  |     }; | ||||||
|  | 
 | ||||||
|  |     virtual void init() override { | ||||||
|  |         lv_init(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | @ -12,13 +12,17 @@ | ||||||
| #include <string> | #include <string> | ||||||
| #include "resource.h" | #include "resource.h" | ||||||
| 
 | 
 | ||||||
|  | #include "omoteconfig.h" | ||||||
|  | #include "HardwareSimulator.hpp" | ||||||
|  | #include "OmoteUI.hpp" | ||||||
|  | 
 | ||||||
| #if _MSC_VER >= 1200 | #if _MSC_VER >= 1200 | ||||||
|  // Disable compilation warnings.
 | // Disable compilation warnings.
 | ||||||
| #pragma warning(push) | #pragma warning(push) | ||||||
| // nonstandard extension used : bit field types other than int
 | // nonstandard extension used : bit field types other than int
 | ||||||
| #pragma warning(disable:4214) | #pragma warning(disable : 4214) | ||||||
| // 'conversion' conversion from 'type1' to 'type2', possible loss of data
 | // 'conversion' conversion from 'type1' to 'type2', possible loss of data
 | ||||||
| #pragma warning(disable:4244) | #pragma warning(disable : 4244) | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #include "lvgl/lvgl.h" | #include "lvgl/lvgl.h" | ||||||
|  | @ -42,7 +46,6 @@ bool single_display_mode_initialization() | ||||||
|     { |     { | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     lv_win32_add_all_input_devices_to_group(NULL); |     lv_win32_add_all_input_devices_to_group(NULL); | ||||||
| 
 | 
 | ||||||
|     return true; |     return true; | ||||||
|  | @ -56,14 +59,10 @@ bool g_initialization_status = false; | ||||||
| #define LVGL_SIMULATOR_MAXIMUM_DISPLAYS 16 | #define LVGL_SIMULATOR_MAXIMUM_DISPLAYS 16 | ||||||
| HWND g_display_window_handles[LVGL_SIMULATOR_MAXIMUM_DISPLAYS]; | HWND g_display_window_handles[LVGL_SIMULATOR_MAXIMUM_DISPLAYS]; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| #define screenWidth 240 |  | ||||||
| #define screenHeight 320 |  | ||||||
| 
 |  | ||||||
| unsigned int __stdcall lv_win32_window_thread_entrypoint( | unsigned int __stdcall lv_win32_window_thread_entrypoint( | ||||||
|     void* raw_parameter) |     void *raw_parameter) | ||||||
| { | { | ||||||
|     size_t display_id = *(size_t*)(raw_parameter); |     size_t display_id = *(size_t *)(raw_parameter); | ||||||
| 
 | 
 | ||||||
|     HINSTANCE instance_handle = GetModuleHandleW(NULL); |     HINSTANCE instance_handle = GetModuleHandleW(NULL); | ||||||
|     int show_window_mode = SW_SHOW; |     int show_window_mode = SW_SHOW; | ||||||
|  | @ -138,8 +137,7 @@ bool multiple_display_mode_initialization() | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     lv_win32_window_context_t* context = (lv_win32_window_context_t*)( |     lv_win32_window_context_t *context = (lv_win32_window_context_t *)(lv_win32_get_window_context(g_display_window_handles[0])); | ||||||
|         lv_win32_get_window_context(g_display_window_handles[0])); |  | ||||||
|     if (context) |     if (context) | ||||||
|     { |     { | ||||||
|         lv_win32_pointer_device_object = context->mouse_device_object; |         lv_win32_pointer_device_object = context->mouse_device_object; | ||||||
|  | @ -152,730 +150,31 @@ bool multiple_display_mode_initialization() | ||||||
|     return true; |     return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| lv_obj_t* panel; |  | ||||||
| byte currentDevice = 4; // Current Device to control (allows switching mappings between devices)
 |  | ||||||
| byte virtualKeyMapTechnisat[10] = { 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0 }; |  | ||||||
| bool wakeupByIMUEnabled = true; |  | ||||||
| int backlight_brightness = 255; |  | ||||||
| 
 |  | ||||||
| lv_color_t color_primary = lv_color_hex(0x303030); // gray
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| // Set the page indicator scroll position relative to the tabview scroll position
 |  | ||||||
| static void store_scroll_value_event_cb(lv_event_t* e) { |  | ||||||
|     float bias = (150.0 + 8.0) / 240.0; |  | ||||||
|     int offset = 240 / 2 - 150 / 2 - 8 - 50 - 3; |  | ||||||
|     lv_obj_t* screen = lv_event_get_target(e); |  | ||||||
|     lv_obj_scroll_to_x(panel, lv_obj_get_scroll_x(screen) * bias - offset, LV_ANIM_OFF); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Update current device when the tabview page is changes
 |  | ||||||
| static void tabview_device_event_cb(lv_event_t* e) { |  | ||||||
|     currentDevice = lv_tabview_get_tab_act(lv_event_get_target(e)); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Backlight Slider Event handler
 |  | ||||||
| static void bl_slider_event_cb(lv_event_t* e) { |  | ||||||
|     lv_obj_t* slider = lv_event_get_target(e); |  | ||||||
|     backlight_brightness = 255;//constrain(lv_slider_get_value(slider), 60, 255);
 |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Apple Key Event handler
 |  | ||||||
| static void appleKey_event_cb(lv_event_t* e) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Wakeup by IMU Switch Event handler
 |  | ||||||
| static void WakeEnableSetting_event_cb(lv_event_t* e) { |  | ||||||
|     wakeupByIMUEnabled = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Smart Home Toggle Event handler
 |  | ||||||
| static void smartHomeToggle_event_cb(lv_event_t* e) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Smart Home Toggle Event handler
 |  | ||||||
| static void smartHomeSlider_event_cb(lv_event_t* e) { |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| // Virtual Keypad Event handler
 |  | ||||||
| static void virtualKeypad_event_cb(lv_event_t* e) { |  | ||||||
|     lv_obj_t* target = lv_event_get_target(e); |  | ||||||
|     lv_obj_t* cont = lv_event_get_current_target(e); |  | ||||||
|     if (target == cont) return; |  | ||||||
| 
 |  | ||||||
|     char buffer[100]; |  | ||||||
|     sprintf_s(buffer, "check it out: %d\n", virtualKeyMapTechnisat[(int)target->user_data]); |  | ||||||
|     OutputDebugStringA(buffer); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| #ifndef LV_ATTRIBUTE_MEM_ALIGN | #ifndef LV_ATTRIBUTE_MEM_ALIGN | ||||||
| #define LV_ATTRIBUTE_MEM_ALIGN | #define LV_ATTRIBUTE_MEM_ALIGN | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t gradientLeft_map[] = { |  | ||||||
|   0xfa, 0xf2, 0xea, 0xe2, 0xda, 0xd1, 0xc7, 0xbe, 0xb7, 0xae, 0xa6, 0x9e, 0x95, 0x8d, 0x84, 0x7d, 0x74, 0x6c, 0x62, 0x5a, 0x51, 0x48, 0x41, 0x38, 0x2f, 0x28, 0x1f, 0x17, 0x0f, 0x07, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t gradientRight_map[] = { |  | ||||||
|   0x07, 0x0f, 0x17, 0x1f, 0x28, 0x2f, 0x38, 0x41, 0x48, 0x51, 0x5a, 0x62, 0x6c, 0x74, 0x7d, 0x84, 0x8d, 0x95, 0x9e, 0xa6, 0xae, 0xb7, 0xbe, 0xc7, 0xd1, 0xda, 0xe2, 0xea, 0xf2, 0xfa, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t appleTvIcon_map[] = { |  | ||||||
|     /*Pixel format: Red: 5 bit, Green: 6 bit, Blue: 5 bit*/ |  | ||||||
|     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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x42, 0x55, 0xad, 0xdb, 0xde, 0x1c, 0xe7, 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, 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, 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, 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, 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, 0x55, 0xad, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 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, 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, 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, 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, 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, 0x79, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 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, 0x24, 0x21, 0x34, 0xa5, 0x55, 0xad, 0x55, 0xad, 0x55, 0xad, 0x55, 0xad, 0x55, 0xad, 0x55, 0xad, 0xcf, 0x7b, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x76, 0xb5, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x8c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x69, 0x4a, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xbd, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0x65, 0x29, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0xb6, 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0x8a, 0x52, 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, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x59, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9a, 0xd6, 0x08, 0x42, 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, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x55, 0xad, 0x9a, 0xd6, 0xd7, 0xbd, 0x8e, 0x73, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0xd7, 0xbd, 0xbb, 0xde, 0x3c, 0xe7, 0xfc, 0xe6, 0x39, 0xce, 0x72, 0x94, 0xa7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa3, 0x18, 0x8e, 0x73, 0xd7, 0xbd, 0x1c, 0xe7, 0x9e, 0xf7, 0xbe, 0xf7, 0x5d, 0xef, 0x9a, 0xd6, 0x34, 0xa5, 0x28, 0x42, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x6b, 0xfb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x7a, 0xd6, 0x71, 0x8c, 0xa6, 0x31, 0x2d, 0x6b, 0xb6, 0xb5, 0x7d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xd7, 0xbd, 0xa3, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x9c, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3c, 0xe7, 0x49, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xe7, 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, 0x38, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x69, 0x4a, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 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, 0x7e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x14, 0xa5, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x9c, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xef, 0x24, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xef, 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, 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x45, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0xe7, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x0c, 0x63, 0xdf, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0xeb, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xef, 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, 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0xa5, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0xdb, 0xde, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0x86, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xef, 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, 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x31, 0xbf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0xe7, 0x39, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x8e, 0x73, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3d, 0xef, 0x86, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, 0xef, 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, 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9a, 0xd6, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x79, 0xce, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xd6, 0x3c, 0xe7, 0x3c, 0xe7, 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x3c, 0xe7, 0x96, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x8c, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x9e, 0xf7, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7a, 0xd6, 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, 0xa7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x18, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0xec, 0x62, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x71, 0x8c, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x31, 0x8c, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x4a, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x4d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x6e, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0xd3, 0x9c, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0xe4, 0x20, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x55, 0xad, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xa5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x76, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x34, 0xa5, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x28, 0x42, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x2d, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x29, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x92, 0x94, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xae, 0x73, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0x9a, 0xd6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x96, 0xb5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0xf0, 0x83, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0xc5, 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, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0x72, 0x94, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1c, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb, 0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x9c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x8a, 0x52, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbf, 0xff, 0x28, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0xbe, 0xf7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8a, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x45, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x9e, 0xf7, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7a, 0xd6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0x18, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x75, 0xad, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xe6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x59, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x9a, 0xd6, 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, 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, 0xb7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0x6d, 0x6b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0xf4, 0xa4, 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, 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, 0x59, 0xce, 0x86, 0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0x3d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x49, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x55, 0xad, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xa3, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0xa6, 0x31, 0xdf, 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, 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, 0x9e, 0xf7, 0xef, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0x96, 0xb5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0xa5, 0x00, 0x00, 0x00, 0x00, 0xfb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x9a, 0xd6, 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, 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, 0x0c, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb7, 0xbd, 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, 0x49, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0x00, 0x00, 0x29, 0x4a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xeb, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x51, 0x8c, 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, 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, 0xdb, 0xde, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x39, 0xce, 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, 0xdb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0x39, 0xf3, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0xe7, 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, 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, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0x24, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x31, 0x29, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x9c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf3, 0x9c, 0xbb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x14, 0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x51, 0x8c, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa7, 0x39, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xe6, 0xd3, 0x9c, 0x51, 0x8c, 0x34, 0xa5, 0x9a, 0xd6, 0xdf, 0xff, 0xf7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa6, 0x31, 0xdf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xdf, 0xff, 0x08, 0x42, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xe6, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xcf, 0x7b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf, 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, 0x1c, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x59, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9a, 0xd6, 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, 0xec, 0x62, 0xdf, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x79, 0xce, 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, 0xe7, 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, 0xdf, 0xff, 0xe7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcf, 0x7b, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x51, 0x8c, 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, 0x55, 0xad, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0xe7, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb7, 0xbd, 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, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7d, 0xef, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 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, 0x59, 0xce, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x10, 0x84, 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, 0xe8, 0x41, 0xdf, 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, 0xf7, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd7, 0xbd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x18, 0xc6, 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, 0x9a, 0xd6, 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, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xb2, 0x94, 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, 0x51, 0x8c, 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, 0x39, 0xce, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x8e, 0x73, 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, 0x18, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x9e, 0xf7, 0x39, 0xce, 0x72, 0x94, 0xcb, 0x5a, 0xa3, 0x18, 0x4d, 0x6b, 0x34, 0xa5, 0xfb, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xf7, 0x72, 0x94, 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, 0xaf, 0x7b, 0x3c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7d, 0xef, 0xd7, 0xbd, 0xeb, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x5d, 0xef, 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, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x73, 0xf8, 0xc5, 0xba, 0xd6, 0xd7, 0xbd, 0xf0, 0x83, 0xa3, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x4a, 0xf3, 0x9c, 0xf8, 0xc5, 0x59, 0xce, 0x55, 0xad, 0x08, 0x42, 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, 0x00, 0x00, 0x00, 0x00, 0xae, 0x73, 0x76, 0xb5, 0x39, 0xce, 0x7a, 0xd6, 0x39, 0xce, 0xd7, 0xbd, 0xd3, 0x9c, 0xec, 0x62, 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, 0x29, 0x4a, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x0c, 0x63, 0x49, 0x4a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t appleDisplayIcon_map[] = { |  | ||||||
|   0x23, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd8, 0x3d, |  | ||||||
|   0xaa, 0xfd, 0xad, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0x9a, 0xa1, 0xf7, 0xd8, |  | ||||||
|   0xd0, 0xd1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xa1, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xd2, 0xcb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9a, 0xff, |  | ||||||
|   0xc6, 0xea, 0x2a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1f, 0xcc, 0xf6, |  | ||||||
|   0x6c, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x98, |  | ||||||
|   0x00, 0x44, 0x7b, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7d, 0x56, 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, 0x13, 0xb7, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc4, 0xc0, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x19, 0xd3, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xde, 0xdb, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t appleBackIcon_map[] = { |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, 0x07, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, 0xbe, 0x94, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xe7, 0xff, 0xf0, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0xfa, 0xff, 0xf5, 0x31, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0xfc, 0xff, 0xea, 0x3e, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4d, 0xee, 0xff, 0xe6, 0x48, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x01, 0x00, 0x50, 0xed, 0xff, 0xe9, 0x39, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x55, 0xfc, 0xff, 0xe7, 0x25, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x59, 0xff, 0xff, 0xe0, 0x2d, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x5e, 0xf6, 0xff, 0xdb, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x64, 0xf4, 0xff, 0xd9, 0x2e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x4d, 0xff, 0xff, 0xce, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x6b, 0xff, 0xff, 0x9e, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x9c, 0xff, 0xff, 0xa8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x04, 0x8f, 0xff, 0xff, 0xb5, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x03, 0x91, 0xff, 0xff, 0xba, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x93, 0xff, 0xff, 0xbb, 0x0a, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x01, 0x00, 0x87, 0xfc, 0xff, 0xbf, 0x14, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xfb, 0xff, 0xc5, 0x22, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x78, 0xff, 0xff, 0xca, 0x1e, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x75, 0xff, 0xff, 0xd0, 0x11, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x6e, 0xfb, 0xff, 0xcc, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x68, 0xea, 0xca, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x28, 0x18, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t high_brightness_map[] = { |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x5c, 0x8e, 0x04, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x04, 0x8e, 0x5c, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x8c, 0xff, 0xa8, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0xa8, 0xff, 0x8c, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x04, 0xa9, 0xf5, 0x0d, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x0d, 0xf5, 0xa9, 0x04, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x42, 0xd4, 0xff, 0xff, 0xd4, 0x41, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0xbd, 0xcc, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x12, 0x0d, 0xbd, 0xcc, 0xbd, |  | ||||||
|   0xbd, 0xcc, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x10, 0x0d, 0xbd, 0xcc, 0xbd, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x01, 0x0a, 0x00, 0x40, 0xd3, 0xff, 0xfe, 0xd2, 0x3f, 0x00, 0x0a, 0x01, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x04, 0xa9, 0xf5, 0x0d, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x0d, 0xf5, 0xa9, 0x04, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x8c, 0xff, 0xa8, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0xa8, 0xff, 0x8c, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x5c, 0x8e, 0x04, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x04, 0x8e, 0x5c, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd4, 0xd4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t low_brightness_map[] = { |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x27, 0x72, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0x72, 0x28, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x71, 0xf5, 0x0f, 0x00, 0x00, 0x11, 0x11, 0x00, 0x00, 0x0d, 0xf5, 0x73, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x01, 0x0b, 0x00, 0x42, 0xd4, 0xff, 0xff, 0xd4, 0x41, 0x00, 0x0a, 0x01, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x42, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xfd, 0x40, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0xd5, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd3, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x43, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x12, 0x0d, 0xbc, 0x44, |  | ||||||
|   0x43, 0xbd, 0x0d, 0x11, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x11, 0x0d, 0xbc, 0x44, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0xd4, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd2, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x41, 0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x01, 0x0b, 0x00, 0x40, 0xd3, 0xfe, 0xff, 0xd2, 0x3f, 0x00, 0x0a, 0x01, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x71, 0xf5, 0x0f, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x0d, 0xf5, 0x73, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x27, 0x72, 0x01, 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x00, 0x01, 0x72, 0x28, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbd, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_LARGE_CONST uint8_t lightbulb_map[] = { |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x04, 0x1c, 0x1c, 0x04, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x16, 0x95, 0xee, 0xff, 0xff, 0xee, 0x94, 0x15, 0x00, 0x00, |  | ||||||
|   0x00, 0x27, 0xe3, 0xff, 0xcc, 0x8d, 0x8d, 0xcd, 0xff, 0xe1, 0x26, 0x00, |  | ||||||
|   0x07, 0xd9, 0xfa, 0x5d, 0x00, 0x00, 0x00, 0x00, 0x5f, 0xfa, 0xd7, 0x06, |  | ||||||
|   0x65, 0xff, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a, 0xff, 0x63, |  | ||||||
|   0xb1, 0xf8, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0xf8, 0xaf, |  | ||||||
|   0xcc, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdb, 0xcd, |  | ||||||
|   0xb1, 0xf5, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0xf1, 0xbd, |  | ||||||
|   0x73, 0xff, 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0xff, 0x74, |  | ||||||
|   0x0b, 0xd5, 0xfb, 0x40, 0x00, 0x00, 0x00, 0x00, 0x41, 0xfb, 0xd9, 0x0b, |  | ||||||
|   0x00, 0x24, 0xef, 0xdc, 0x01, 0x00, 0x00, 0x01, 0xdd, 0xee, 0x24, 0x00, |  | ||||||
|   0x00, 0x00, 0x83, 0xff, 0x30, 0x00, 0x00, 0x30, 0xff, 0x81, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x12, 0x6c, 0x06, 0x00, 0x00, 0x06, 0x6c, 0x12, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x25, 0xc7, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0x25, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x25, 0xc7, 0xcc, 0xcc, 0xcc, 0xcc, 0xc7, 0x25, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x1c, 0x76, 0x77, 0x77, 0x76, 0x1c, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x69, 0xff, 0xff, 0xff, 0xff, 0x69, 0x00, 0x00, 0x00, |  | ||||||
|   0x00, 0x00, 0x00, 0x01, 0x21, 0x22, 0x22, 0x21, 0x01, 0x00, 0x00, 0x00, |  | ||||||
| }; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| int main() | int main() | ||||||
| { | { | ||||||
|   lv_init(); |     auto hal = std::make_shared<HardwareSimulator>(); | ||||||
|  |     hal->init(); | ||||||
|  | 
 | ||||||
|  |     auto ui = OmoteUI::getInstance(hal); | ||||||
| 
 | 
 | ||||||
|     if (!single_display_mode_initialization()) |     if (!single_display_mode_initialization()) | ||||||
|     { |     { | ||||||
|         return -1; |         return -1; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| 
 |     ui->layout_UI(); | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   // --- LVGL UI Configuration ---  
 |  | ||||||
| 
 |  | ||||||
|   // Set the background color
 |  | ||||||
|   lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   // Setup a scrollable tabview for devices and settings
 |  | ||||||
|   lv_obj_t* tabview; |  | ||||||
|   tabview = lv_tabview_create(lv_scr_act(), LV_DIR_TOP, 0); // Hide tab labels by setting their height to 0
 |  | ||||||
|   lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_size(tabview, screenWidth, 270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
 |  | ||||||
|   lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20); |  | ||||||
| 
 |  | ||||||
|   // Add 4 tabs (names are irrelevant since the labels are hidden)
 |  | ||||||
|   lv_obj_t* tab1 = lv_tabview_add_tab(tabview, "Settings"); |  | ||||||
|   lv_obj_t* tab2 = lv_tabview_add_tab(tabview, "Technisat"); |  | ||||||
|   lv_obj_t* tab3 = lv_tabview_add_tab(tabview, "Apple TV"); |  | ||||||
|   lv_obj_t* tab4 = lv_tabview_add_tab(tabview, "Smart Home"); |  | ||||||
| 
 |  | ||||||
|   // Configure number button grid 
 |  | ||||||
|   static lv_coord_t col_dsc[] = { LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_TEMPLATE_LAST }; // equal x distribution
 |  | ||||||
|   static lv_coord_t row_dsc[] = { 52, 52, 52, 52, LV_GRID_TEMPLATE_LAST }; // manual y distribution to compress the grid a bit
 |  | ||||||
| 
 |  | ||||||
|   // Create a container with grid for tab2
 |  | ||||||
|   lv_obj_set_style_pad_all(tab2, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_t* cont = lv_obj_create(tab2); |  | ||||||
|   lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_grid_column_dsc_array(cont, col_dsc, 0); |  | ||||||
|   lv_obj_set_style_grid_row_dsc_array(cont, row_dsc, 0); |  | ||||||
|   lv_obj_set_size(cont, 240, 270); |  | ||||||
|   lv_obj_set_layout(cont, LV_LAYOUT_GRID); |  | ||||||
|   lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0); |  | ||||||
|   lv_obj_set_style_radius(cont, 0, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   lv_obj_t* buttonLabel; |  | ||||||
|   lv_obj_t* obj; |  | ||||||
| 
 |  | ||||||
|   // Iterate through grid buttons and configure them
 |  | ||||||
|   for (int i = 0; i < 12; i++) { |  | ||||||
|       uint8_t col = i % 3; |  | ||||||
|       uint8_t row = i / 3; |  | ||||||
|       // Create the button object
 |  | ||||||
|       if ((row == 3) && ((col == 0) || (col == 2))) continue; // Do not create a complete fourth row, only a 0 button
 |  | ||||||
|       obj = lv_btn_create(cont); |  | ||||||
|       lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, LV_GRID_ALIGN_STRETCH, row, 1); |  | ||||||
|       lv_obj_set_style_bg_color(obj, color_primary, LV_PART_MAIN); |  | ||||||
|       lv_obj_set_style_radius(obj, 14, LV_PART_MAIN); |  | ||||||
|       lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes a event in its container
 |  | ||||||
|       // Create Labels for each button
 |  | ||||||
|       buttonLabel = lv_label_create(obj); |  | ||||||
|       if (i < 9) { |  | ||||||
|           lv_label_set_text_fmt(buttonLabel, std::to_string(i + 1).c_str(), col, row); |  | ||||||
|           lv_obj_set_user_data(obj, (void*)i); // Add user data so we can identify which button caused the container event
 |  | ||||||
|       } |  | ||||||
|       else { |  | ||||||
|           lv_label_set_text_fmt(buttonLabel, "0", col, row); |  | ||||||
|           lv_obj_set_user_data(obj, (void*)9); |  | ||||||
|       } |  | ||||||
|       lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_24, LV_PART_MAIN); |  | ||||||
|       lv_obj_center(buttonLabel); |  | ||||||
|   } |  | ||||||
|   // Create a shared event for all button inside container
 |  | ||||||
|   lv_obj_add_event_cb(cont, virtualKeypad_event_cb, LV_EVENT_CLICKED, NULL); |  | ||||||
| 
 |  | ||||||
|   // Only for the LVGL PC Simulator !!!
 |  | ||||||
|   lv_img_dsc_t appleTvIcon; |  | ||||||
|   appleTvIcon.header.cf = LV_IMG_CF_TRUE_COLOR; |  | ||||||
|   appleTvIcon.header.always_zero = 0; |  | ||||||
|   appleTvIcon.header.reserved = 0; |  | ||||||
|   appleTvIcon.header.w = 91; |  | ||||||
|   appleTvIcon.header.h = 42; |  | ||||||
|   appleTvIcon.data_size = 3822 * LV_COLOR_SIZE / 8; |  | ||||||
|   appleTvIcon.data = appleTvIcon_map; |  | ||||||
|   lv_img_dsc_t appleDisplayIcon; |  | ||||||
|   appleDisplayIcon.header.cf = LV_IMG_CF_ALPHA_8BIT; |  | ||||||
|   appleDisplayIcon.header.always_zero = 0; |  | ||||||
|   appleDisplayIcon.header.reserved = 0; |  | ||||||
|   appleDisplayIcon.header.w = 25; |  | ||||||
|   appleDisplayIcon.header.h = 20; |  | ||||||
|   appleDisplayIcon.data_size = 500; |  | ||||||
|   appleDisplayIcon.data = appleDisplayIcon_map; |  | ||||||
|   lv_img_dsc_t appleBackIcon; |  | ||||||
|   appleBackIcon.header.cf = LV_IMG_CF_ALPHA_8BIT; |  | ||||||
|   appleBackIcon.header.always_zero = 0; |  | ||||||
|   appleBackIcon.header.reserved = 0; |  | ||||||
|   appleBackIcon.header.w = 13; |  | ||||||
|   appleBackIcon.header.h = 25; |  | ||||||
|   appleBackIcon.data_size = 325; |  | ||||||
|   appleBackIcon.data = appleBackIcon_map;   |  | ||||||
|    |  | ||||||
| 
 |  | ||||||
|   // Add content to the Apple TV tab (3)
 |  | ||||||
|   // Add a nice apple tv logo
 |  | ||||||
|   lv_obj_t* appleImg = lv_img_create(tab3); |  | ||||||
|   lv_img_set_src(appleImg, &appleTvIcon); |  | ||||||
|   lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, -60); |  | ||||||
|   // create two buttons and add their icons accordingly
 |  | ||||||
|   lv_obj_t* button = lv_btn_create(tab3); |  | ||||||
|   lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0); |  | ||||||
|   lv_obj_set_size(button, 60, 60); |  | ||||||
|   lv_obj_set_style_radius(button, 30, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_add_event_cb(button, appleKey_event_cb, LV_EVENT_CLICKED, (void*)1); |  | ||||||
| 
 |  | ||||||
|   appleImg = lv_img_create(button); |  | ||||||
|   lv_img_set_src(appleImg, &appleBackIcon); |  | ||||||
|   lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN); |  | ||||||
|   lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0); |  | ||||||
| 
 |  | ||||||
|   button = lv_btn_create(tab3); |  | ||||||
|   lv_obj_align(button, LV_ALIGN_BOTTOM_RIGHT, -10, 0); |  | ||||||
|   lv_obj_set_size(button, 60, 60); |  | ||||||
|   lv_obj_set_style_radius(button, 30, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_add_event_cb(button, appleKey_event_cb, LV_EVENT_CLICKED, (void*)2); |  | ||||||
| 
 |  | ||||||
|   appleImg = lv_img_create(button); |  | ||||||
|   lv_img_set_src(appleImg, &appleDisplayIcon); |  | ||||||
|   lv_obj_set_style_img_recolor(appleImg, lv_color_white(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_img_recolor_opa(appleImg, LV_OPA_COVER, LV_PART_MAIN); |  | ||||||
|   lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|    |  | ||||||
| 
 |  | ||||||
|   // Add content to the settings tab
 |  | ||||||
|   // With a flex layout, setting groups/boxes will position themselves automatically
 |  | ||||||
|   lv_obj_set_layout(tab1, LV_LAYOUT_FLEX); |  | ||||||
|   lv_obj_set_flex_flow(tab1, LV_FLEX_FLOW_COLUMN); |  | ||||||
|   lv_obj_set_scrollbar_mode(tab1, LV_SCROLLBAR_MODE_ACTIVE); |  | ||||||
| 
 |  | ||||||
|   // Only for the LVGL PC Simulator !!!
 |  | ||||||
|   lv_img_dsc_t high_brightness; |  | ||||||
|   high_brightness.header.cf = LV_IMG_CF_ALPHA_8BIT, |  | ||||||
|   high_brightness.header.always_zero = 0, |  | ||||||
|   high_brightness.header.reserved = 0, |  | ||||||
|   high_brightness.header.w = 18, |  | ||||||
|   high_brightness.header.h = 18, |  | ||||||
|   high_brightness.data_size = 352, |  | ||||||
|   high_brightness.data = high_brightness_map; |  | ||||||
|   lv_img_dsc_t low_brightness; |  | ||||||
|   low_brightness.header.cf = LV_IMG_CF_ALPHA_8BIT, |  | ||||||
|   low_brightness.header.always_zero = 0, |  | ||||||
|   low_brightness.header.reserved = 0, |  | ||||||
|   low_brightness.header.w = 16, |  | ||||||
|   low_brightness.header.h = 16, |  | ||||||
|   low_brightness.data_size = 256, |  | ||||||
|   low_brightness.data = low_brightness_map; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   // Add a label, then a box for the display settings
 |  | ||||||
|   lv_obj_t* menuLabel = lv_label_create(tab1); |  | ||||||
|   lv_label_set_text(menuLabel, "Display"); |  | ||||||
| 
 |  | ||||||
|   lv_obj_t* menuBox = lv_obj_create(tab1); |  | ||||||
|   lv_obj_set_size(menuBox, lv_pct(100), 109); |  | ||||||
|   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   lv_obj_t* brightnessIcon = lv_img_create(menuBox); |  | ||||||
|   lv_img_set_src(brightnessIcon, &low_brightness); |  | ||||||
|   lv_obj_set_style_img_recolor(brightnessIcon, lv_color_white(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_img_recolor_opa(brightnessIcon, LV_OPA_COVER, LV_PART_MAIN); |  | ||||||
|   lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0); |  | ||||||
|   lv_obj_t* slider = lv_slider_create(menuBox); |  | ||||||
|   lv_slider_set_range(slider, 60, 255); |  | ||||||
|   lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); |  | ||||||
|   lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); |  | ||||||
|   lv_slider_set_value(slider, backlight_brightness, LV_ANIM_OFF); |  | ||||||
|   lv_obj_set_size(slider, lv_pct(66), 10); |  | ||||||
|   lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3); |  | ||||||
|   brightnessIcon = lv_img_create(menuBox); |  | ||||||
|   lv_img_set_src(brightnessIcon, &high_brightness); |  | ||||||
|   lv_obj_set_style_img_recolor(brightnessIcon, lv_color_white(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_img_recolor_opa(brightnessIcon, LV_OPA_COVER, LV_PART_MAIN); |  | ||||||
|   lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1); |  | ||||||
|   lv_obj_add_event_cb(slider, bl_slider_event_cb, LV_EVENT_VALUE_CHANGED, NULL); |  | ||||||
| 
 |  | ||||||
|   menuLabel = lv_label_create(menuBox); |  | ||||||
|   lv_label_set_text(menuLabel, "Lift to Wake"); |  | ||||||
|   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32); |  | ||||||
|   lv_obj_t* wakeToggle = lv_switch_create(menuBox); |  | ||||||
|   lv_obj_set_size(wakeToggle, 40, 22); |  | ||||||
|   lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29); |  | ||||||
|   lv_obj_set_style_bg_color(wakeToggle, lv_color_lighten(color_primary, 50), LV_PART_MAIN); |  | ||||||
|   lv_obj_add_event_cb(wakeToggle, WakeEnableSetting_event_cb, LV_EVENT_VALUE_CHANGED, NULL); |  | ||||||
|   if (wakeupByIMUEnabled) lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
 |  | ||||||
| 
 |  | ||||||
|   menuLabel = lv_label_create(menuBox); |  | ||||||
|   lv_label_set_text(menuLabel, "Timeout"); |  | ||||||
|   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64); |  | ||||||
|   lv_obj_t* drop = lv_dropdown_create(menuBox); |  | ||||||
|   lv_dropdown_set_options(drop, "10s\n" |  | ||||||
|       "30s\n" |  | ||||||
|       "1m\n" |  | ||||||
|       "3m"); |  | ||||||
|   lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61); |  | ||||||
|   lv_obj_set_size(drop, 70, 22); |  | ||||||
|   lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(drop, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(drop, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_color(lv_dropdown_get_list(drop), lv_color_darken(color_primary, 40), LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   // Add another label, then a settings box for WiFi
 |  | ||||||
|   menuLabel = lv_label_create(tab1); |  | ||||||
|   lv_label_set_text(menuLabel, "Wi-Fi"); |  | ||||||
|   menuBox = lv_obj_create(tab1); |  | ||||||
|   lv_obj_set_size(menuBox, lv_pct(100), 80); |  | ||||||
|   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); |  | ||||||
|   menuLabel = lv_label_create(menuBox); |  | ||||||
|   lv_label_set_text(menuLabel, "Network"); |  | ||||||
|   menuLabel = lv_label_create(menuBox); |  | ||||||
|   lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT); |  | ||||||
|   lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 0); |  | ||||||
|   menuLabel = lv_label_create(menuBox); |  | ||||||
|   lv_label_set_text(menuLabel, "Password"); |  | ||||||
|   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32); |  | ||||||
|   menuLabel = lv_label_create(menuBox); |  | ||||||
|   lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT); |  | ||||||
|   lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 32); |  | ||||||
| 
 |  | ||||||
|   // Another setting for the battery
 |  | ||||||
|   menuLabel = lv_label_create(tab1); |  | ||||||
|   lv_label_set_text(menuLabel, "Battery"); |  | ||||||
|   menuBox = lv_obj_create(tab1); |  | ||||||
|   lv_obj_set_size(menuBox, lv_pct(100), 125); |  | ||||||
|   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   // Add content to the smart home tab (4)
 |  | ||||||
| 
 |  | ||||||
|   // Only for the LVGL PC Simulator !!!
 |  | ||||||
|   lv_img_dsc_t lightbulb; |  | ||||||
|   lightbulb.header.cf = LV_IMG_CF_ALPHA_8BIT, |  | ||||||
|   lightbulb.header.always_zero = 0, |  | ||||||
|   lightbulb.header.reserved = 0, |  | ||||||
|   lightbulb.header.w = 12, |  | ||||||
|   lightbulb.header.h = 20, |  | ||||||
|   lightbulb.data_size = 240, |  | ||||||
|   lightbulb.data = lightbulb_map; |  | ||||||
| 
 |  | ||||||
|   lv_obj_set_layout(tab4, LV_LAYOUT_FLEX); |  | ||||||
|   lv_obj_set_flex_flow(tab4, LV_FLEX_FLOW_COLUMN); |  | ||||||
|   lv_obj_set_scrollbar_mode(tab4, LV_SCROLLBAR_MODE_ACTIVE); |  | ||||||
| 
 |  | ||||||
|   // Add a label, then a box for the light controls
 |  | ||||||
|   menuLabel = lv_label_create(tab4); |  | ||||||
|   lv_label_set_text(menuLabel, "Living Room"); |  | ||||||
| 
 |  | ||||||
|   menuBox = lv_obj_create(tab4); |  | ||||||
|   lv_obj_set_size(menuBox, lv_pct(100), 79); |  | ||||||
|   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   lv_obj_t* bulbIcon = lv_img_create(menuBox); |  | ||||||
|   lv_img_set_src(bulbIcon, &lightbulb); |  | ||||||
|   lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_img_recolor_opa(bulbIcon, LV_OPA_COVER, LV_PART_MAIN); |  | ||||||
|   lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0); |  | ||||||
| 
 |  | ||||||
|   menuLabel = lv_label_create(menuBox); |  | ||||||
|   lv_label_set_text(menuLabel, "Floor Lamp"); |  | ||||||
|   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3); |  | ||||||
|   lv_obj_t* lightToggleA = lv_switch_create(menuBox); |  | ||||||
|   lv_obj_set_size(lightToggleA, 40, 22); |  | ||||||
|   lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0); |  | ||||||
|   lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(lightToggleA, color_primary, LV_PART_INDICATOR); |  | ||||||
|   lv_obj_add_event_cb(lightToggleA, smartHomeToggle_event_cb, LV_EVENT_VALUE_CHANGED, (void*)1); |  | ||||||
| 
 |  | ||||||
|   slider = lv_slider_create(menuBox); |  | ||||||
|   lv_slider_set_range(slider, 60, 255); |  | ||||||
|   lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR); |  | ||||||
|   lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR); |  | ||||||
|   lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR); |  | ||||||
|   lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); |  | ||||||
|   lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); |  | ||||||
|   lv_slider_set_value(slider, 255, LV_ANIM_OFF); |  | ||||||
|   lv_obj_set_size(slider, lv_pct(90), 10); |  | ||||||
|   lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37); |  | ||||||
|   lv_obj_add_event_cb(slider, smartHomeSlider_event_cb, LV_EVENT_VALUE_CHANGED, (void*)1); |  | ||||||
| 
 |  | ||||||
|   // Add another menu box for a second appliance
 |  | ||||||
|   menuBox = lv_obj_create(tab4); |  | ||||||
|   lv_obj_set_size(menuBox, lv_pct(100), 79); |  | ||||||
|   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   bulbIcon = lv_img_create(menuBox); |  | ||||||
|   lv_img_set_src(bulbIcon, &lightbulb); |  | ||||||
|   lv_obj_set_style_img_recolor(bulbIcon, lv_color_white(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_img_recolor_opa(bulbIcon, LV_OPA_COVER, LV_PART_MAIN); |  | ||||||
|   lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0); |  | ||||||
| 
 |  | ||||||
|   menuLabel = lv_label_create(menuBox); |  | ||||||
|   lv_label_set_text(menuLabel, "Ceiling Light"); |  | ||||||
|   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3); |  | ||||||
|   lv_obj_t* lightToggleB = lv_switch_create(menuBox); |  | ||||||
|   lv_obj_set_size(lightToggleB, 40, 22); |  | ||||||
|   lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0); |  | ||||||
|   lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(lightToggleB, color_primary, LV_PART_INDICATOR); |  | ||||||
|   lv_obj_add_event_cb(lightToggleB, smartHomeToggle_event_cb, LV_EVENT_VALUE_CHANGED, (void*)2); |  | ||||||
| 
 |  | ||||||
|   slider = lv_slider_create(menuBox); |  | ||||||
|   lv_slider_set_range(slider, 60, 255); |  | ||||||
|   lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), LV_PART_INDICATOR); |  | ||||||
|   lv_obj_set_style_bg_grad_color(slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), LV_PART_INDICATOR); |  | ||||||
|   lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR); |  | ||||||
|   lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); |  | ||||||
|   lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), LV_PART_MAIN); |  | ||||||
|   lv_slider_set_value(slider, 255, LV_ANIM_OFF); |  | ||||||
|   lv_obj_set_size(slider, lv_pct(90), 10); |  | ||||||
|   lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37); |  | ||||||
|   lv_obj_add_event_cb(slider, smartHomeSlider_event_cb, LV_EVENT_VALUE_CHANGED, (void*)2); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   // Add another room (empty for now)
 |  | ||||||
|   menuLabel = lv_label_create(tab4); |  | ||||||
|   lv_label_set_text(menuLabel, "Kitchen"); |  | ||||||
| 
 |  | ||||||
|   menuBox = lv_obj_create(tab4); |  | ||||||
|   lv_obj_set_size(menuBox, lv_pct(100), 79); |  | ||||||
|   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   // Set current page according to the current Device
 |  | ||||||
|   lv_tabview_set_act(tabview, currentDevice, LV_ANIM_OFF); |  | ||||||
| 
 |  | ||||||
|   // Create a page indicator
 |  | ||||||
|   panel = lv_obj_create(lv_scr_act()); |  | ||||||
|   lv_obj_clear_flag(panel, LV_OBJ_FLAG_CLICKABLE); // this indicator will not be clickable
 |  | ||||||
|   lv_obj_set_size(panel, screenWidth, 30); |  | ||||||
|   lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW); |  | ||||||
|   lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0); |  | ||||||
|   lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF); |  | ||||||
|   // This small hidden button enables the page indicator to scroll further
 |  | ||||||
|   lv_obj_t* btn = lv_btn_create(panel); |  | ||||||
|   lv_obj_set_size(btn, 50, lv_pct(100)); |  | ||||||
|   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN); |  | ||||||
|   // Create actual (non-clickable) buttons for every tab
 |  | ||||||
|   btn = lv_btn_create(panel); |  | ||||||
|   lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); |  | ||||||
|   lv_obj_set_size(btn, 150, lv_pct(100)); |  | ||||||
|   lv_obj_t* label = lv_label_create(btn); |  | ||||||
|   lv_label_set_text_fmt(label, "Settings"); |  | ||||||
|   lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); |  | ||||||
|   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   btn = lv_btn_create(panel); |  | ||||||
|   lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); |  | ||||||
|   lv_obj_set_size(btn, 150, lv_pct(100)); |  | ||||||
|   label = lv_label_create(btn); |  | ||||||
|   lv_label_set_text_fmt(label, "Technisat"); |  | ||||||
|   lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); |  | ||||||
|   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   btn = lv_btn_create(panel); |  | ||||||
|   lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); |  | ||||||
|   lv_obj_set_size(btn, 150, lv_pct(100)); |  | ||||||
|   label = lv_label_create(btn); |  | ||||||
|   lv_label_set_text_fmt(label, "Apple TV"); |  | ||||||
|   lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); |  | ||||||
|   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   btn = lv_btn_create(panel); |  | ||||||
|   lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); |  | ||||||
|   lv_obj_set_size(btn, 150, lv_pct(100)); |  | ||||||
|   label = lv_label_create(btn); |  | ||||||
|   lv_label_set_text_fmt(label, "Smart Home"); |  | ||||||
|   lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); |  | ||||||
|   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); |  | ||||||
|   // This small hidden button enables the page indicator to scroll further
 |  | ||||||
|   btn = lv_btn_create(panel); |  | ||||||
|   lv_obj_set_size(btn, 50, lv_pct(100)); |  | ||||||
|   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   // Make the indicator scroll together with the tabs by creating a scroll event
 |  | ||||||
|   lv_obj_add_event_cb(lv_tabview_get_content(tabview), store_scroll_value_event_cb, LV_EVENT_SCROLL, NULL); |  | ||||||
|   lv_obj_add_event_cb(tabview, tabview_device_event_cb, LV_EVENT_VALUE_CHANGED, NULL); |  | ||||||
|   // Initialize scroll position for the indicator
 |  | ||||||
|   lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL); |  | ||||||
| 
 |  | ||||||
|   // Style the panel background
 |  | ||||||
|   static lv_style_t style_btn; |  | ||||||
|   lv_style_init(&style_btn); |  | ||||||
|   lv_style_set_pad_all(&style_btn, 3); |  | ||||||
|   lv_style_set_border_width(&style_btn, 0); |  | ||||||
|   lv_style_set_bg_opa(&style_btn, LV_OPA_TRANSP); |  | ||||||
|   lv_obj_add_style(panel, &style_btn, 0); |  | ||||||
| 
 |  | ||||||
|   // Only for the LVGL PC Simulator !!!
 |  | ||||||
|   lv_img_dsc_t gradientLeft; |  | ||||||
|   gradientLeft.header.cf = LV_IMG_CF_ALPHA_8BIT; |  | ||||||
|   gradientLeft.header.always_zero = 0; |  | ||||||
|   gradientLeft.header.reserved = 0; |  | ||||||
|   gradientLeft.header.w = 30; |  | ||||||
|   gradientLeft.header.h = 1; |  | ||||||
|   gradientLeft.data_size = 30; |  | ||||||
|   gradientLeft.data = gradientLeft_map; |  | ||||||
|   lv_img_dsc_t gradientRight; |  | ||||||
|   gradientRight.header.cf = LV_IMG_CF_ALPHA_8BIT; |  | ||||||
|   gradientRight.header.always_zero = 0; |  | ||||||
|   gradientRight.header.reserved = 0; |  | ||||||
|   gradientRight.header.w = 30; |  | ||||||
|   gradientRight.header.h = 1; |  | ||||||
|   gradientRight.data_size = 30; |  | ||||||
|   gradientRight.data = gradientRight_map; |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   // Make the indicator fade out at the sides using gradient bitmaps
 |  | ||||||
|   lv_obj_t* img1 = lv_img_create(lv_scr_act()); |  | ||||||
|   lv_img_set_src(img1, &gradientLeft); |  | ||||||
|   lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0); |  | ||||||
|   lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px
 |  | ||||||
|   lv_obj_t* img2 = lv_img_create(lv_scr_act()); |  | ||||||
|   lv_img_set_src(img2, &gradientRight); |  | ||||||
|   lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0); |  | ||||||
|   lv_obj_set_size(img2, 30, 30); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|   // Create a status bar
 |  | ||||||
|   lv_obj_t* statusbar = lv_btn_create(lv_scr_act()); |  | ||||||
|   lv_obj_set_size(statusbar, 240, 20); |  | ||||||
|   lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN); |  | ||||||
|   lv_obj_set_style_radius(statusbar, 0, LV_PART_MAIN); |  | ||||||
|   lv_obj_align(statusbar, LV_ALIGN_TOP_MID, 0, 0); |  | ||||||
| 
 |  | ||||||
|   lv_obj_t* WifiLabel = lv_label_create(statusbar); |  | ||||||
|   lv_label_set_text(WifiLabel, LV_SYMBOL_WIFI); |  | ||||||
|   lv_obj_align(WifiLabel, LV_ALIGN_LEFT_MID, -8, 0); |  | ||||||
|   lv_obj_set_style_text_font(WifiLabel, &lv_font_montserrat_12, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   lv_obj_t* objBattPercentage = lv_label_create(statusbar); |  | ||||||
|   lv_label_set_text(objBattPercentage, ""); |  | ||||||
|   lv_obj_align(objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0); |  | ||||||
|   lv_obj_set_style_text_font(objBattPercentage, &lv_font_montserrat_12, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
|   lv_obj_t* objBattIcon = lv_label_create(statusbar); |  | ||||||
|   lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_EMPTY); |  | ||||||
|   lv_obj_align(objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0); |  | ||||||
|   lv_obj_set_style_text_font(objBattIcon, &lv_font_montserrat_16, LV_PART_MAIN); |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
| 
 | 
 | ||||||
|     while (!lv_win32_quit_signal) |     while (!lv_win32_quit_signal) | ||||||
|     { |     { | ||||||
|         lv_task_handler(); |         lv_task_handler(); | ||||||
|       //std::string strng = std::to_string(scroll_value);
 |         // std::string strng = std::to_string(scroll_value);
 | ||||||
|       //const char* pchar = strng.c_str();
 |         // const char* pchar = strng.c_str();
 | ||||||
|       //OutputDebugStringW();
 |         // OutputDebugStringW();
 | ||||||
|       //lv_label_set_text_fmt(scrollPos, "%d %d", lv_obj_get_scroll_x(lv_tabview_get_content(tabview)), lv_obj_get_scroll_x(panel));
 |         // lv_label_set_text_fmt(scrollPos, "%d %d", lv_obj_get_scroll_x(lv_tabview_get_content(tabview)), lv_obj_get_scroll_x(panel));
 | ||||||
|        |  | ||||||
| 
 | 
 | ||||||
|         Sleep(1); |         Sleep(1); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -9,6 +9,7 @@ | ||||||
|     <MileProjectType>ConsoleApplication</MileProjectType> |     <MileProjectType>ConsoleApplication</MileProjectType> | ||||||
|     <MileProjectManifestFile>LVGL.Simulator.manifest</MileProjectManifestFile> |     <MileProjectManifestFile>LVGL.Simulator.manifest</MileProjectManifestFile> | ||||||
|     <MileProjectEnableVCLTLSupport>true</MileProjectEnableVCLTLSupport> |     <MileProjectEnableVCLTLSupport>true</MileProjectEnableVCLTLSupport> | ||||||
|  |     <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|   <PropertyGroup Label="Configuration" Condition="'$(Configuration)'=='Debug'"> |   <PropertyGroup Label="Configuration" Condition="'$(Configuration)'=='Debug'"> | ||||||
|     <SupportLTL>false</SupportLTL> |     <SupportLTL>false</SupportLTL> | ||||||
|  | @ -18,6 +19,9 @@ | ||||||
|   <PropertyGroup> |   <PropertyGroup> | ||||||
|     <IncludePath>$(MSBuildThisFileDirectory);$(MSBuildThisFileDirectory)..\LvglPlatform\lvgl\;$(MSBuildThisFileDirectory)..\LvglPlatform\;$(IncludePath)</IncludePath> |     <IncludePath>$(MSBuildThisFileDirectory);$(MSBuildThisFileDirectory)..\LvglPlatform\lvgl\;$(MSBuildThisFileDirectory)..\LvglPlatform\;$(IncludePath)</IncludePath> | ||||||
|   </PropertyGroup> |   </PropertyGroup> | ||||||
|  |   <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||||
|  |     <SourcePath>$(VC_SourcePath);</SourcePath> | ||||||
|  |   </PropertyGroup> | ||||||
|   <ItemDefinitionGroup> |   <ItemDefinitionGroup> | ||||||
|     <ClCompile> |     <ClCompile> | ||||||
|       <WarningLevel>Level3</WarningLevel> |       <WarningLevel>Level3</WarningLevel> | ||||||
|  | @ -32,10 +36,19 @@ | ||||||
|       <LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">stdcpp17</LanguageStandard> |       <LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">stdcpp17</LanguageStandard> | ||||||
|       <LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">stdcpp17</LanguageStandard> |       <LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">stdcpp17</LanguageStandard> | ||||||
|     </ClCompile> |     </ClCompile> | ||||||
|  |     <Link> | ||||||
|  |       <AdditionalLibraryDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||||
|  |       </AdditionalLibraryDirectories> | ||||||
|  |     </Link> | ||||||
|   </ItemDefinitionGroup> |   </ItemDefinitionGroup> | ||||||
|   <Import Project="LVGL.Portable.vcxitems" /> |   <Import Project="LVGL.Portable.vcxitems" /> | ||||||
|   <Import Project="LVGL.Drivers.vcxitems" /> |   <Import Project="LVGL.Drivers.vcxitems" /> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  |     <ClInclude Include="..\..\Platformio\include\OmoteUI\HardwareAbstractionInterface.h" /> | ||||||
|  |     <ClInclude Include="..\..\Platformio\include\OmoteUI\Images.hpp" /> | ||||||
|  |     <ClInclude Include="..\..\Platformio\include\OmoteUI\OmoteUI.hpp" /> | ||||||
|  |     <ClInclude Include="HardwareSimulator.hpp" /> | ||||||
|  |     <ClInclude Include="omoteconfig.h" /> | ||||||
|     <ClInclude Include="lv_conf.h" /> |     <ClInclude Include="lv_conf.h" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|  | @ -49,7 +62,12 @@ | ||||||
|     <ClInclude Include="resource.h" /> |     <ClInclude Include="resource.h" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="LVGL.Simulator.cpp" /> |     <ClCompile Include="..\..\Platformio\src\HardwareAbstractionInterface.cpp" /> | ||||||
|  |     <ClCompile Include="..\..\Platformio\src\OmoteUI.cpp" /> | ||||||
|  |     <ClCompile Include="HardwareSimulator.cpp" /> | ||||||
|  |     <ClCompile Include="LVGL.Simulator.cpp"> | ||||||
|  |       <LanguageStandard Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">stdcpp17</LanguageStandard> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ResourceCompile Include="LVGL.Simulator.rc" /> |     <ResourceCompile Include="LVGL.Simulator.rc" /> | ||||||
|  |  | ||||||
|  | @ -5,6 +5,17 @@ | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClInclude Include="lv_conf.h" /> |     <ClInclude Include="lv_conf.h" /> | ||||||
|     <ClInclude Include="lv_drv_conf.h" /> |     <ClInclude Include="lv_drv_conf.h" /> | ||||||
|  |     <ClInclude Include="HardwareSimulator.hpp" /> | ||||||
|  |     <ClInclude Include="..\..\Platformio\include\OmoteUI\HardwareAbstractionInterface.h"> | ||||||
|  |       <Filter>OmoteUI</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="..\..\Platformio\include\OmoteUI\OmoteUI.hpp"> | ||||||
|  |       <Filter>OmoteUI</Filter> | ||||||
|  |     </ClInclude> | ||||||
|  |     <ClInclude Include="omoteconfig.h" /> | ||||||
|  |     <ClInclude Include="..\..\Platformio\include\OmoteUI\Images.hpp"> | ||||||
|  |       <Filter>OmoteUI</Filter> | ||||||
|  |     </ClInclude> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <Manifest Include="LVGL.Simulator.manifest" /> |     <Manifest Include="LVGL.Simulator.manifest" /> | ||||||
|  | @ -15,6 +26,13 @@ | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ClCompile Include="LVGL.Simulator.cpp" /> |     <ClCompile Include="LVGL.Simulator.cpp" /> | ||||||
|  |     <ClCompile Include="HardwareSimulator.cpp" /> | ||||||
|  |     <ClCompile Include="..\..\Platformio\src\HardwareAbstractionInterface.cpp"> | ||||||
|  |       <Filter>OmoteUI</Filter> | ||||||
|  |     </ClCompile> | ||||||
|  |     <ClCompile Include="..\..\Platformio\src\OmoteUI.cpp"> | ||||||
|  |       <Filter>OmoteUI</Filter> | ||||||
|  |     </ClCompile> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <ResourceCompile Include="LVGL.Simulator.rc" /> |     <ResourceCompile Include="LVGL.Simulator.rc" /> | ||||||
|  | @ -25,4 +43,9 @@ | ||||||
|   <ItemGroup> |   <ItemGroup> | ||||||
|     <None Include="freetype.props" /> |     <None Include="freetype.props" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|  |   <ItemGroup> | ||||||
|  |     <Filter Include="OmoteUI"> | ||||||
|  |       <UniqueIdentifier>{0b1f99aa-73cb-482d-9d62-20e17f93b890}</UniqueIdentifier> | ||||||
|  |     </Filter> | ||||||
|  |   </ItemGroup> | ||||||
| </Project> | </Project> | ||||||
							
								
								
									
										6
									
								
								LVGL Simulator/LVGL.Simulator/omoteconfig.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								LVGL Simulator/LVGL.Simulator/omoteconfig.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,6 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #define IS_SIMULATOR true | ||||||
|  | 
 | ||||||
|  | #define SCREEN_WIDTH 240 | ||||||
|  | #define SCREEN_HEIGHT 360 | ||||||
							
								
								
									
										54
									
								
								Platformio/.vscode/settings.json
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										54
									
								
								Platformio/.vscode/settings.json
									
										
									
									
										vendored
									
									
								
							|  | @ -2,7 +2,57 @@ | ||||||
|     "cmake.configureOnOpen": false, |     "cmake.configureOnOpen": false, | ||||||
|     "files.associations": { |     "files.associations": { | ||||||
|         "random": "cpp", |         "random": "cpp", | ||||||
|         "array": "cpp" |         "array": "cpp", | ||||||
|  |         "atomic": "cpp", | ||||||
|  |         "*.tcc": "cpp", | ||||||
|  |         "cctype": "cpp", | ||||||
|  |         "clocale": "cpp", | ||||||
|  |         "cmath": "cpp", | ||||||
|  |         "cstdarg": "cpp", | ||||||
|  |         "cstddef": "cpp", | ||||||
|  |         "cstdint": "cpp", | ||||||
|  |         "cstdio": "cpp", | ||||||
|  |         "cstdlib": "cpp", | ||||||
|  |         "cstring": "cpp", | ||||||
|  |         "ctime": "cpp", | ||||||
|  |         "cwchar": "cpp", | ||||||
|  |         "cwctype": "cpp", | ||||||
|  |         "deque": "cpp", | ||||||
|  |         "unordered_map": "cpp", | ||||||
|  |         "unordered_set": "cpp", | ||||||
|  |         "vector": "cpp", | ||||||
|  |         "exception": "cpp", | ||||||
|  |         "algorithm": "cpp", | ||||||
|  |         "functional": "cpp", | ||||||
|  |         "iterator": "cpp", | ||||||
|  |         "map": "cpp", | ||||||
|  |         "memory": "cpp", | ||||||
|  |         "memory_resource": "cpp", | ||||||
|  |         "numeric": "cpp", | ||||||
|  |         "optional": "cpp", | ||||||
|  |         "set": "cpp", | ||||||
|  |         "string": "cpp", | ||||||
|  |         "string_view": "cpp", | ||||||
|  |         "system_error": "cpp", | ||||||
|  |         "tuple": "cpp", | ||||||
|  |         "type_traits": "cpp", | ||||||
|  |         "utility": "cpp", | ||||||
|  |         "fstream": "cpp", | ||||||
|  |         "initializer_list": "cpp", | ||||||
|  |         "iomanip": "cpp", | ||||||
|  |         "iosfwd": "cpp", | ||||||
|  |         "iostream": "cpp", | ||||||
|  |         "istream": "cpp", | ||||||
|  |         "limits": "cpp", | ||||||
|  |         "new": "cpp", | ||||||
|  |         "ostream": "cpp", | ||||||
|  |         "sstream": "cpp", | ||||||
|  |         "stdexcept": "cpp", | ||||||
|  |         "streambuf": "cpp", | ||||||
|  |         "cinttypes": "cpp", | ||||||
|  |         "typeinfo": "cpp" | ||||||
|     }, |     }, | ||||||
|     "cmake.sourceDirectory": "${workspaceFolder}/.pio/libdeps/esp32/Adafruit BusIO" |     "cmake.sourceDirectory": "${workspaceFolder}/.pio/libdeps/esp32/Adafruit BusIO", | ||||||
|  |     "editor.formatOnSave": false, | ||||||
|  |     "idf.portWin": "COM8" | ||||||
| } | } | ||||||
							
								
								
									
										16
									
								
								Platformio/include/OmoteUI/HardwareAbstractionInterface.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								Platformio/include/OmoteUI/HardwareAbstractionInterface.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | ||||||
|  | // OMOTE Hardware Abstraction
 | ||||||
|  | // 2023 Matthew Colvin
 | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | #include <lvgl.h> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | class HardwareAbstractionInterface { | ||||||
|  | public: | ||||||
|  |   HardwareAbstractionInterface() = default; | ||||||
|  | 
 | ||||||
|  |   virtual void init() = 0; | ||||||
|  |   virtual void sendIR() = 0; | ||||||
|  |   virtual void MQTTPublish(const char *topic, const char *payload) = 0; | ||||||
|  |   virtual void debugPrint(std::string message) = 0; | ||||||
|  | }; | ||||||
							
								
								
									
										1020
									
								
								Platformio/include/OmoteUI/Images.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1020
									
								
								Platformio/include/OmoteUI/Images.hpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										68
									
								
								Platformio/include/OmoteUI/OmoteUI.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								Platformio/include/OmoteUI/OmoteUI.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,68 @@ | ||||||
|  | // OMOTE UI
 | ||||||
|  | // 2023 Matthew Colvin
 | ||||||
|  | #pragma once | ||||||
|  | #define LV_CONF_INCLUDE_SIMPLE | ||||||
|  | 
 | ||||||
|  | #include "HardwareAbstractionInterface.h" | ||||||
|  | #include "lvgl.h" | ||||||
|  | #include "Images.hpp" | ||||||
|  | #include <algorithm> | ||||||
|  | #include <memory> | ||||||
|  | #include <stdio.h> | ||||||
|  | #include <string> | ||||||
|  | 
 | ||||||
|  | /// @brief Singleton to allow UI code to live separately from the Initialization
 | ||||||
|  | /// of resources.
 | ||||||
|  | class OmoteUI { | ||||||
|  | public: | ||||||
|  |   OmoteUI(std::shared_ptr<HardwareAbstractionInterface> aHardware) | ||||||
|  |       : mHardware(aHardware) {}; | ||||||
|  | 
 | ||||||
|  |   static std::weak_ptr<OmoteUI> getRefrence() { return getInstance(); }; | ||||||
|  |   static std::shared_ptr<OmoteUI> getInstance( | ||||||
|  |       std::shared_ptr<HardwareAbstractionInterface> aHardware = nullptr) { | ||||||
|  |     if (mInstance) { | ||||||
|  |       return mInstance; | ||||||
|  |     } else if (aHardware) { | ||||||
|  |       mInstance = std::make_shared<OmoteUI>(aHardware); | ||||||
|  |     } | ||||||
|  |     return mInstance; | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   // Set the page indicator scroll position relative to the tabview scroll
 | ||||||
|  |   // position
 | ||||||
|  |   void store_scroll_value_event_cb(lv_event_t *e); | ||||||
|  |   // Update current device when the tabview page is changes
 | ||||||
|  |   void tabview_device_event_cb(lv_event_t *e); | ||||||
|  |   // Slider Event handler
 | ||||||
|  |   void bl_slider_event_cb(lv_event_t *e); | ||||||
|  |   // Apple Key Event handler
 | ||||||
|  |   void appleKey_event_cb(lv_event_t *e); | ||||||
|  |   // Wakeup by IMU Switch Event handler
 | ||||||
|  |   void WakeEnableSetting_event_cb(lv_event_t *e); | ||||||
|  |   // Smart Home Toggle Event handler
 | ||||||
|  |   void smartHomeToggle_event_cb(lv_event_t *e); | ||||||
|  |   // Smart Home Toggle Event handler
 | ||||||
|  |   void smartHomeSlider_event_cb(lv_event_t *e); | ||||||
|  |   // Virtual Keypad Event handler
 | ||||||
|  |   void virtualKeypad_event_cb(lv_event_t *e); | ||||||
|  | 
 | ||||||
|  |   // Use LVGL to layout the ui and register the callbacks
 | ||||||
|  |   void layout_UI(); | ||||||
|  | 
 | ||||||
|  |   void loopHandler(); | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  |   static std::shared_ptr<OmoteUI> mInstance; | ||||||
|  |   std::shared_ptr<HardwareAbstractionInterface> mHardware; | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *panel = nullptr; | ||||||
|  |   Images imgs = Images(); | ||||||
|  |   uint_fast8_t currentDevice = 4; | ||||||
|  |   int backlight_brightness = 255; | ||||||
|  |   lv_color_t color_primary = lv_color_hex(0x303030); // gray
 | ||||||
|  |   bool wakeupByIMUEnabled = true; | ||||||
|  |    | ||||||
|  |   inline static const uint_fast8_t virtualKeyMapTechnisat[10] = { | ||||||
|  |       0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0x0}; | ||||||
|  | }; | ||||||
							
								
								
									
										55
									
								
								Platformio/include/omoteconfig.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								Platformio/include/omoteconfig.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #define IS_SIMULATOR false | ||||||
|  | 
 | ||||||
|  | // Comment out to disable connected features
 | ||||||
|  | #define ENABLE_WIFI | ||||||
|  | #define WIFI_SSID "YOUR_WIFI_SSID" | ||||||
|  | #define WIFI_PASSWORD "YOUR_WIFI_PASSWORD" | ||||||
|  | #define MQTT_SERVER "YOUR_MQTT_SERVER_IP" | ||||||
|  | 
 | ||||||
|  | // time until device enters sleep mode in milliseconds
 | ||||||
|  | #define SLEEP_TIMEOUT 20000 | ||||||
|  | 
 | ||||||
|  | // motion above threshold keeps device awake
 | ||||||
|  | #define MOTION_THRESHOLD 50 | ||||||
|  | 
 | ||||||
|  | // IO34+IO35+IO37+IO38+IO39(+IO13)
 | ||||||
|  | #define BUTTON_PIN_BITMASK 0b1110110000000000000000000010000000000000 | ||||||
|  | 
 | ||||||
|  | #define SCREEN_WIDTH 240 | ||||||
|  | #define SCREEN_HEIGHT 360 | ||||||
|  | 
 | ||||||
|  | // Pin assignment
 | ||||||
|  | // -----------------------------------------------------------------------------------------------------------------------
 | ||||||
|  | 
 | ||||||
|  | #define LCD_DC 9 // defined in TFT_eSPI User_Setup.h
 | ||||||
|  | #define LCD_CS 5 | ||||||
|  | #define LCD_MOSI 23 | ||||||
|  | #define LCD_SCK 18 | ||||||
|  | #define LCD_BL 4 | ||||||
|  | #define LCD_EN 10 | ||||||
|  | 
 | ||||||
|  | #define USER_LED 2 | ||||||
|  | 
 | ||||||
|  | #define SW_1 32 // 1...5: Output
 | ||||||
|  | #define SW_2 26 | ||||||
|  | #define SW_3 27 | ||||||
|  | #define SW_4 14 | ||||||
|  | #define SW_5 12 | ||||||
|  | #define SW_A 37 // A...E: Input
 | ||||||
|  | #define SW_B 38 | ||||||
|  | #define SW_C 39 | ||||||
|  | #define SW_D 34 | ||||||
|  | #define SW_E 35 | ||||||
|  | 
 | ||||||
|  | #define IR_RX 15   // IR receiver input
 | ||||||
|  | #define ADC_BAT 36 // Battery voltage sense input (1/2 divider)
 | ||||||
|  | #define IR_VCC 25  // IR receiver power
 | ||||||
|  | #define IR_LED 33  // IR LED output
 | ||||||
|  | 
 | ||||||
|  | #define SCL 22 | ||||||
|  | #define SDA 19 | ||||||
|  | #define ACC_INT 20 | ||||||
|  | 
 | ||||||
|  | #define CRG_STAT 21 // battery charger feedback
 | ||||||
|  | @ -24,8 +24,12 @@ lib_deps = | ||||||
| 	bodmer/TFT_eSPI@^2.5.23 | 	bodmer/TFT_eSPI@^2.5.23 | ||||||
| 	knolleary/PubSubClient@^2.8 | 	knolleary/PubSubClient@^2.8 | ||||||
| build_flags =  | build_flags =  | ||||||
|  | 	-std=c++17 | ||||||
|  | 	-std=gnu++17 | ||||||
| 	-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG | 	-D CORE_DEBUG_LEVEL=ARDUHAL_LOG_LEVEL_DEBUG | ||||||
| 	-I include ; Include the folder containing lv_conf.h | 	-I include | ||||||
|  | 	-I include/OmoteUI | ||||||
|  | 	 ; Include the folder containing lv_conf.h | ||||||
| 	; The following lines replace the TFT_eSPI User_setup.h-file | 	; The following lines replace the TFT_eSPI User_setup.h-file | ||||||
| 	-D USER_SETUP_LOADED=1 | 	-D USER_SETUP_LOADED=1 | ||||||
| 	-D ILI9341_DRIVER=1 | 	-D ILI9341_DRIVER=1 | ||||||
|  | @ -47,3 +51,5 @@ build_flags = | ||||||
| 	;-D LOAD_FONT8=1 | 	;-D LOAD_FONT8=1 | ||||||
| 	;-D LOAD_GFXFF=1 | 	;-D LOAD_GFXFF=1 | ||||||
| 	;-D SMOOTH_FONT=1 | 	;-D SMOOTH_FONT=1 | ||||||
|  | build_unflags = | ||||||
|  |     -std=gnu++11 | ||||||
							
								
								
									
										1
									
								
								Platformio/src/HardwareAbstractionInterface.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								Platformio/src/HardwareAbstractionInterface.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1 @@ | ||||||
|  | #include "HardwareAbstractionInterface.h" | ||||||
							
								
								
									
										507
									
								
								Platformio/src/HardwareRevX.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										507
									
								
								Platformio/src/HardwareRevX.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,507 @@ | ||||||
|  | #include "HardwareRevX.hpp" | ||||||
|  | #include "driver/ledc.h" | ||||||
|  | 
 | ||||||
|  | std::shared_ptr<HardwareRevX> HardwareRevX::mInstance = nullptr; | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::initIO() { | ||||||
|  |   // Button Pin Definition
 | ||||||
|  |   pinMode(SW_1, OUTPUT); | ||||||
|  |   pinMode(SW_2, OUTPUT); | ||||||
|  |   pinMode(SW_3, OUTPUT); | ||||||
|  |   pinMode(SW_4, OUTPUT); | ||||||
|  |   pinMode(SW_5, OUTPUT); | ||||||
|  |   pinMode(SW_A, INPUT); | ||||||
|  |   pinMode(SW_B, INPUT); | ||||||
|  |   pinMode(SW_C, INPUT); | ||||||
|  |   pinMode(SW_D, INPUT); | ||||||
|  |   pinMode(SW_E, INPUT); | ||||||
|  | 
 | ||||||
|  |   // Power Pin Definition
 | ||||||
|  |   pinMode(CRG_STAT, INPUT_PULLUP); | ||||||
|  |   pinMode(ADC_BAT, INPUT); | ||||||
|  | 
 | ||||||
|  |   // IR Pin Definition
 | ||||||
|  |   pinMode(IR_RX, INPUT); | ||||||
|  |   pinMode(IR_LED, OUTPUT); | ||||||
|  |   pinMode(IR_VCC, OUTPUT); | ||||||
|  |   digitalWrite(IR_LED, HIGH); // HIGH off - LOW on
 | ||||||
|  |   digitalWrite(IR_VCC, LOW);  // HIGH on - LOW off
 | ||||||
|  | 
 | ||||||
|  |   // LCD Pin Definition
 | ||||||
|  |   pinMode(LCD_EN, OUTPUT); | ||||||
|  |   digitalWrite(LCD_EN, HIGH); | ||||||
|  |   pinMode(LCD_BL, OUTPUT); | ||||||
|  |   digitalWrite(LCD_BL, HIGH); | ||||||
|  | 
 | ||||||
|  |   // Other Pin Definition
 | ||||||
|  |   pinMode(ACC_INT, INPUT); | ||||||
|  |   pinMode(USER_LED, OUTPUT); | ||||||
|  |   digitalWrite(USER_LED, LOW); | ||||||
|  | 
 | ||||||
|  |   // Release GPIO hold in case we are coming out of standby
 | ||||||
|  |   gpio_hold_dis((gpio_num_t)SW_1); | ||||||
|  |   gpio_hold_dis((gpio_num_t)SW_2); | ||||||
|  |   gpio_hold_dis((gpio_num_t)SW_3); | ||||||
|  |   gpio_hold_dis((gpio_num_t)SW_4); | ||||||
|  |   gpio_hold_dis((gpio_num_t)SW_5); | ||||||
|  |   gpio_hold_dis((gpio_num_t)LCD_EN); | ||||||
|  |   gpio_hold_dis((gpio_num_t)LCD_BL); | ||||||
|  |   gpio_deep_sleep_hold_dis(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | HardwareRevX::WakeReason getWakeReason() { | ||||||
|  |   // Find out wakeup cause
 | ||||||
|  |   if (esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_EXT1) { | ||||||
|  |     if (log(esp_sleep_get_ext1_wakeup_status()) / log(2) == 13) | ||||||
|  |       return HardwareRevX::WakeReason::IMU; | ||||||
|  |     else | ||||||
|  |       return HardwareRevX::WakeReason::KEYPAD; | ||||||
|  |   } else { | ||||||
|  |     return HardwareRevX::WakeReason::RESET; | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::init() { | ||||||
|  |   // Make sure ESP32 is running at full speed
 | ||||||
|  |   setCpuFrequencyMhz(240); | ||||||
|  | 
 | ||||||
|  |   wakeup_reason = getWakeReason(); | ||||||
|  |   initIO(); | ||||||
|  |   setupBacklight(); | ||||||
|  |   Serial.begin(115200); | ||||||
|  |   restorePreferences(); | ||||||
|  |   slowDisplayWakeup(); | ||||||
|  |   setupTFT(); | ||||||
|  |   setupTouchScreen(); | ||||||
|  |   initLVGL(); | ||||||
|  |   setupWifi(); | ||||||
|  |   setupIMU(); | ||||||
|  |   setupIR(); | ||||||
|  | 
 | ||||||
|  |   debugPrint(std::string("Finished Hardware Setup in %d",millis())); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::debugPrint(std::string aDebugMessage){ | ||||||
|  |   Serial.print(aDebugMessage.c_str()); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::sendIR(){ | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::MQTTPublish(const char *topic, const char *payload){ | ||||||
|  | 
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::initLVGL() { | ||||||
|  |   lv_init(); | ||||||
|  | 
 | ||||||
|  |   lv_disp_draw_buf_init(&mdraw_buf, mbufA, mbufB, | ||||||
|  |                         SCREEN_WIDTH * SCREEN_HEIGHT / 10); | ||||||
|  | 
 | ||||||
|  |   // Initialize the display driver
 | ||||||
|  |   static lv_disp_drv_t disp_drv; | ||||||
|  |   lv_disp_drv_init(&disp_drv); | ||||||
|  |   disp_drv.hor_res = SCREEN_WIDTH; | ||||||
|  |   disp_drv.ver_res = SCREEN_HEIGHT; | ||||||
|  |   disp_drv.flush_cb = &HardwareRevX::displayFlushImpl; | ||||||
|  |   disp_drv.draw_buf = &mdraw_buf; | ||||||
|  |   lv_disp_drv_register(&disp_drv); | ||||||
|  | 
 | ||||||
|  |   // Initialize the touchscreen driver
 | ||||||
|  |   static lv_indev_drv_t indev_drv; | ||||||
|  |   lv_indev_drv_init(&indev_drv); | ||||||
|  |   indev_drv.type = LV_INDEV_TYPE_POINTER; | ||||||
|  |   indev_drv.read_cb = &HardwareRevX::touchPadReadImpl; | ||||||
|  |   lv_indev_drv_register(&indev_drv); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::handleDisplayFlush(lv_disp_drv_t *disp, const lv_area_t *area, | ||||||
|  |                                 lv_color_t *color_p) { | ||||||
|  |   uint32_t w = (area->x2 - area->x1 + 1); | ||||||
|  |   uint32_t h = (area->y2 - area->y1 + 1); | ||||||
|  | 
 | ||||||
|  |   tft.startWrite(); | ||||||
|  |   tft.setAddrWindow(area->x1, area->y1, w, h); | ||||||
|  |   tft.pushPixelsDMA((uint16_t *)&color_p->full, w * h); | ||||||
|  |   tft.endWrite(); | ||||||
|  | 
 | ||||||
|  |   lv_disp_flush_ready(disp); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::handleTouchPadRead(lv_indev_drv_t *indev_driver, | ||||||
|  |                                 lv_indev_data_t *data) { | ||||||
|  |   // int16_t touchX, touchY;
 | ||||||
|  |   touchPoint = touch.getPoint(); | ||||||
|  |   int16_t touchX = touchPoint.x; | ||||||
|  |   int16_t touchY = touchPoint.y; | ||||||
|  |   bool touched = false; | ||||||
|  |   if ((touchX > 0) || (touchY > 0)) { | ||||||
|  |     touched = true; | ||||||
|  |     standbyTimer = SLEEP_TIMEOUT; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!touched) { | ||||||
|  |     data->state = LV_INDEV_STATE_REL; | ||||||
|  |   } else { | ||||||
|  |     data->state = LV_INDEV_STATE_PR; | ||||||
|  | 
 | ||||||
|  |     // Set the coordinates
 | ||||||
|  |     data->point.x = SCREEN_WIDTH - touchX; | ||||||
|  |     data->point.y = SCREEN_HEIGHT - touchY; | ||||||
|  | 
 | ||||||
|  |     // Serial.print( "touchpoint: x" );
 | ||||||
|  |     // Serial.print( touchX );
 | ||||||
|  |     // Serial.print( " y" );
 | ||||||
|  |     // Serial.println( touchY );
 | ||||||
|  |     // tft.drawFastHLine(0, screenHeight - touchY, screenWidth, TFT_RED);
 | ||||||
|  |     // tft.drawFastVLine(screenWidth - touchX, 0, screenHeight, TFT_RED);
 | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::activityDetection() { | ||||||
|  |   static int accXold; | ||||||
|  |   static int accYold; | ||||||
|  |   static int accZold; | ||||||
|  |   int accX = IMU.readFloatAccelX() * 1000; | ||||||
|  |   int accY = IMU.readFloatAccelY() * 1000; | ||||||
|  |   int accZ = IMU.readFloatAccelZ() * 1000; | ||||||
|  | 
 | ||||||
|  |   // determine motion value as da/dt
 | ||||||
|  |   motion = (abs(accXold - accX) + abs(accYold - accY) + abs(accZold - accZ)); | ||||||
|  |   // Calculate time to standby
 | ||||||
|  |   standbyTimer -= 100; | ||||||
|  |   if (standbyTimer < 0) | ||||||
|  |     standbyTimer = 0; | ||||||
|  |   // If the motion exceeds the threshold, the standbyTimer is reset
 | ||||||
|  |   if (motion > MOTION_THRESHOLD) | ||||||
|  |     standbyTimer = SLEEP_TIMEOUT; | ||||||
|  | 
 | ||||||
|  |   // Store the current acceleration and time
 | ||||||
|  |   accXold = accX; | ||||||
|  |   accYold = accY; | ||||||
|  |   accZold = accZ; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::enterSleep() { | ||||||
|  |   // Save settings to internal flash memory
 | ||||||
|  |   preferences.putBool("wkpByIMU", wakeupByIMUEnabled); | ||||||
|  |   preferences.putUChar("blBrightness", backlight_brightness); | ||||||
|  |   preferences.putUChar("currentDevice", currentDevice); | ||||||
|  |   if (!preferences.getBool("alreadySetUp")) | ||||||
|  |     preferences.putBool("alreadySetUp", true); | ||||||
|  |   preferences.end(); | ||||||
|  | 
 | ||||||
|  |   // Configure IMU
 | ||||||
|  |   uint8_t intDataRead; | ||||||
|  |   IMU.readRegister(&intDataRead, LIS3DH_INT1_SRC); // clear interrupt
 | ||||||
|  |   configIMUInterrupts(); | ||||||
|  |   IMU.readRegister(&intDataRead, | ||||||
|  |                    LIS3DH_INT1_SRC); // really clear interrupt
 | ||||||
|  | 
 | ||||||
|  | #ifdef ENABLE_WIFI | ||||||
|  |   // Power down modem
 | ||||||
|  |   WiFi.disconnect(); | ||||||
|  |   WiFi.mode(WIFI_OFF); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   // Prepare IO states
 | ||||||
|  |   digitalWrite(LCD_DC, LOW); // LCD control signals off
 | ||||||
|  |   digitalWrite(LCD_CS, LOW); | ||||||
|  |   digitalWrite(LCD_MOSI, LOW); | ||||||
|  |   digitalWrite(LCD_SCK, LOW); | ||||||
|  |   digitalWrite(LCD_EN, HIGH); // LCD logic off
 | ||||||
|  |   digitalWrite(LCD_BL, HIGH); // LCD backlight off
 | ||||||
|  |   pinMode(CRG_STAT, INPUT);   // Disable Pull-Up
 | ||||||
|  |   digitalWrite(IR_VCC, LOW);  // IR Receiver off
 | ||||||
|  | 
 | ||||||
|  |   // Configure button matrix for ext1 interrupt
 | ||||||
|  |   pinMode(SW_1, OUTPUT); | ||||||
|  |   pinMode(SW_2, OUTPUT); | ||||||
|  |   pinMode(SW_3, OUTPUT); | ||||||
|  |   pinMode(SW_4, OUTPUT); | ||||||
|  |   pinMode(SW_5, OUTPUT); | ||||||
|  |   digitalWrite(SW_1, HIGH); | ||||||
|  |   digitalWrite(SW_2, HIGH); | ||||||
|  |   digitalWrite(SW_3, HIGH); | ||||||
|  |   digitalWrite(SW_4, HIGH); | ||||||
|  |   digitalWrite(SW_5, HIGH); | ||||||
|  |   gpio_hold_en((gpio_num_t)SW_1); | ||||||
|  |   gpio_hold_en((gpio_num_t)SW_2); | ||||||
|  |   gpio_hold_en((gpio_num_t)SW_3); | ||||||
|  |   gpio_hold_en((gpio_num_t)SW_4); | ||||||
|  |   gpio_hold_en((gpio_num_t)SW_5); | ||||||
|  |   // Force display pins to high impedance
 | ||||||
|  |   // Without this the display might not wake up from sleep
 | ||||||
|  |   pinMode(LCD_BL, INPUT); | ||||||
|  |   pinMode(LCD_EN, INPUT); | ||||||
|  |   gpio_hold_en((gpio_num_t)LCD_BL); | ||||||
|  |   gpio_hold_en((gpio_num_t)LCD_EN); | ||||||
|  |   gpio_deep_sleep_hold_en(); | ||||||
|  | 
 | ||||||
|  |   esp_sleep_enable_ext1_wakeup(BUTTON_PIN_BITMASK, ESP_EXT1_WAKEUP_ANY_HIGH); | ||||||
|  | 
 | ||||||
|  |   delay(100); | ||||||
|  |   // Sleep
 | ||||||
|  |   esp_deep_sleep_start(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::configIMUInterrupts() { | ||||||
|  |   uint8_t dataToWrite = 0; | ||||||
|  | 
 | ||||||
|  |   // LIS3DH_INT1_CFG
 | ||||||
|  |   // dataToWrite |= 0x80;//AOI, 0 = OR 1 = AND
 | ||||||
|  |   // dataToWrite |= 0x40;//6D, 0 = interrupt source, 1 = 6 direction source
 | ||||||
|  |   // Set these to enable individual axes of generation source (or direction)
 | ||||||
|  |   //  -- high and low are used generically
 | ||||||
|  |   dataToWrite |= 0x20; // Z high
 | ||||||
|  |   // dataToWrite |= 0x10;//Z low
 | ||||||
|  |   dataToWrite |= 0x08; // Y high
 | ||||||
|  |   // dataToWrite |= 0x04;//Y low
 | ||||||
|  |   dataToWrite |= 0x02; // X high
 | ||||||
|  |   // dataToWrite |= 0x01;//X low
 | ||||||
|  |   if (wakeupByIMUEnabled) | ||||||
|  |     IMU.writeRegister(LIS3DH_INT1_CFG, 0b00101010); | ||||||
|  |   else | ||||||
|  |     IMU.writeRegister(LIS3DH_INT1_CFG, 0b00000000); | ||||||
|  | 
 | ||||||
|  |   // LIS3DH_INT1_THS
 | ||||||
|  |   dataToWrite = 0; | ||||||
|  |   // Provide 7 bit value, 0x7F always equals max range by accelRange setting
 | ||||||
|  |   dataToWrite |= 0x45; | ||||||
|  |   IMU.writeRegister(LIS3DH_INT1_THS, dataToWrite); | ||||||
|  | 
 | ||||||
|  |   // LIS3DH_INT1_DURATION
 | ||||||
|  |   dataToWrite = 0; | ||||||
|  |   // minimum duration of the interrupt
 | ||||||
|  |   // LSB equals 1/(sample rate)
 | ||||||
|  |   dataToWrite |= 0x00; // 1 * 1/50 s = 20ms
 | ||||||
|  |   IMU.writeRegister(LIS3DH_INT1_DURATION, dataToWrite); | ||||||
|  | 
 | ||||||
|  |   // LIS3DH_CTRL_REG5
 | ||||||
|  |   // Int1 latch interrupt and 4D on  int1 (preserve fifo en)
 | ||||||
|  |   IMU.readRegister(&dataToWrite, LIS3DH_CTRL_REG5); | ||||||
|  |   dataToWrite &= 0xF3; // Clear bits of interest
 | ||||||
|  |   dataToWrite |= 0x08; // Latch interrupt (Cleared by reading int1_src)
 | ||||||
|  |   // dataToWrite |= 0x04; //Pipe 4D detection from 6D recognition to int1?
 | ||||||
|  |   IMU.writeRegister(LIS3DH_CTRL_REG5, dataToWrite); | ||||||
|  | 
 | ||||||
|  |   // LIS3DH_CTRL_REG3
 | ||||||
|  |   // Choose source for pin 1
 | ||||||
|  |   dataToWrite = 0; | ||||||
|  |   // dataToWrite |= 0x80; //Click detect on pin 1
 | ||||||
|  |   dataToWrite |= 0x40; // AOI1 event (Generator 1 interrupt on pin 1)
 | ||||||
|  |   dataToWrite |= 0x20; // AOI2 event ()
 | ||||||
|  |   // dataToWrite |= 0x10; //Data ready
 | ||||||
|  |   // dataToWrite |= 0x04; //FIFO watermark
 | ||||||
|  |   // dataToWrite |= 0x02; //FIFO overrun
 | ||||||
|  |   IMU.writeRegister(LIS3DH_CTRL_REG3, dataToWrite); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::setupBacklight() { | ||||||
|  |   // Configure the backlight PWM
 | ||||||
|  |   // Manual setup because ledcSetup() briefly turns on the backlight
 | ||||||
|  |   ledc_channel_config_t ledc_channel_left; | ||||||
|  |   ledc_channel_left.gpio_num = (gpio_num_t)LCD_BL; | ||||||
|  |   ledc_channel_left.speed_mode = LEDC_HIGH_SPEED_MODE; | ||||||
|  |   ledc_channel_left.channel = LEDC_CHANNEL_5; | ||||||
|  |   ledc_channel_left.intr_type = LEDC_INTR_DISABLE; | ||||||
|  |   ledc_channel_left.timer_sel = LEDC_TIMER_1; | ||||||
|  |   ledc_channel_left.flags.output_invert = 1; // Can't do this with ledcSetup()
 | ||||||
|  |   ledc_channel_left.duty = 0; | ||||||
|  | 
 | ||||||
|  |   ledc_timer_config_t ledc_timer; | ||||||
|  |   ledc_timer.speed_mode = LEDC_HIGH_SPEED_MODE; | ||||||
|  |   ledc_timer.duty_resolution = LEDC_TIMER_8_BIT; | ||||||
|  |   ledc_timer.timer_num = LEDC_TIMER_1; | ||||||
|  |   ledc_timer.freq_hz = 640; | ||||||
|  | 
 | ||||||
|  |   ledc_channel_config(&ledc_channel_left); | ||||||
|  |   ledc_timer_config(&ledc_timer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::restorePreferences() { | ||||||
|  |   // Restore settings from internal flash memory
 | ||||||
|  |   preferences.begin("settings", false); | ||||||
|  |   if (preferences.getBool("alreadySetUp")) { | ||||||
|  |     wakeupByIMUEnabled = preferences.getBool("wkpByIMU"); | ||||||
|  |     backlight_brightness = preferences.getUChar("blBrightness"); | ||||||
|  |     currentDevice = preferences.getUChar("currentDevice"); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::setupTFT() { | ||||||
|  |   // Setup TFT
 | ||||||
|  |   tft.init(); | ||||||
|  |   tft.initDMA(); | ||||||
|  |   tft.setRotation(0); | ||||||
|  |   tft.fillScreen(TFT_BLACK); | ||||||
|  |   tft.setSwapBytes(true); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::setupTouchScreen() { | ||||||
|  |   // Configure i2c pins and set frequency to 400kHz
 | ||||||
|  |   Wire.begin(SDA, SCL, 400000); | ||||||
|  |   touch.begin(128); // Initialize touchscreen and set sensitivity threshold
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::setupIMU() { | ||||||
|  |   // Setup hal
 | ||||||
|  |   IMU.settings.accelSampleRate = | ||||||
|  |       50; // Hz.  Can be: 0,1,10,25,50,100,200,400,1600,5000 Hz
 | ||||||
|  |   IMU.settings.accelRange = 2; // Max G force readable.  Can be: 2, 4, 8, 16
 | ||||||
|  |   IMU.settings.adcEnabled = 0; | ||||||
|  |   IMU.settings.tempEnabled = 0; | ||||||
|  |   IMU.settings.xAccelEnabled = 1; | ||||||
|  |   IMU.settings.yAccelEnabled = 1; | ||||||
|  |   IMU.settings.zAccelEnabled = 1; | ||||||
|  |   IMU.begin(); | ||||||
|  |   uint8_t intDataRead; | ||||||
|  |   IMU.readRegister(&intDataRead, LIS3DH_INT1_SRC); // clear interrupt
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::slowDisplayWakeup() { | ||||||
|  |   // Slowly charge the VSW voltage to prevent a brownout
 | ||||||
|  |   // Workaround for hardware rev 1!
 | ||||||
|  |   for (int i = 0; i < 100; i++) { | ||||||
|  |     digitalWrite(LCD_EN, HIGH); // LCD Logic off
 | ||||||
|  |     delayMicroseconds(1); | ||||||
|  |     digitalWrite(LCD_EN, LOW); // LCD Logic on
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   delay(100); // Wait for the LCD driver to power on
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::handleWifiEvent(WiFiEvent_t event){ | ||||||
|  | #ifdef ENABLE_WIFI | ||||||
|  |   // Serial.printf("[WiFi-event] event: %d\n", event);
 | ||||||
|  |   if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP) { | ||||||
|  |     client.setServer(MQTT_SERVER, 1883); // MQTT initialization
 | ||||||
|  |     client.connect("OMOTE");             // Connect using a client id
 | ||||||
|  |   } | ||||||
|  |   // Set status bar icon based on WiFi status
 | ||||||
|  |   // TODO allow UI to register a Handler for these events
 | ||||||
|  | 
 | ||||||
|  |   //   if (event == ARDUINO_EVENT_WIFI_STA_GOT_IP ||
 | ||||||
|  |   //       event == ARDUINO_EVENT_WIFI_STA_GOT_IP6) {
 | ||||||
|  |   //     lv_label_set_text(WifiLabel, LV_SYMBOL_WIFI);
 | ||||||
|  |   //   } else {
 | ||||||
|  |   //     lv_label_set_text(WifiLabel, "");
 | ||||||
|  |   //   }
 | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  |   | ||||||
|  | void HardwareRevX::setupIR(){ | ||||||
|  |     // Setup IR
 | ||||||
|  |   IrSender.begin(); | ||||||
|  |   digitalWrite(IR_VCC, HIGH); // Turn on IR receiver
 | ||||||
|  |   IrReceiver.enableIRIn();    // Start the receiver
 | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::setupWifi(){ | ||||||
|  | #ifdef ENABLE_WIFI | ||||||
|  |   // Setup WiFi
 | ||||||
|  |   WiFi.setHostname("OMOTE"); // define hostname
 | ||||||
|  |   WiFi.onEvent(wiFiEventImpl); | ||||||
|  |   WiFi.begin(WIFI_SSID, WIFI_PASSWORD); | ||||||
|  |   WiFi.setSleep(true); | ||||||
|  | #endif | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::startTasks(){ | ||||||
|  |   if(xTaskCreate(&HardwareRevX::updateBatteryTask, | ||||||
|  |                  "Battery Percent Update",1024,nullptr,5,&batteryUpdateTskHndl) != pdPASS){ | ||||||
|  |     debugPrint("ERROR Could not Create Battery Update Task!"); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::updateBatteryTask([[maybe_unused]] void* aData){ | ||||||
|  |   while(true){ | ||||||
|  |     mInstance->battery_voltage = | ||||||
|  |         analogRead(ADC_BAT) * 2 * 3300 / 4095 + 350; // 350mV ADC offset
 | ||||||
|  |     mInstance->battery_percentage = | ||||||
|  |         constrain(map(mInstance->battery_voltage, 3700, 4200, 0, 100), 0, 100); | ||||||
|  |     mInstance->battery_ischarging = !digitalRead(CRG_STAT); | ||||||
|  |     // Check if battery is charging, fully charged or disconnected
 | ||||||
|  |     vTaskDelay(1000/ portTICK_PERIOD_MS); | ||||||
|  |     // Update battery at 1Hz
 | ||||||
|  |   } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void HardwareRevX::loopHandler(){ | ||||||
|  |     // Update Backlight brightness
 | ||||||
|  |   static int fadeInTimer = millis(); // fadeInTimer = time after setup
 | ||||||
|  |   if (millis() < | ||||||
|  |       fadeInTimer + | ||||||
|  |           backlight_brightness) { // Fade in the backlight brightness
 | ||||||
|  |     ledcWrite(5, millis() - fadeInTimer); | ||||||
|  |   } else { // Dim Backlight before entering standby
 | ||||||
|  |     if (standbyTimer < 2000) | ||||||
|  |       ledcWrite(5, 85); // Backlight dim
 | ||||||
|  |     else | ||||||
|  |       ledcWrite(5, backlight_brightness); // Backlight on
 | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // Blink debug LED at 1 Hz
 | ||||||
|  |   digitalWrite(USER_LED, millis() % 1000 > 500); | ||||||
|  | 
 | ||||||
|  |   // Refresh IMU data at 10Hz
 | ||||||
|  |   static unsigned long IMUTaskTimer = millis(); | ||||||
|  |   if (millis() - IMUTaskTimer >= 100) { | ||||||
|  |     activityDetection(); | ||||||
|  |     if (standbyTimer == 0) { | ||||||
|  |       Serial.println("Entering Sleep Mode. Goodbye."); | ||||||
|  |       enterSleep(); | ||||||
|  |     } | ||||||
|  |     IMUTaskTimer = millis(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   // TODO Convert to free RTOS task
 | ||||||
|  | 
 | ||||||
|  |   // TODO Create batter change notification for UI
 | ||||||
|  |    | ||||||
|  |   //   if (battery_ischarging || (!battery_ischarging && battery_voltage > 4350)) {
 | ||||||
|  |   //     lv_label_set_text(objBattPercentage, "");
 | ||||||
|  |   //     lv_label_set_text(objBattIcon, LV_SYMBOL_USB);
 | ||||||
|  |   //   } else {
 | ||||||
|  |   //     // Update status bar battery indicator
 | ||||||
|  |   //     // lv_label_set_text_fmt(objBattPercentage, "%d%%", battery_percentage);
 | ||||||
|  |   //     if (battery_percentage > 95)
 | ||||||
|  |   //       lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_FULL);
 | ||||||
|  |   //     else if (battery_percentage > 75)
 | ||||||
|  |   //       lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_3);
 | ||||||
|  |   //     else if (battery_percentage > 50)
 | ||||||
|  |   //       lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_2);
 | ||||||
|  |   //     else if (battery_percentage > 25)
 | ||||||
|  |   //       lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_1);
 | ||||||
|  |   //     else
 | ||||||
|  |   //       lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_EMPTY);
 | ||||||
|  |   //   }
 | ||||||
|  |   // }
 | ||||||
|  | 
 | ||||||
|  |   // Keypad Handling
 | ||||||
|  |   customKeypad.getKey(); // Populate key list
 | ||||||
|  |   for (int i = 0; i < LIST_MAX; i++) { // Handle multiple keys (Not really necessary in this case)
 | ||||||
|  |     if (customKeypad.key[i].kstate == PRESSED || | ||||||
|  |         customKeypad.key[i].kstate == HOLD) { | ||||||
|  |       standbyTimer = | ||||||
|  |           SLEEP_TIMEOUT; // Reset the sleep timer when a button is pressed
 | ||||||
|  |       int keyCode = customKeypad.key[i].kcode; | ||||||
|  |       Serial.println(customKeypad.key[i].kchar); | ||||||
|  |       // Send IR codes depending on the current device (tabview page)
 | ||||||
|  |       if (currentDevice == 1){ | ||||||
|  |         IrSender.sendRC5(IrSender.encodeRC5X(0x00, keyMapTechnisat[keyCode / ROWS][keyCode % ROWS])); | ||||||
|  |       } | ||||||
|  |       else if (currentDevice == 2){ | ||||||
|  |         IrSender.sendSony((keyCode / ROWS) * (keyCode % ROWS), 15); | ||||||
|  |       } | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   // IR Test
 | ||||||
|  |   // tft.drawString("IR Command: ", 10, 90, 1);
 | ||||||
|  |   // decode_results results;
 | ||||||
|  |   // if (IrReceiver.decode(&results)) {
 | ||||||
|  |   // IrReceiver.resume(); // Enable receiving of the next value
 | ||||||
|  |   //}  //tft.drawString(String(results.command) + "        ", 80, 90, 1);
 | ||||||
|  |   // 
 | ||||||
|  | } | ||||||
							
								
								
									
										155
									
								
								Platformio/src/HardwareRevX.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										155
									
								
								Platformio/src/HardwareRevX.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,155 @@ | ||||||
|  | #pragma once | ||||||
|  | #include "SparkFunLIS3DH.h" | ||||||
|  | 
 | ||||||
|  | #include "HardwareAbstractionInterface.h" | ||||||
|  | #include "WiFi.h" | ||||||
|  | #include "Wire.h" | ||||||
|  | #include "lvgl.h" | ||||||
|  | #include <Adafruit_FT6206.h> | ||||||
|  | #include <IRrecv.h> | ||||||
|  | #include <IRremoteESP8266.h> | ||||||
|  | #include <IRsend.h> | ||||||
|  | #include <IRutils.h> | ||||||
|  | #include <PubSubClient.h> | ||||||
|  | #include <Preferences.h> | ||||||
|  | #include <TFT_eSPI.h> // Hardware-specific library
 | ||||||
|  | #include <Keypad.h> // modified for inverted logic
 | ||||||
|  | #include <functional> | ||||||
|  | #include <memory> | ||||||
|  | 
 | ||||||
|  | #include "omoteconfig.h" | ||||||
|  | 
 | ||||||
|  | class HardwareRevX : public HardwareAbstractionInterface { | ||||||
|  | public: | ||||||
|  |   enum class WakeReason { RESET, IMU, KEYPAD }; | ||||||
|  | 
 | ||||||
|  |   static std::shared_ptr<HardwareRevX> getInstance() { | ||||||
|  |     if (!mInstance) { | ||||||
|  |       mInstance = std::make_shared<HardwareRevX>(); | ||||||
|  |     } | ||||||
|  |     return mInstance; | ||||||
|  |   } | ||||||
|  |   static std::weak_ptr<HardwareRevX> getRefrence(){ | ||||||
|  |     return getInstance(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   HardwareRevX() : HardwareAbstractionInterface(){}; | ||||||
|  |   // HardwareAbstractionInterface 
 | ||||||
|  |   virtual void init() override; | ||||||
|  |   virtual void sendIR() override; | ||||||
|  |   virtual void MQTTPublish(const char *topic, const char *payload) override; | ||||||
|  |   virtual void debugPrint(std::string aDebugMessage) override; | ||||||
|  |    | ||||||
|  |   void loopHandler(); | ||||||
|  | 
 | ||||||
|  | protected: | ||||||
|  |   // Init Functions to setup hardware
 | ||||||
|  |   void initIO(); | ||||||
|  |   void setupBacklight(); | ||||||
|  |   void restorePreferences(); | ||||||
|  |   void slowDisplayWakeup(); | ||||||
|  |   void setupTFT(); | ||||||
|  |   void setupTouchScreen(); | ||||||
|  |   void initLVGL(); | ||||||
|  |   void setupIMU(); | ||||||
|  |   void setupIR(); | ||||||
|  |   void setupWifi(); | ||||||
|  | 
 | ||||||
|  |   void activityDetection(); | ||||||
|  |   void enterSleep(); | ||||||
|  |   void configIMUInterrupts(); | ||||||
|  | 
 | ||||||
|  |   // UI/UX Handlers
 | ||||||
|  |   void handleDisplayFlush(lv_disp_drv_t *disp, const lv_area_t *area, | ||||||
|  |                     lv_color_t *color_p); | ||||||
|  |   void handleTouchPadRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data); | ||||||
|  | 
 | ||||||
|  |   void handleWifiEvent(WiFiEvent_t event); | ||||||
|  | 
 | ||||||
|  |   // Tasks
 | ||||||
|  |   void startTasks(); | ||||||
|  | 
 | ||||||
|  |   static void updateBatteryTask([[maybe_unused]] void* aData); | ||||||
|  |   TaskHandle_t batteryUpdateTskHndl = nullptr; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 
 | ||||||
|  |   // Static Wrappers Needed to Satisfy C APIs
 | ||||||
|  |   static void wiFiEventImpl(WiFiEvent_t event){ | ||||||
|  |     mInstance->handleWifiEvent(event); | ||||||
|  |   } | ||||||
|  |   static void displayFlushImpl(lv_disp_drv_t *disp, const lv_area_t *area, | ||||||
|  |                                lv_color_t *color_p) { | ||||||
|  |     mInstance->handleDisplayFlush(disp, area, color_p); | ||||||
|  |   } | ||||||
|  |   static void touchPadReadImpl(lv_indev_drv_t *indev_driver, | ||||||
|  |                                lv_indev_data_t *data) { | ||||||
|  |     mInstance->handleTouchPadRead(indev_driver, data); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  | #ifdef ENABLE_WIFI | ||||||
|  |   WiFiClient espClient; | ||||||
|  |   PubSubClient client = PubSubClient(espClient); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  |   Adafruit_FT6206 touch = Adafruit_FT6206(); | ||||||
|  |   TS_Point touchPoint; | ||||||
|  |   TS_Point oldPoint; | ||||||
|  | 
 | ||||||
|  |   TFT_eSPI tft = TFT_eSPI(); | ||||||
|  | 
 | ||||||
|  |   // IMU Motion Detection
 | ||||||
|  |   LIS3DH IMU = LIS3DH(I2C_MODE, 0x19); // Default constructor is I2C, addr 0x19.
 | ||||||
|  |   int standbyTimer = SLEEP_TIMEOUT; | ||||||
|  |   int motion = 0; | ||||||
|  |   WakeReason wakeup_reason; | ||||||
|  | 
 | ||||||
|  |   Preferences preferences; | ||||||
|  |   bool wakeupByIMUEnabled = true; | ||||||
|  |   int backlight_brightness = 255; | ||||||
|  |   byte currentDevice = 1; // Current Device to control (allows switching
 | ||||||
|  |                           // mappings between devices)
 | ||||||
|  | 
 | ||||||
|  |   // IR declarations
 | ||||||
|  |   IRsend IrSender = IRsend(IR_LED, true); | ||||||
|  |   IRrecv IrReceiver = IRrecv(IR_RX); | ||||||
|  | 
 | ||||||
|  |   int battery_voltage = 0; | ||||||
|  |   int battery_percentage = 100; | ||||||
|  |   bool battery_ischarging = false; | ||||||
|  | 
 | ||||||
|  |   // LVGL Screen Buffers
 | ||||||
|  |   lv_disp_draw_buf_t mdraw_buf; | ||||||
|  |   lv_color_t mbufA[SCREEN_WIDTH * SCREEN_HEIGHT / 10]; | ||||||
|  |   lv_color_t mbufB[SCREEN_WIDTH * SCREEN_HEIGHT / 10]; | ||||||
|  | 
 | ||||||
|  |   lv_color_t color_primary = lv_color_hex(0x303030); // gray
 | ||||||
|  | 
 | ||||||
|  |   // Keypad declarations
 | ||||||
|  |   static const byte ROWS = 5; // four rows
 | ||||||
|  |   static const byte COLS = 5; // four columns
 | ||||||
|  |   // define the symbols on the buttons of the keypads
 | ||||||
|  |   char hexaKeys[ROWS][COLS] = { | ||||||
|  |       {'s', '^', '-', 'm', 'r'}, //  source, channel+, Volume-,   mute, record
 | ||||||
|  |       {'i', 'r', '+', 'k', 'd'}, //    info,    right, Volume+,     OK,   down
 | ||||||
|  |       {'4', 'v', '1', '3', '2'}, //    blue, channel-,     red, yellow,  green
 | ||||||
|  |       {'>', 'o', 'b', 'u', 'l'}, // forward,      off,    back,     up,   left
 | ||||||
|  |       {'?', 'p', 'c', '<', '='}  //       ?,     play,  config, rewind,   stop
 | ||||||
|  |   }; | ||||||
|  |   byte rowPins[ROWS] = {SW_A, SW_B, SW_C, SW_D, | ||||||
|  |                         SW_E}; // connect to the row pinouts of the keypad
 | ||||||
|  |   byte colPins[COLS] = {SW_1, SW_2, SW_3, SW_4, | ||||||
|  |                         SW_5}; // connect to the column pinouts of the keypad
 | ||||||
|  |   Keypad customKeypad = | ||||||
|  |       Keypad(makeKeymap(hexaKeys), rowPins, colPins, ROWS, COLS); | ||||||
|  | 
 | ||||||
|  |   byte keyMapTechnisat[ROWS][COLS] = {{0x69, 0x20, 0x11, 0x0D, 0x56}, | ||||||
|  |                                       {0x4F, 0x37, 0x10, 0x57, 0x51}, | ||||||
|  |                                       {0x6E, 0x21, 0x6B, 0x6D, 0x6C}, | ||||||
|  |                                       {0x34, 0x0C, 0x22, 0x50, 0x55}, | ||||||
|  |                                       {'?', 0x35, 0x2F, 0x32, 0x36}}; | ||||||
|  |   byte virtualKeyMapTechnisat[10] = {0x1, 0x2, 0x3, 0x4, 0x5, | ||||||
|  |                                     0x6, 0x7, 0x8, 0x9, 0x0}; | ||||||
|  | 
 | ||||||
|  |   static std::shared_ptr<HardwareRevX> mInstance; | ||||||
|  | }; | ||||||
							
								
								
									
										516
									
								
								Platformio/src/OmoteUI.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										516
									
								
								Platformio/src/OmoteUI.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,516 @@ | ||||||
|  | #include "OmoteUI.hpp" | ||||||
|  | #include "lvgl.h" | ||||||
|  | #include "omoteconfig.h" | ||||||
|  | #include <functional> | ||||||
|  | 
 | ||||||
|  | std::shared_ptr<OmoteUI> OmoteUI::mInstance = nullptr; | ||||||
|  | 
 | ||||||
|  | // This can be used to flag out specific code for SIM only
 | ||||||
|  | // #if defined(IS_SIMULATOR) && (IS_SIMULATOR == true)
 | ||||||
|  | // #endif
 | ||||||
|  | 
 | ||||||
|  | // Set the page indicator scroll position relative to the tabview scroll
 | ||||||
|  | // position
 | ||||||
|  | void OmoteUI::store_scroll_value_event_cb(lv_event_t *e) { | ||||||
|  |   float bias = (150.0 + 8.0) / 240.0; | ||||||
|  |   int offset = 240 / 2 - 150 / 2 - 8 - 50 - 3; | ||||||
|  |   lv_obj_t *screen = lv_event_get_target(e); | ||||||
|  |   lv_obj_scroll_to_x(panel, lv_obj_get_scroll_x(screen) * bias - offset, | ||||||
|  |                      LV_ANIM_OFF); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Update current device when the tabview page is changes
 | ||||||
|  | void OmoteUI::tabview_device_event_cb(lv_event_t *e) { | ||||||
|  |   currentDevice = lv_tabview_get_tab_act(lv_event_get_target(e)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Slider Event handler
 | ||||||
|  | void OmoteUI::bl_slider_event_cb(lv_event_t *e) { | ||||||
|  |   lv_obj_t *slider = lv_event_get_target(e); | ||||||
|  |   backlight_brightness = std::clamp(lv_slider_get_value(slider), 60, 255); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Apple Key Event handler
 | ||||||
|  | void OmoteUI::appleKey_event_cb(lv_event_t *e) { | ||||||
|  |   // Send IR command based on the event user data
 | ||||||
|  |   mHardware->sendIR(); | ||||||
|  |   mHardware->debugPrint(std::to_string(50 + (int)e->user_data)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Wakeup by IMU Switch Event handler
 | ||||||
|  | void OmoteUI::WakeEnableSetting_event_cb(lv_event_t *e) { | ||||||
|  |   wakeupByIMUEnabled = | ||||||
|  |       lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Smart Home Toggle Event handler
 | ||||||
|  | void OmoteUI::smartHomeToggle_event_cb(lv_event_t *e) { | ||||||
|  |   char payload[8]; | ||||||
|  |   if (lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED)) | ||||||
|  |     strcpy(payload, "true"); | ||||||
|  |   else | ||||||
|  |     strcpy(payload, "false"); | ||||||
|  |   // Publish an MQTT message based on the event user data
 | ||||||
|  |   if ((int)e->user_data == 1) | ||||||
|  |     mHardware->MQTTPublish("bulb1_set", payload); | ||||||
|  |   if ((int)e->user_data == 2) | ||||||
|  |     mHardware->MQTTPublish("bulb2_set", payload); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Smart Home Toggle Event handler
 | ||||||
|  | void OmoteUI::smartHomeSlider_event_cb(lv_event_t *e) { | ||||||
|  |   lv_obj_t *slider = lv_event_get_target(e); | ||||||
|  |   char payload[8]; | ||||||
|  |   auto sliderValue = lv_slider_get_value(slider); | ||||||
|  | 
 | ||||||
|  |   // TODO convert this dtostrf to somethign more portable.
 | ||||||
|  |   //  I gave it a stab here but not sure it is the same.
 | ||||||
|  |   // dtostrf(lv_slider_get_value(slider), 1, 2, payload);
 | ||||||
|  |   snprintf(payload, sizeof(payload), "%8.2f", sliderValue); | ||||||
|  | 
 | ||||||
|  |   // Publish an MQTT message based on the event user data
 | ||||||
|  |   if ((int)e->user_data == 1) | ||||||
|  |     mHardware->MQTTPublish("bulb1_setbrightness", payload); | ||||||
|  |   if ((int)e->user_data == 2) | ||||||
|  |     mHardware->MQTTPublish("bulb2_setbrightness", payload); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void OmoteUI::virtualKeypad_event_cb(lv_event_t *e) { | ||||||
|  |   lv_obj_t *target = lv_event_get_target(e); | ||||||
|  |   lv_obj_t *cont = lv_event_get_current_target(e); | ||||||
|  |   if (target == cont) | ||||||
|  |     return; | ||||||
|  | 
 | ||||||
|  |   char buffer[100]; | ||||||
|  |   sprintf(buffer, "check it out: %d\n", | ||||||
|  |           virtualKeyMapTechnisat[(int)target->user_data]); | ||||||
|  |   mHardware->debugPrint(buffer); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void OmoteUI::loopHandler(){ | ||||||
|  |   lv_timer_handler(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void OmoteUI::layout_UI() { | ||||||
|  | 
 | ||||||
|  |   // --- LVGL UI Configuration ---
 | ||||||
|  |      | ||||||
|  |   // Set the background color
 | ||||||
|  |   lv_obj_set_style_bg_color(lv_scr_act(), lv_color_black(), LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   // Setup a scrollable tabview for devices and settings
 | ||||||
|  |   lv_obj_t *tabview; | ||||||
|  |   tabview = | ||||||
|  |       lv_tabview_create(lv_scr_act(), LV_DIR_TOP, | ||||||
|  |                         0); // Hide tab labels by setting their height to 0
 | ||||||
|  |   lv_obj_set_style_bg_color(tabview, lv_color_black(), LV_PART_MAIN); | ||||||
|  |   lv_obj_set_size(tabview, SCREEN_WIDTH, | ||||||
|  |                   270); // 270 = screenHeight(320) - panel(30) - statusbar(20)
 | ||||||
|  |   lv_obj_align(tabview, LV_ALIGN_TOP_MID, 0, 20); | ||||||
|  | 
 | ||||||
|  |   // Add 4 tabs (names are irrelevant since the labels are hidden)
 | ||||||
|  |   lv_obj_t *tab1 = lv_tabview_add_tab(tabview, "Settings"); | ||||||
|  |   lv_obj_t *tab2 = lv_tabview_add_tab(tabview, "Technisat"); | ||||||
|  |   lv_obj_t *tab3 = lv_tabview_add_tab(tabview, "Apple TV"); | ||||||
|  |   lv_obj_t *tab4 = lv_tabview_add_tab(tabview, "Smart Home"); | ||||||
|  | 
 | ||||||
|  |   // Configure number button grid
 | ||||||
|  |   static lv_coord_t col_dsc[] = {LV_GRID_FR(1), LV_GRID_FR(1), LV_GRID_FR(1), | ||||||
|  |                                  LV_GRID_TEMPLATE_LAST}; // equal x distribution
 | ||||||
|  |   static lv_coord_t row_dsc[] = { | ||||||
|  |       52, 52, 52, 52, LV_GRID_TEMPLATE_LAST}; // manual y distribution to
 | ||||||
|  |                                               // compress the grid a bit
 | ||||||
|  | 
 | ||||||
|  |   // Create a container with grid for tab2
 | ||||||
|  |   lv_obj_set_style_pad_all(tab2, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_t *cont = lv_obj_create(tab2); | ||||||
|  |   lv_obj_set_style_shadow_width(cont, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(cont, lv_color_black(), LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(cont, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_grid_column_dsc_array(cont, col_dsc, 0); | ||||||
|  |   lv_obj_set_style_grid_row_dsc_array(cont, row_dsc, 0); | ||||||
|  |   lv_obj_set_size(cont, 240, 270); | ||||||
|  |   lv_obj_set_layout(cont, LV_LAYOUT_GRID); | ||||||
|  |   lv_obj_align(cont, LV_ALIGN_TOP_MID, 0, 0); | ||||||
|  |   lv_obj_set_style_radius(cont, 0, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *buttonLabel; | ||||||
|  |   lv_obj_t *obj; | ||||||
|  | 
 | ||||||
|  |   // Iterate through grid buttons and configure them
 | ||||||
|  |   for (int i = 0; i < 12; i++) { | ||||||
|  |     uint8_t col = i % 3; | ||||||
|  |     uint8_t row = i / 3; | ||||||
|  |     // Create the button object
 | ||||||
|  |     if ((row == 3) && ((col == 0) || (col == 2))) | ||||||
|  |       continue; // Do not create a complete fourth row, only a 0 button
 | ||||||
|  |     obj = lv_btn_create(cont); | ||||||
|  |     lv_obj_set_grid_cell(obj, LV_GRID_ALIGN_STRETCH, col, 1, | ||||||
|  |                          LV_GRID_ALIGN_STRETCH, row, 1); | ||||||
|  |     lv_obj_set_style_bg_color(obj, color_primary, LV_PART_MAIN); | ||||||
|  |     lv_obj_set_style_radius(obj, 14, LV_PART_MAIN); | ||||||
|  |     lv_obj_add_flag(obj, LV_OBJ_FLAG_EVENT_BUBBLE); // Clicking a button causes
 | ||||||
|  |                                                     // a event in its container
 | ||||||
|  |     // Create Labels for each button
 | ||||||
|  |     buttonLabel = lv_label_create(obj); | ||||||
|  |     if (i < 9) { | ||||||
|  |       lv_label_set_text_fmt(buttonLabel, std::to_string(i + 1).c_str(), col, | ||||||
|  |                             row); | ||||||
|  |       lv_obj_set_user_data(obj, | ||||||
|  |                            (void *)i); // Add user data so we can identify which
 | ||||||
|  |                                        // button caused the container event
 | ||||||
|  |     } else { | ||||||
|  |       lv_label_set_text_fmt(buttonLabel, "0", col, row); | ||||||
|  |       lv_obj_set_user_data(obj, (void *)9); | ||||||
|  |     } | ||||||
|  |     lv_obj_set_style_text_font(buttonLabel, &lv_font_montserrat_14, | ||||||
|  |                                LV_PART_MAIN); | ||||||
|  |     lv_obj_center(buttonLabel); | ||||||
|  |   } | ||||||
|  |   // Create a shared event for all button inside container
 | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       cont, [](lv_event_t *e) { mInstance->virtualKeypad_event_cb(e); }, | ||||||
|  |       LV_EVENT_CLICKED, NULL); | ||||||
|  | 
 | ||||||
|  |   // Add content to the Apple TV tab (3)
 | ||||||
|  |   // Add a nice apple tv logo
 | ||||||
|  |    | ||||||
|  |   lv_obj_t* appleImg = imgs.addAppleTVIcon(tab3); | ||||||
|  |   lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, -60); | ||||||
|  |    | ||||||
|  |   // create two buttons and add their icons accordingly
 | ||||||
|  |   lv_obj_t *button = lv_btn_create(tab3); | ||||||
|  |   lv_obj_align(button, LV_ALIGN_BOTTOM_LEFT, 10, 0); | ||||||
|  |   lv_obj_set_size(button, 60, 60); | ||||||
|  |   lv_obj_set_style_radius(button, 30, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); }, | ||||||
|  |       LV_EVENT_CLICKED, (void *)1); | ||||||
|  | 
 | ||||||
|  |   appleImg = imgs.addAppleBackIcon(button); | ||||||
|  |   lv_obj_align(appleImg, LV_ALIGN_CENTER, -3, 0); | ||||||
|  | 
 | ||||||
|  |   button = lv_btn_create(tab3); | ||||||
|  |   lv_obj_align(button, LV_ALIGN_BOTTOM_RIGHT, -10, 0); | ||||||
|  |   lv_obj_set_size(button, 60, 60); | ||||||
|  |   lv_obj_set_style_radius(button, 30, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(button, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       button, [](lv_event_t *e) { mInstance->appleKey_event_cb(e); }, | ||||||
|  |       LV_EVENT_CLICKED, (void *)2); | ||||||
|  | 
 | ||||||
|  |   appleImg = imgs.addAppleDisplayImage(button); | ||||||
|  |   lv_obj_align(appleImg, LV_ALIGN_CENTER, 0, 0); | ||||||
|  | 
 | ||||||
|  |   // Add content to the settings tab
 | ||||||
|  |   // With a flex layout, setting groups/boxes will position themselves
 | ||||||
|  |   // automatically
 | ||||||
|  |   lv_obj_set_layout(tab1, LV_LAYOUT_FLEX); | ||||||
|  |   lv_obj_set_flex_flow(tab1, LV_FLEX_FLOW_COLUMN); | ||||||
|  |   lv_obj_set_scrollbar_mode(tab1, LV_SCROLLBAR_MODE_ACTIVE); | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  |   // Add a label, then a box for the display settings
 | ||||||
|  |   lv_obj_t *menuLabel = lv_label_create(tab1); | ||||||
|  |   lv_label_set_text(menuLabel, "Display"); | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *menuBox = lv_obj_create(tab1); | ||||||
|  |   lv_obj_set_size(menuBox, lv_pct(100), 109); | ||||||
|  |   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *brightnessIcon = imgs.addLowBrightnessIcon(menuBox); | ||||||
|  |   lv_obj_align(brightnessIcon, LV_ALIGN_TOP_LEFT, 0, 0); | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *slider = lv_slider_create(menuBox); | ||||||
|  |   lv_slider_set_range(slider, 60, 255); | ||||||
|  |   lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); | ||||||
|  |   lv_obj_set_style_bg_opa(slider, LV_OPA_COVER, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), | ||||||
|  |                             LV_PART_MAIN); | ||||||
|  |   lv_slider_set_value(slider, backlight_brightness, LV_ANIM_OFF); | ||||||
|  |   lv_obj_set_size(slider, lv_pct(66), 10); | ||||||
|  |   lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 3); | ||||||
|  | 
 | ||||||
|  |   brightnessIcon = imgs.addHighBrightnessIcon(menuBox); | ||||||
|  |   lv_obj_align(brightnessIcon, LV_ALIGN_TOP_RIGHT, 0, -1); | ||||||
|  |    | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       slider, [](lv_event_t *e) { mInstance->bl_slider_event_cb(e); }, | ||||||
|  |       LV_EVENT_VALUE_CHANGED, NULL); | ||||||
|  | 
 | ||||||
|  |   menuLabel = lv_label_create(menuBox); | ||||||
|  |   lv_label_set_text(menuLabel, "Lift to Wake"); | ||||||
|  |   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32); | ||||||
|  |   lv_obj_t *wakeToggle = lv_switch_create(menuBox); | ||||||
|  |   lv_obj_set_size(wakeToggle, 40, 22); | ||||||
|  |   lv_obj_align(wakeToggle, LV_ALIGN_TOP_RIGHT, 0, 29); | ||||||
|  |   lv_obj_set_style_bg_color(wakeToggle, lv_color_lighten(color_primary, 50), | ||||||
|  |                             LV_PART_MAIN); | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       wakeToggle, | ||||||
|  |       [](lv_event_t *e) { mInstance->WakeEnableSetting_event_cb(e); }, | ||||||
|  |       LV_EVENT_VALUE_CHANGED, NULL); | ||||||
|  |   if (wakeupByIMUEnabled) | ||||||
|  |     lv_obj_add_state(wakeToggle, LV_STATE_CHECKED); // set default state
 | ||||||
|  | 
 | ||||||
|  |   menuLabel = lv_label_create(menuBox); | ||||||
|  |   lv_label_set_text(menuLabel, "Timeout"); | ||||||
|  |   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 64); | ||||||
|  |   lv_obj_t *drop = lv_dropdown_create(menuBox); | ||||||
|  |   lv_dropdown_set_options(drop, "10s\n" | ||||||
|  |                                 "30s\n" | ||||||
|  |                                 "1m\n" | ||||||
|  |                                 "3m"); | ||||||
|  |   lv_obj_align(drop, LV_ALIGN_TOP_RIGHT, 0, 61); | ||||||
|  |   lv_obj_set_size(drop, 70, 22); | ||||||
|  |   lv_obj_set_style_pad_top(drop, 1, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(drop, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(drop, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(lv_dropdown_get_list(drop), color_primary, | ||||||
|  |                             LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(lv_dropdown_get_list(drop), 1, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_color(lv_dropdown_get_list(drop), | ||||||
|  |                                 lv_color_darken(color_primary, 40), | ||||||
|  |                                 LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   // Add another label, then a settings box for WiFi
 | ||||||
|  |   menuLabel = lv_label_create(tab1); | ||||||
|  |   lv_label_set_text(menuLabel, "Wi-Fi"); | ||||||
|  |   menuBox = lv_obj_create(tab1); | ||||||
|  |   lv_obj_set_size(menuBox, lv_pct(100), 80); | ||||||
|  |   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); | ||||||
|  |   menuLabel = lv_label_create(menuBox); | ||||||
|  |   lv_label_set_text(menuLabel, "Network"); | ||||||
|  |   menuLabel = lv_label_create(menuBox); | ||||||
|  |   lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT); | ||||||
|  |   lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 0); | ||||||
|  |   menuLabel = lv_label_create(menuBox); | ||||||
|  |   lv_label_set_text(menuLabel, "Password"); | ||||||
|  |   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 0, 32); | ||||||
|  |   menuLabel = lv_label_create(menuBox); | ||||||
|  |   lv_label_set_text(menuLabel, LV_SYMBOL_RIGHT); | ||||||
|  |   lv_obj_align(menuLabel, LV_ALIGN_TOP_RIGHT, 0, 32); | ||||||
|  | 
 | ||||||
|  |   // Another setting for the battery
 | ||||||
|  |   menuLabel = lv_label_create(tab1); | ||||||
|  |   lv_label_set_text(menuLabel, "Battery"); | ||||||
|  |   menuBox = lv_obj_create(tab1); | ||||||
|  |   lv_obj_set_size(menuBox, lv_pct(100), 125); | ||||||
|  |   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   // Add content to the smart home tab (4)
 | ||||||
|  | 
 | ||||||
|  |   lv_obj_set_layout(tab4, LV_LAYOUT_FLEX); | ||||||
|  |   lv_obj_set_flex_flow(tab4, LV_FLEX_FLOW_COLUMN); | ||||||
|  |   lv_obj_set_scrollbar_mode(tab4, LV_SCROLLBAR_MODE_ACTIVE); | ||||||
|  | 
 | ||||||
|  |   // Add a label, then a box for the light controls
 | ||||||
|  |   menuLabel = lv_label_create(tab4); | ||||||
|  |   lv_label_set_text(menuLabel, "Living Room"); | ||||||
|  | 
 | ||||||
|  |   menuBox = lv_obj_create(tab4); | ||||||
|  |   lv_obj_set_size(menuBox, lv_pct(100), 79); | ||||||
|  |   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *bulbIcon = imgs.addLightBulbIcon(menuBox); | ||||||
|  |   lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0); | ||||||
|  | 
 | ||||||
|  |   menuLabel = lv_label_create(menuBox); | ||||||
|  |   lv_label_set_text(menuLabel, "Floor Lamp"); | ||||||
|  |   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3); | ||||||
|  |   lv_obj_t *lightToggleA = lv_switch_create(menuBox); | ||||||
|  |   lv_obj_set_size(lightToggleA, 40, 22); | ||||||
|  |   lv_obj_align(lightToggleA, LV_ALIGN_TOP_RIGHT, 0, 0); | ||||||
|  |   lv_obj_set_style_bg_color(lightToggleA, lv_color_lighten(color_primary, 50), | ||||||
|  |                             LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(lightToggleA, color_primary, LV_PART_INDICATOR); | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       lightToggleA, | ||||||
|  |       [](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); }, | ||||||
|  |       LV_EVENT_VALUE_CHANGED, (void *)1); | ||||||
|  | 
 | ||||||
|  |   slider = lv_slider_create(menuBox); | ||||||
|  |   lv_slider_set_range(slider, 60, 255); | ||||||
|  |   lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), | ||||||
|  |                             LV_PART_INDICATOR); | ||||||
|  |   lv_obj_set_style_bg_grad_color( | ||||||
|  |       slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), | ||||||
|  |       LV_PART_INDICATOR); | ||||||
|  |   lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR); | ||||||
|  |   lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); | ||||||
|  |   lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), | ||||||
|  |                             LV_PART_MAIN); | ||||||
|  |   lv_slider_set_value(slider, 255, LV_ANIM_OFF); | ||||||
|  |   lv_obj_set_size(slider, lv_pct(90), 10); | ||||||
|  |   lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37); | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); }, | ||||||
|  |       LV_EVENT_VALUE_CHANGED, (void *)1); | ||||||
|  | 
 | ||||||
|  |   // Add another menu box for a second appliance
 | ||||||
|  |   menuBox = lv_obj_create(tab4); | ||||||
|  |   lv_obj_set_size(menuBox, lv_pct(100), 79); | ||||||
|  |   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   bulbIcon = imgs.addLightBulbIcon(menuBox); | ||||||
|  |   lv_obj_align(bulbIcon, LV_ALIGN_TOP_LEFT, 0, 0); | ||||||
|  | 
 | ||||||
|  |   menuLabel = lv_label_create(menuBox); | ||||||
|  |   lv_label_set_text(menuLabel, "Ceiling Light"); | ||||||
|  |   lv_obj_align(menuLabel, LV_ALIGN_TOP_LEFT, 22, 3); | ||||||
|  |   lv_obj_t *lightToggleB = lv_switch_create(menuBox); | ||||||
|  |   lv_obj_set_size(lightToggleB, 40, 22); | ||||||
|  |   lv_obj_align(lightToggleB, LV_ALIGN_TOP_RIGHT, 0, 0); | ||||||
|  |   lv_obj_set_style_bg_color(lightToggleB, lv_color_lighten(color_primary, 50), | ||||||
|  |                             LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(lightToggleB, color_primary, LV_PART_INDICATOR); | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       lightToggleB, | ||||||
|  |       [](lv_event_t *e) { mInstance->smartHomeToggle_event_cb(e); }, | ||||||
|  |       LV_EVENT_VALUE_CHANGED, (void *)2); | ||||||
|  | 
 | ||||||
|  |   slider = lv_slider_create(menuBox); | ||||||
|  |   lv_slider_set_range(slider, 60, 255); | ||||||
|  |   lv_obj_set_style_bg_color(slider, lv_color_lighten(lv_color_black(), 30), | ||||||
|  |                             LV_PART_INDICATOR); | ||||||
|  |   lv_obj_set_style_bg_grad_color( | ||||||
|  |       slider, lv_color_lighten(lv_palette_main(LV_PALETTE_AMBER), 180), | ||||||
|  |       LV_PART_INDICATOR); | ||||||
|  |   lv_obj_set_style_bg_grad_dir(slider, LV_GRAD_DIR_HOR, LV_PART_INDICATOR); | ||||||
|  |   lv_obj_set_style_bg_color(slider, lv_color_white(), LV_PART_KNOB); | ||||||
|  |   lv_obj_set_style_bg_opa(slider, 255, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(slider, lv_color_lighten(color_primary, 50), | ||||||
|  |                             LV_PART_MAIN); | ||||||
|  |   lv_slider_set_value(slider, 255, LV_ANIM_OFF); | ||||||
|  |   lv_obj_set_size(slider, lv_pct(90), 10); | ||||||
|  |   lv_obj_align(slider, LV_ALIGN_TOP_MID, 0, 37); | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       slider, [](lv_event_t *e) { mInstance->smartHomeSlider_event_cb(e); }, | ||||||
|  |       LV_EVENT_VALUE_CHANGED, (void *)2); | ||||||
|  | 
 | ||||||
|  |   // Add another room (empty for now)
 | ||||||
|  |   menuLabel = lv_label_create(tab4); | ||||||
|  |   lv_label_set_text(menuLabel, "Kitchen"); | ||||||
|  | 
 | ||||||
|  |   menuBox = lv_obj_create(tab4); | ||||||
|  |   lv_obj_set_size(menuBox, lv_pct(100), 79); | ||||||
|  |   lv_obj_set_style_bg_color(menuBox, color_primary, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_border_width(menuBox, 0, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   // Set current page according to the current Device
 | ||||||
|  |   lv_tabview_set_act(tabview, currentDevice, LV_ANIM_OFF); | ||||||
|  | 
 | ||||||
|  |   // Create a page indicator
 | ||||||
|  |   panel = lv_obj_create(lv_scr_act()); | ||||||
|  |   lv_obj_clear_flag( | ||||||
|  |       panel, LV_OBJ_FLAG_CLICKABLE); // this indicator will not be clickable
 | ||||||
|  |   lv_obj_set_size(panel, SCREEN_WIDTH, 30); | ||||||
|  |   lv_obj_set_flex_flow(panel, LV_FLEX_FLOW_ROW); | ||||||
|  |   lv_obj_align(panel, LV_ALIGN_BOTTOM_MID, 0, 0); | ||||||
|  |   lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF); | ||||||
|  |   // This small hidden button enables the page indicator to scroll further
 | ||||||
|  |   lv_obj_t *btn = lv_btn_create(panel); | ||||||
|  |   lv_obj_set_size(btn, 50, lv_pct(100)); | ||||||
|  |   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN); | ||||||
|  |   // Create actual (non-clickable) buttons for every tab
 | ||||||
|  |   btn = lv_btn_create(panel); | ||||||
|  |   lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); | ||||||
|  |   lv_obj_set_size(btn, 150, lv_pct(100)); | ||||||
|  |   lv_obj_t *label = lv_label_create(btn); | ||||||
|  |   lv_label_set_text_fmt(label, "Settings"); | ||||||
|  |   lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); | ||||||
|  |   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   btn = lv_btn_create(panel); | ||||||
|  |   lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); | ||||||
|  |   lv_obj_set_size(btn, 150, lv_pct(100)); | ||||||
|  |   label = lv_label_create(btn); | ||||||
|  |   lv_label_set_text_fmt(label, "Technisat"); | ||||||
|  |   lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); | ||||||
|  |   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   btn = lv_btn_create(panel); | ||||||
|  |   lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); | ||||||
|  |   lv_obj_set_size(btn, 150, lv_pct(100)); | ||||||
|  |   label = lv_label_create(btn); | ||||||
|  |   lv_label_set_text_fmt(label, "Apple TV"); | ||||||
|  |   lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); | ||||||
|  |   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   btn = lv_btn_create(panel); | ||||||
|  |   lv_obj_clear_flag(btn, LV_OBJ_FLAG_CLICKABLE); | ||||||
|  |   lv_obj_set_size(btn, 150, lv_pct(100)); | ||||||
|  |   label = lv_label_create(btn); | ||||||
|  |   lv_label_set_text_fmt(label, "Smart Home"); | ||||||
|  |   lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); | ||||||
|  |   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(btn, color_primary, LV_PART_MAIN); | ||||||
|  |   // This small hidden button enables the page indicator to scroll further
 | ||||||
|  |   btn = lv_btn_create(panel); | ||||||
|  |   lv_obj_set_size(btn, 50, lv_pct(100)); | ||||||
|  |   lv_obj_set_style_shadow_width(btn, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_opa(btn, LV_OPA_TRANSP, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   // Make the indicator scroll together with the tabs by creating a scroll event
 | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       lv_tabview_get_content(tabview), | ||||||
|  |       [](lv_event_t *e) { mInstance->store_scroll_value_event_cb(e); }, | ||||||
|  |       LV_EVENT_SCROLL, NULL); | ||||||
|  |   lv_obj_add_event_cb( | ||||||
|  |       tabview, [](lv_event_t *e) { mInstance->tabview_device_event_cb(e); }, | ||||||
|  |       LV_EVENT_VALUE_CHANGED, NULL); | ||||||
|  |   // Initialize scroll position for the indicator
 | ||||||
|  |   lv_event_send(lv_tabview_get_content(tabview), LV_EVENT_SCROLL, NULL); | ||||||
|  | 
 | ||||||
|  |   // Style the panel background
 | ||||||
|  |   static lv_style_t style_btn; | ||||||
|  |   lv_style_init(&style_btn); | ||||||
|  |   lv_style_set_pad_all(&style_btn, 3); | ||||||
|  |   lv_style_set_border_width(&style_btn, 0); | ||||||
|  |   lv_style_set_bg_opa(&style_btn, LV_OPA_TRANSP); | ||||||
|  |   lv_obj_add_style(panel, &style_btn, 0); | ||||||
|  | 
 | ||||||
|  |   // Make the indicator fade out at the sides using gradient bitmaps
 | ||||||
|  |   lv_obj_t *img1 = imgs.addLeftGradiant(lv_scr_act()); | ||||||
|  |   lv_obj_align(img1, LV_ALIGN_BOTTOM_LEFT, 0, 0); | ||||||
|  |   lv_obj_set_size(img1, 30, 30); // stretch the 1-pixel high image to 30px
 | ||||||
|  |    | ||||||
|  |   lv_obj_t* img2 = imgs.addRightGradiant(lv_scr_act()); | ||||||
|  |   lv_obj_align(img2, LV_ALIGN_BOTTOM_RIGHT, 0, 0); | ||||||
|  |   lv_obj_set_size(img2, 30, 30); | ||||||
|  | 
 | ||||||
|  |   // Create a status bar
 | ||||||
|  |   lv_obj_t *statusbar = lv_btn_create(lv_scr_act()); | ||||||
|  |   lv_obj_set_size(statusbar, 240, 20); | ||||||
|  |   lv_obj_set_style_shadow_width(statusbar, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_bg_color(statusbar, lv_color_black(), LV_PART_MAIN); | ||||||
|  |   lv_obj_set_style_radius(statusbar, 0, LV_PART_MAIN); | ||||||
|  |   lv_obj_align(statusbar, LV_ALIGN_TOP_MID, 0, 0); | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *WifiLabel = lv_label_create(statusbar); | ||||||
|  |   lv_label_set_text(WifiLabel, LV_SYMBOL_WIFI); | ||||||
|  |   lv_obj_align(WifiLabel, LV_ALIGN_LEFT_MID, -8, 0); | ||||||
|  |   lv_obj_set_style_text_font(WifiLabel, &lv_font_montserrat_14, LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *objBattPercentage = lv_label_create(statusbar); | ||||||
|  |   lv_label_set_text(objBattPercentage, ""); | ||||||
|  |   lv_obj_align(objBattPercentage, LV_ALIGN_RIGHT_MID, -16, 0); | ||||||
|  |   lv_obj_set_style_text_font(objBattPercentage, &lv_font_montserrat_14, | ||||||
|  |                              LV_PART_MAIN); | ||||||
|  | 
 | ||||||
|  |   lv_obj_t *objBattIcon = lv_label_create(statusbar); | ||||||
|  |   lv_label_set_text(objBattIcon, LV_SYMBOL_BATTERY_EMPTY); | ||||||
|  |   lv_obj_align(objBattIcon, LV_ALIGN_RIGHT_MID, 8, 0); | ||||||
|  |   lv_obj_set_style_text_font(objBattIcon, &lv_font_montserrat_14, LV_PART_MAIN); | ||||||
|  | } | ||||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
		Loading…
	
	Add table
		
		Reference in a new issue