diff --git a/CYD-Klipper-Display/platformio.ini b/CYD-Klipper-Display/platformio.ini index f88bb6a..e756d90 100644 --- a/CYD-Klipper-Display/platformio.ini +++ b/CYD-Klipper-Display/platformio.ini @@ -23,7 +23,6 @@ build_flags = -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" -DUSER_SETUP_LOADED=1 -DILI9341_2_DRIVER=1 - -DTFT_INVERSION_ON=1 -DTFT_WIDTH=240 -DTFT_HEIGHT=320 -DTFT_BL=21 diff --git a/CYD-Klipper-Display/src/conf/global_config.cpp b/CYD-Klipper-Display/src/conf/global_config.cpp index 4f64b8f..da3b692 100644 --- a/CYD-Klipper-Display/src/conf/global_config.cpp +++ b/CYD-Klipper-Display/src/conf/global_config.cpp @@ -1,8 +1,19 @@ #include #include "global_config.h" +#include "lvgl.h" GLOBAL_CONFIG global_config = {0}; +COLOR_DEF color_defs[] = { + {LV_PALETTE_BLUE, LV_PALETTE_RED}, + {LV_PALETTE_GREEN, LV_PALETTE_PURPLE}, + {LV_PALETTE_GREY, LV_PALETTE_CYAN}, + {LV_PALETTE_YELLOW, LV_PALETTE_PINK}, + {LV_PALETTE_ORANGE, LV_PALETTE_BLUE}, + {LV_PALETTE_RED, LV_PALETTE_GREEN}, + {LV_PALETTE_PURPLE, LV_PALETTE_GREY}, +}; + void WriteGlobalConfig() { Preferences preferences; preferences.begin("global_config", false); diff --git a/CYD-Klipper-Display/src/conf/global_config.h b/CYD-Klipper-Display/src/conf/global_config.h index eeb1985..fedfd73 100644 --- a/CYD-Klipper-Display/src/conf/global_config.h +++ b/CYD-Klipper-Display/src/conf/global_config.h @@ -1,6 +1,8 @@ #ifndef _GLOBAL_CONFIG_INIT #define _GLOBAL_CONFIG_INIT +#include "lvgl.h" + #define CONFIG_VERSION 80 typedef struct _GLOBAL_CONFIG { @@ -11,6 +13,8 @@ typedef struct _GLOBAL_CONFIG { bool screenCalibrated : 1; bool wifiConfigured : 1; bool ipConfigured : 1; + bool lightMode : 1; + bool invertColors : 1; }; }; float screenCalXOffset; @@ -23,9 +27,17 @@ typedef struct _GLOBAL_CONFIG { char klipperHost[64]; unsigned short klipperPort; + + unsigned char color_scheme; } GLOBAL_CONFIG; + +typedef struct _COLOR_DEF { + lv_palette_t primary_color; + lv_palette_t secondary_color; +} COLOR_DEF; extern GLOBAL_CONFIG global_config; +extern COLOR_DEF color_defs[]; void WriteGlobalConfig(); void VerifyVersion(); diff --git a/CYD-Klipper-Display/src/core/data_setup.cpp b/CYD-Klipper-Display/src/core/data_setup.cpp index 2ea825c..c723ed1 100644 --- a/CYD-Klipper-Display/src/core/data_setup.cpp +++ b/CYD-Klipper-Display/src/core/data_setup.cpp @@ -31,6 +31,7 @@ void send_gcode(bool wait, const char* gcode){ } } +// TODO: Merge with other request, see https://moonraker.readthedocs.io/en/latest/printer_objects/#webhooks void fetch_printer_state(){ char buff[91] = {}; sprintf(buff, "http://%s:%d/printer/info", global_config.klipperHost, global_config.klipperPort); @@ -74,15 +75,17 @@ void fetch_printer_state(){ } } +char filename_buff[512] = {0}; + void fetch_printer_data(){ char buff[256] = {}; - sprintf(buff, "http://%s:%d/printer/objects/query?extruder&heater_bed&toolhead&gcode_move", global_config.klipperHost, global_config.klipperPort); + sprintf(buff, "http://%s:%d/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats", global_config.klipperHost, global_config.klipperPort); HTTPClient client; client.begin(buff); int httpCode = client.GET(); if (httpCode == 200) { String payload = client.getString(); - DynamicJsonDocument doc(2048); + DynamicJsonDocument doc(4096); deserializeJson(doc, payload); auto status = doc["result"]["status"]; if (status.containsKey("extruder")){ @@ -110,7 +113,45 @@ void fetch_printer_data(){ printer.absolute_coords = absolute_coords == true; } + if (status.containsKey("virtual_sdcard")){ + printer.print_progress = status["virtual_sdcard"]["progress"]; + } + + int printer_state = printer.state; + + if (status.containsKey("print_stats")){ + const char* filename = status["print_stats"]["filename"]; + strcpy(filename_buff, filename); + printer.print_filename = filename_buff; + printer.elapsed_time_s = status["print_stats"]["print_duration"]; + printer.filament_used_mm = status["print_stats"]["filament_used"]; + + const char* state = status["print_stats"]["state"]; + + if (strcmp(state, "printing") == 0){ + printer_state = PRINTER_STATE_PRINTING; + } + else if (strcmp(state, "paused") == 0){ + printer_state = PRINTER_STATE_PAUSED; + } + else if (strcmp(state, "complete") == 0 || strcmp(state, "cancelled") == 0 || strcmp(state, "standby") == 0){ + printer_state = PRINTER_STATE_IDLE; + } + } + + // TODO: make a call to /server/files/metadata to get more accurate time estimates + // https://moonraker.readthedocs.io/en/latest/web_api/#server-administration + + if (printer.state == PRINTER_STATE_PRINTING && printer.print_progress > 0){ + printer.remaining_time_s = (printer.elapsed_time_s / printer.print_progress) - printer.elapsed_time_s; + } + lv_msg_send(DATA_PRINTER_DATA, &printer); + + if (printer.state != printer_state){ + printer.state = printer_state; + lv_msg_send(DATA_PRINTER_STATE, &printer); + } } else { Serial.printf("Failed to fetch printer data: %d\n", httpCode); @@ -132,6 +173,7 @@ void data_loop(){ } void data_setup(){ + printer.print_filename = filename_buff; fetch_printer_state(); fetch_printer_data(); } \ No newline at end of file diff --git a/CYD-Klipper-Display/src/core/data_setup.h b/CYD-Klipper-Display/src/core/data_setup.h index 2c826ad..6439166 100644 --- a/CYD-Klipper-Display/src/core/data_setup.h +++ b/CYD-Klipper-Display/src/core/data_setup.h @@ -4,11 +4,12 @@ enum { PRINTER_STATE_ERROR = 0, PRINTER_STATE_IDLE = 1, PRINTER_STATE_PRINTING = 2, + PRINTER_STATE_PAUSED = 3, }; extern const char* printer_state_messages[]; -typedef struct Printer { +typedef struct _Printer { unsigned char state; char* state_message; float extruder_temp; @@ -19,7 +20,12 @@ typedef struct Printer { unsigned char can_extrude; unsigned char homed_axis; unsigned char absolute_coords; -} _Printer; + float elapsed_time_s; + float remaining_time_s; + float filament_used_mm; + char* print_filename; // 0 -> 1 + float print_progress; +} Printer; extern Printer printer; diff --git a/CYD-Klipper-Display/src/core/screen_driver.cpp b/CYD-Klipper-Display/src/core/screen_driver.cpp index 4c897a7..660c6e2 100644 --- a/CYD-Klipper-Display/src/core/screen_driver.cpp +++ b/CYD-Klipper-Display/src/core/screen_driver.cpp @@ -158,6 +158,16 @@ void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) } } +void set_color_scheme(){ + lv_disp_t *dispp = lv_disp_get_default(); + lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(color_defs[global_config.color_scheme].primary_color), lv_palette_main(color_defs[global_config.color_scheme].secondary_color), !global_config.lightMode, LV_FONT_DEFAULT); + lv_disp_set_theme(dispp, theme); +} + +void set_invert_display(){ + tft.invertDisplay(global_config.invertColors); +} + void screen_setup() { touchscreen_spi.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS); @@ -169,6 +179,7 @@ void screen_setup() tft.init(); tft.setRotation(1); tft.fillScreen(TFT_BLACK); + set_invert_display(); touchscreen_spi.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS); touchscreen.begin(touchscreen_spi); @@ -199,8 +210,5 @@ void screen_setup() /*Initialize the graphics library */ LV_EVENT_GET_COMP_CHILD = lv_event_register_id(); - - lv_disp_t *dispp = lv_disp_get_default(); - lv_theme_t *theme = lv_theme_default_init(dispp, lv_palette_main(LV_PALETTE_BLUE), lv_palette_main(LV_PALETTE_RED), true, LV_FONT_DEFAULT); - lv_disp_set_theme(dispp, theme); + set_color_scheme(); } \ No newline at end of file diff --git a/CYD-Klipper-Display/src/core/screen_driver.h b/CYD-Klipper-Display/src/core/screen_driver.h index 64f2549..2f95db3 100644 --- a/CYD-Klipper-Display/src/core/screen_driver.h +++ b/CYD-Klipper-Display/src/core/screen_driver.h @@ -5,6 +5,7 @@ #define _SCREEN_DRIVER_INIT #include +#include #define XPT2046_IRQ 36 #define XPT2046_MOSI 32 @@ -19,6 +20,10 @@ void screen_timer_setup(); void screen_timer_start(); void screen_timer_stop(); void screen_timer_period(uint32_t period); +void set_color_scheme(); void screen_setup(); +void set_invert_display(); + +extern TFT_eSPI tft; #endif // _SCREEN_DRIVER_INIT \ No newline at end of file diff --git a/CYD-Klipper-Display/src/main.cpp b/CYD-Klipper-Display/src/main.cpp index ad7df6c..3517415 100644 --- a/CYD-Klipper-Display/src/main.cpp +++ b/CYD-Klipper-Display/src/main.cpp @@ -17,7 +17,6 @@ static void event_handler(lv_event_t * e){ } } - void setup() { Serial.begin(115200); Serial.println("Hello World"); diff --git a/CYD-Klipper-Display/src/ui/main_ui.cpp b/CYD-Klipper-Display/src/ui/main_ui.cpp index 7f276b4..8bff3b2 100644 --- a/CYD-Klipper-Display/src/ui/main_ui.cpp +++ b/CYD-Klipper-Display/src/ui/main_ui.cpp @@ -98,7 +98,7 @@ static void on_state_change(void * s, lv_msg_t * m){ error_ui(); } else { - nav_buttons_setup(1); + nav_buttons_setup(0); } } diff --git a/CYD-Klipper-Display/src/ui/nav_buttons.cpp b/CYD-Klipper-Display/src/ui/nav_buttons.cpp index 63299a0..b86c87e 100644 --- a/CYD-Klipper-Display/src/ui/nav_buttons.cpp +++ b/CYD-Klipper-Display/src/ui/nav_buttons.cpp @@ -8,6 +8,7 @@ static lv_style_t nav_button_style; static char temp_buffer[10]; static char z_pos_buffer[10]; +static char time_buffer[10]; static lv_style_t nav_button_text_style; @@ -25,6 +26,39 @@ static void update_printer_data_temp(lv_event_t * e) { lv_label_set_text(label, temp_buffer); } +static void update_printer_data_time(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + + if (printer.state == PRINTER_STATE_IDLE){ + lv_label_set_text(label, "Idle"); + return; + } + + if (printer.state == PRINTER_STATE_PAUSED){ + lv_label_set_text(label, "Paused"); + return; + } + + unsigned long time = printer.remaining_time_s; + unsigned long hours = time / 3600; + unsigned long minutes = (time % 3600) / 60; + unsigned long seconds = (time % 3600) % 60; + + if (hours > 99){ + lv_label_set_text(label, ">99h"); + return; + } + + if (hours >= 1){ + sprintf(time_buffer, "%02luh%02lum", hours, minutes); + } else { + sprintf(time_buffer, "%02lum%02lus", minutes, seconds); + } + + lv_label_set_text(label, time_buffer); + +} + static void btn_click_files(lv_event_t * e){ nav_buttons_setup(0); } @@ -66,6 +100,8 @@ void nav_buttons_setup(unsigned char active_panel){ lv_label_set_text(label, "Idle"); lv_obj_align(label, LV_ALIGN_CENTER, 0, icon_text_spacing); lv_obj_add_style(label, &nav_button_text_style, 0); + lv_obj_add_event_cb(label, update_printer_data_time, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subsribe_obj(DATA_PRINTER_STATE, label, NULL); // Move btn = lv_btn_create(lv_scr_act()); diff --git a/CYD-Klipper-Display/src/ui/panels/move_panel.cpp b/CYD-Klipper-Display/src/ui/panels/move_panel.cpp index d511137..92b742a 100644 --- a/CYD-Klipper-Display/src/ui/panels/move_panel.cpp +++ b/CYD-Klipper-Display/src/ui/panels/move_panel.cpp @@ -18,7 +18,7 @@ static void move_printer(const char* axis, float amount) { const char * space = "%20"; - sprintf(gcode, "G1%s%s%s%.1f", space, axis, extra, amount); + sprintf(gcode, "G1%s%s%s%.1f%sF6000", space, axis, extra, amount, space); send_gcode(true, gcode); if (absolute_coords) { diff --git a/CYD-Klipper-Display/src/ui/panels/panel.h b/CYD-Klipper-Display/src/ui/panels/panel.h index b8c54e5..7b2aaa0 100644 --- a/CYD-Klipper-Display/src/ui/panels/panel.h +++ b/CYD-Klipper-Display/src/ui/panels/panel.h @@ -3,4 +3,5 @@ void settings_panel_init(lv_obj_t* panel); void temp_panel_init(lv_obj_t* panel); void print_panel_init(lv_obj_t* panel); -void move_panel_init(lv_obj_t* panel); \ No newline at end of file +void move_panel_init(lv_obj_t* panel); +void progress_panel_init(lv_obj_t* panel); \ No newline at end of file diff --git a/CYD-Klipper-Display/src/ui/panels/print_panel.cpp b/CYD-Klipper-Display/src/ui/panels/print_panel.cpp index 227f98e..a932ffa 100644 --- a/CYD-Klipper-Display/src/ui/panels/print_panel.cpp +++ b/CYD-Klipper-Display/src/ui/panels/print_panel.cpp @@ -1,6 +1,10 @@ #include "lvgl.h" #include "panel.h" +#include "../../core/data_setup.h" void print_panel_init(lv_obj_t* panel){ - + if (printer.state == PRINTER_STATE_PRINTING || printer.state == PRINTER_STATE_PAUSED || true){ + progress_panel_init(panel); + return; + } } \ No newline at end of file diff --git a/CYD-Klipper-Display/src/ui/panels/progress_panel.cpp b/CYD-Klipper-Display/src/ui/panels/progress_panel.cpp new file mode 100644 index 0000000..f7056de --- /dev/null +++ b/CYD-Klipper-Display/src/ui/panels/progress_panel.cpp @@ -0,0 +1,120 @@ +#include "panel.h" +#include "../../core/data_setup.h" +#include + +char time_buffer[12]; + +char* time_display(unsigned long time){ + unsigned long hours = time / 3600; + unsigned long minutes = (time % 3600) / 60; + unsigned long seconds = (time % 3600) % 60; + sprintf(time_buffer, "%02lu:%02lu:%02lu", hours, minutes, seconds); + return time_buffer; +} + +static void progress_bar_update(lv_event_t* e){ + lv_obj_t * bar = lv_event_get_target(e); + lv_bar_set_value(bar, printer.print_progress * 100, LV_ANIM_ON); +} + +static void update_printer_data_elapsed_time(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + lv_label_set_text(label, time_display(printer.elapsed_time_s)); +} + +static void update_printer_data_remaining_time(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + lv_label_set_text(label, time_display(printer.remaining_time_s)); +} + +static void update_printer_data_percentage(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char percentage_buffer[12]; + sprintf(percentage_buffer, "%.2f%%", printer.print_progress * 100); + lv_label_set_text(label, percentage_buffer); +} + +static void btn_click_stop(lv_event_t * e){ + // TODO: Implement +} + +static void btn_click_pause(lv_event_t * e){ + // TODO: Implement +} + +static void btn_click_resume(lv_event_t * e){ + // TODO: Implement +} + +void progress_panel_init(lv_obj_t* panel){ + auto panel_width = TFT_HEIGHT - 40; + auto panel_width_margin = panel_width - 30; + + // Filename + lv_obj_t * label = lv_label_create(panel); + lv_label_set_text(label, printer.print_filename); + lv_obj_align(label, LV_ALIGN_CENTER, 0, -40); + lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); + lv_obj_set_width(label, panel_width_margin); + + // Progress Bar + lv_obj_t * bar = lv_bar_create(panel); + lv_obj_align(bar, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_size(bar, panel_width_margin, 20); + lv_obj_add_event_cb(bar, progress_bar_update, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subsribe_obj(DATA_PRINTER_DATA, bar, NULL); + + // Elapsed Time + label = lv_label_create(panel); + lv_label_set_text(label, "???"); + lv_obj_align(label, LV_ALIGN_LEFT_MID, 10, 20); + lv_obj_add_event_cb(label, update_printer_data_elapsed_time, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); + + // Remaining Time + label = lv_label_create(panel); + lv_label_set_text(label, "???"); + lv_obj_align(label, LV_ALIGN_RIGHT_MID, -10, 20); + lv_obj_add_event_cb(label, update_printer_data_remaining_time, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); + + // Percentage + label = lv_label_create(panel); + lv_label_set_text(label, "???"); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 20); + lv_obj_add_event_cb(label, update_printer_data_percentage, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); + + // Stop Button + lv_obj_t * btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -10, -10); + lv_obj_set_size(btn, 40, 40); + lv_obj_add_event_cb(btn, btn_click_stop, LV_EVENT_CLICKED, NULL); + + label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_STOP); + lv_obj_center(label); + + // Resume Button + if (printer.state == PRINTER_STATE_PAUSED){ + btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -60, -10); + lv_obj_set_size(btn, 40, 40); + lv_obj_add_event_cb(btn, btn_click_resume, LV_EVENT_CLICKED, NULL); + + label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_PLAY); + lv_obj_center(label); + } + // Pause Button + else { + btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -60, -10); + lv_obj_set_size(btn, 40, 40); + lv_obj_add_event_cb(btn, btn_click_pause, LV_EVENT_CLICKED, NULL); + + label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_PAUSE); + lv_obj_center(label); + } +} \ No newline at end of file diff --git a/CYD-Klipper-Display/src/ui/panels/settings_panel.cpp b/CYD-Klipper-Display/src/ui/panels/settings_panel.cpp index 618ea11..c2d2069 100644 --- a/CYD-Klipper-Display/src/ui/panels/settings_panel.cpp +++ b/CYD-Klipper-Display/src/ui/panels/settings_panel.cpp @@ -1,6 +1,99 @@ #include "lvgl.h" #include "panel.h" +#include "../../core/screen_driver.h" +#include "../../conf/global_config.h" + +static void invert_color_switch(lv_event_t * e){ + auto state = lv_obj_get_state(lv_event_get_target(e)); + bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + global_config.invertColors = checked; + WriteGlobalConfig(); + set_invert_display(); +} + +static void reset_calibration_click(lv_event_t * e){ + global_config.screenCalibrated = false; + WriteGlobalConfig(); + ESP.restart(); +} + +static void reset_wifi_click(lv_event_t * e){ + global_config.wifiConfigured = false; + global_config.ipConfigured = false; + WriteGlobalConfig(); + ESP.restart(); +} + +static void light_mode_switch(lv_event_t * e){ + auto state = lv_obj_get_state(lv_event_get_target(e)); + bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + global_config.lightMode = checked; + WriteGlobalConfig(); + set_color_scheme(); +} + +static void theme_dropdown(lv_event_t * e){ + lv_obj_t * dropdown = lv_event_get_target(e); + auto selected = lv_dropdown_get_selected(dropdown); + global_config.color_scheme = selected; + WriteGlobalConfig(); + set_color_scheme(); +} void settings_panel_init(lv_obj_t* panel){ - + auto panel_width = TFT_HEIGHT - 40; + + lv_obj_t * btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_TOP_LEFT, 10, 5); + lv_obj_add_event_cb(btn, reset_wifi_click, LV_EVENT_CLICKED, NULL); + lv_obj_set_size(btn, panel_width / 2 - 15, 30); + + lv_obj_t * label = lv_label_create(btn); + lv_label_set_text(label, "WiFi Setup"); + lv_obj_center(label); + + btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_TOP_RIGHT, -10, 5); + lv_obj_add_event_cb(btn, reset_calibration_click, LV_EVENT_CLICKED, NULL); + lv_obj_set_size(btn, panel_width / 2 - 15, 30); + + label = lv_label_create(btn); + lv_label_set_text(label, "Touch Cal"); + lv_obj_center(label); + + + lv_obj_t * toggle = lv_switch_create(panel); + lv_obj_align(toggle, LV_ALIGN_TOP_RIGHT, -14, 57); + lv_obj_add_event_cb(toggle, invert_color_switch, LV_EVENT_VALUE_CHANGED, NULL); + + if (global_config.invertColors) + lv_obj_add_state(toggle, LV_STATE_CHECKED); + + label = lv_label_create(panel); + lv_label_set_text(label, "Invert Colors"); + lv_obj_align(label, LV_ALIGN_TOP_RIGHT, -10, 40); + lv_obj_set_style_text_font(label, &lv_font_montserrat_10, 0); + + toggle = lv_switch_create(panel); + lv_obj_align(toggle, LV_ALIGN_TOP_LEFT, 13, 57); + lv_obj_add_event_cb(toggle, light_mode_switch, LV_EVENT_VALUE_CHANGED, NULL); + + if (global_config.lightMode) + lv_obj_add_state(toggle, LV_STATE_CHECKED); + + label = lv_label_create(panel); + lv_label_set_text(label, "Light Mode"); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 40); + lv_obj_set_style_text_font(label, &lv_font_montserrat_10, 0); + + lv_obj_t * dropdown = lv_dropdown_create(panel); + lv_dropdown_set_options(dropdown, "Blue\nGreen\nGrey\nYellow\nOrange\nRed\nPurple"); + lv_dropdown_set_selected(dropdown, global_config.color_scheme); + lv_obj_align(dropdown, LV_ALIGN_TOP_MID, 0, 55); + lv_obj_add_event_cb(dropdown, theme_dropdown, LV_EVENT_VALUE_CHANGED, NULL); + + label = lv_label_create(panel); + lv_label_set_text(label, "Theme"); + lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 40); + lv_obj_set_style_text_font(label, &lv_font_montserrat_10, 0); } \ No newline at end of file diff --git a/CYD-Klipper-Display/src/ui/panels/temp_panel.cpp b/CYD-Klipper-Display/src/ui/panels/temp_panel.cpp index 3cd5397..ebb23d6 100644 --- a/CYD-Klipper-Display/src/ui/panels/temp_panel.cpp +++ b/CYD-Klipper-Display/src/ui/panels/temp_panel.cpp @@ -1,6 +1,151 @@ #include "lvgl.h" #include "panel.h" +#include "../../core/data_setup.h" +#include + +// False: Hotend, True: Bed +static bool hotend_or_bed = true; +static char hotend_buff[40]; +static char bed_buff[40]; + +static void update_printer_data_hotend_temp(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + sprintf(hotend_buff, "Hotend: %.0f C\nTarget: %.0f C", printer.extruder_temp, printer.extruder_target_temp); + lv_label_set_text(label, hotend_buff); +} + +static void update_printer_data_bed_temp(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + sprintf(bed_buff, "Bed: %.0f C\nTarget: %.0f C", printer.bed_temp, printer.bed_target_temp); + lv_label_set_text(label, bed_buff); +} + +static void keyboard_callback(lv_event_t * e){ + lv_event_code_t code = lv_event_get_code(e); + lv_obj_t * ta = lv_event_get_target(e); + lv_obj_t * kb = (lv_obj_t *)lv_event_get_user_data(e); + + if (code == LV_EVENT_READY) { + const char * text = lv_textarea_get_text(ta); + + int temp = atoi(text); + if (temp < 0 || temp > 500){ + return; + } + + Serial.printf("%d %s %d\n", hotend_or_bed, text, temp); + char gcode[64]; + const char* space = "%20"; + + if (hotend_or_bed){ + sprintf(gcode, "M140%sS%d", space, temp); + } else { + sprintf(gcode, "M104%sS%d", space, temp); + } + + send_gcode(true, gcode); + } + + if(code == LV_EVENT_DEFOCUSED || code == LV_EVENT_CANCEL || code == LV_EVENT_READY) { + lv_keyboard_set_textarea(kb, NULL); + lv_obj_del(kb); + lv_obj_del(ta); + } +} + +static void show_keyboard(lv_event_t * e){ + lv_obj_t * panel = (lv_obj_t *)lv_event_get_user_data(e); + lv_obj_t * keyboard = lv_keyboard_create(panel); + lv_obj_t * ta = lv_textarea_create(panel); + lv_obj_set_size(ta, 100, 30); + lv_obj_align(ta, LV_ALIGN_TOP_MID, 0, 40); + lv_textarea_set_max_length(ta, 3); + lv_textarea_set_one_line(ta, true); + lv_textarea_set_text(ta, ""); + lv_obj_add_event_cb(ta, keyboard_callback, LV_EVENT_ALL, keyboard); + + lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_NUMBER); + lv_keyboard_set_textarea(keyboard, ta); +} + +static void show_keyboard_with_hotend(lv_event_t * e){ + hotend_or_bed = false; + show_keyboard(e); +} + +static void show_keyboard_with_bed(lv_event_t * e){ + hotend_or_bed = true; + show_keyboard(e); +} + +static void cooldown_temp(lv_event_t * e){ + send_gcode(true, "M104%20S0"); + send_gcode(true, "M140%20S0"); +} + +static void btn_extrude(lv_event_t * e){ + send_gcode(true, "M83"); + send_gcode(true, "G1%20E25%20F300"); +} + +static void btn_retract(lv_event_t * e){ + send_gcode(true, "M83"); + send_gcode(true, "G1%20E-25%20F300"); +} void temp_panel_init(lv_obj_t* panel){ - + auto panel_width = TFT_HEIGHT - 40; + lv_obj_t * label = lv_label_create(panel); + lv_label_set_text(label, "Hotend"); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 10); + lv_obj_add_event_cb(label, update_printer_data_hotend_temp, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subscribe_obj(DATA_PRINTER_DATA, label, NULL); + + label = lv_label_create(panel); + lv_label_set_text(label, "Bed"); + lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 50); + lv_obj_add_event_cb(label, update_printer_data_bed_temp, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subscribe_obj(DATA_PRINTER_DATA, label, NULL); + + lv_obj_t * btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_TOP_RIGHT, -10, 10); + lv_obj_add_event_cb(btn, show_keyboard_with_hotend, LV_EVENT_CLICKED, panel); + + label = lv_label_create(btn); + lv_label_set_text(label, "Set"); + lv_obj_center(label); + + btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_TOP_RIGHT, -10, 50); + lv_obj_add_event_cb(btn, show_keyboard_with_bed, LV_EVENT_CLICKED, panel); + + label = lv_label_create(btn); + lv_label_set_text(label, "Set"); + lv_obj_center(label); + + btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_TOP_MID, 0, 90); + lv_obj_add_event_cb(btn, cooldown_temp, LV_EVENT_CLICKED, panel); + + label = lv_label_create(btn); + lv_label_set_text(label, "Cooldown"); + lv_obj_center(label); + + btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_BOTTOM_LEFT, 10, -5); + lv_obj_add_event_cb(btn, btn_extrude, LV_EVENT_CLICKED, NULL); + lv_obj_set_size(btn, panel_width / 2 - 15, 30); + + label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_DOWN " Extrude"); + lv_obj_center(label); + + btn = lv_btn_create(panel); + lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -10, -5); + lv_obj_add_event_cb(btn, btn_retract, LV_EVENT_CLICKED, NULL); + lv_obj_set_size(btn, panel_width / 2 - 15, 30); + + label = lv_label_create(btn); + lv_label_set_text(label, LV_SYMBOL_UP " Retract"); + lv_obj_center(label); } \ No newline at end of file