Skip to content

Commit

Permalink
Add experimental gcode img loading (unstable)
Browse files Browse the repository at this point in the history
  • Loading branch information
suchmememanyskill committed Nov 21, 2023
1 parent dccb10c commit 86aad72
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 12 deletions.
3 changes: 2 additions & 1 deletion CYD-Klipper/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"unordered_set": "cpp",
"vector": "cpp",
"string_view": "cpp",
"initializer_list": "cpp"
"initializer_list": "cpp",
"cstddef": "cpp"
}
}
2 changes: 1 addition & 1 deletion CYD-Klipper/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@ build_flags =
-DSMOOTH_FONT=1
-DSPI_FREQUENCY=55000000
-DSPI_READ_FREQUENCY=20000000
-DSPI_TOUCH_FREQUENCY=2500000
-DSPI_TOUCH_FREQUENCY=2500000
1 change: 1 addition & 0 deletions CYD-Klipper/src/conf/global_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ typedef struct _GLOBAL_CONFIG {
bool invertColors : 1;
bool rotateScreen : 1;
bool onDuringPrint : 1;
bool showGcodePreview : 1;
};
};
float screenCalXOffset;
Expand Down
6 changes: 3 additions & 3 deletions CYD-Klipper/src/conf/lv_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
#define LV_MEM_CUSTOM 0
#if LV_MEM_CUSTOM == 0
/*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
#define LV_MEM_SIZE (32U * 1024U) /*[bytes]*/
#define LV_MEM_SIZE (32U * 1800U) /*[bytes]*/

/*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
#define LV_MEM_ADR 0 /*0: unused*/
Expand Down Expand Up @@ -204,7 +204,7 @@
*LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
*LV_LOG_LEVEL_USER Only logs added by the user
*LV_LOG_LEVEL_NONE Do not log anything*/
#define LV_LOG_LEVEL LV_LOG_LEVEL_USER
#define LV_LOG_LEVEL LV_LOG_LEVEL_INFO

/*1: Print the log with 'printf';
*0: User need to register a callback with `lv_log_register_print_cb()`*/
Expand Down Expand Up @@ -603,7 +603,7 @@
#endif

/*PNG decoder library*/
#define LV_USE_PNG 0
#define LV_USE_PNG 1

/*BMP decoder library*/
#define LV_USE_BMP 0
Expand Down
17 changes: 17 additions & 0 deletions CYD-Klipper/src/core/data_setup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "../conf/global_config.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include "thumb_query.h"

const char *printer_state_messages[] = {
"Error",
Expand Down Expand Up @@ -34,6 +35,20 @@ void send_gcode(bool wait, const char *gcode)
}
}

void on_state_change(){
if (printer.state == PRINTER_STATE_PRINTING || printer.state == PRINTER_STATE_PAUSED){
if (global_config.showGcodePreview && printer.print_thumb.data == NULL){
printer.print_thumb = fetch_gcode_thumb(printer.print_filename);
}
}
else {
if (printer.print_thumb.data != NULL){
free(printer.print_thumb.data);
printer.print_thumb.data = NULL;
}
}
}

char filename_buff[512] = {0};

void fetch_printer_data()
Expand Down Expand Up @@ -153,6 +168,7 @@ void fetch_printer_data()
if (printer.state != printer_state || emit_state_update)
{
printer.state = printer_state;
on_state_change();
lv_msg_send(DATA_PRINTER_STATE, &printer);
}
}
Expand All @@ -178,5 +194,6 @@ void data_loop()
void data_setup()
{
printer.print_filename = filename_buff;
printer.print_thumb = {0};
fetch_printer_data();
}
7 changes: 5 additions & 2 deletions CYD-Klipper/src/core/data_setup.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#include "thumb_query.h"

enum {
PRINTER_STATE_ERROR = 0,
PRINTER_STATE_IDLE = 1,
Expand All @@ -23,8 +25,9 @@ typedef struct _Printer {
float elapsed_time_s;
float remaining_time_s;
float filament_used_mm;
char* print_filename; // 0 -> 1
float print_progress;
char* print_filename;
float print_progress; // 0 -> 1
ThumbImg print_thumb;
} Printer;

extern Printer printer;
Expand Down
89 changes: 89 additions & 0 deletions CYD-Klipper/src/core/thumb_query.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@

#include "thumb_query.h"
#include "data_setup.h"
#include "lvgl.h"
#include "../conf/global_config.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>

const unsigned int MAX_SIZE = 10000;
const unsigned int MAX_RES = 64;

ThumbImg fetch_gcode_thumb(const char* gcode_filename){
if (gcode_filename == NULL){
Serial.println("No gcode filename");
return {0};
}

String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/server/files/thumbnails?filename=" + String(gcode_filename);
HTTPClient client;
int httpCode = 0;
try {
client.begin(url.c_str());
httpCode = client.GET();
}
catch (...){
Serial.println("Exception while fetching gcode thumb location");
return {0};
}

if (httpCode == 200)
{
String payload = client.getString();
DynamicJsonDocument doc(4096);
deserializeJson(doc, payload);
auto result = doc["result"].as<JsonArray>();
int chosen_size = 0;
int chosen_width = 0;
const char* chosen_thumb = NULL;

for (auto file : result){
int width = file["width"];
int height = file["height"];
int size = file["size"];
const char* thumbnail = file["thumbnail_path"];

if (width != height)
continue;

if (size > MAX_SIZE)
continue;

if (width > MAX_RES)
continue;

if (size <= chosen_size)
continue;

chosen_size = size;
chosen_thumb = thumbnail;
chosen_width = width;
}

if (chosen_thumb == NULL) {
Serial.println("No thumb filename");
return {0};
}

Serial.printf("Fetching thumbnail: %s\n", chosen_thumb);
String thumb_url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/server/files/gcodes/" + String(chosen_thumb);
client.begin(thumb_url.c_str());
httpCode = client.GET();
if (httpCode == 200)
{
unsigned char* data_png = (unsigned char*)malloc(chosen_size + 1);
client.getStream().readBytes(data_png, chosen_size);
return {chosen_width, chosen_size, data_png};
}
else
{
Serial.printf("Failed to fetch gcode thumb: %d\n", httpCode);
}
}
else
{
Serial.printf("Failed to fetch gcode thumb location: %d\n", httpCode);
}

return {0};
}
9 changes: 9 additions & 0 deletions CYD-Klipper/src/core/thumb_query.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once

typedef struct _ThumbImg {
unsigned int width_height;
unsigned int size;
unsigned char* data;
} ThumbImg;

ThumbImg fetch_gcode_thumb(const char* gcode_filename);
53 changes: 48 additions & 5 deletions CYD-Klipper/src/ui/panels/progress_panel.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include "panel.h"
#include "../../core/data_setup.h"
#include <stdio.h>
#include <HardwareSerial.h>

char time_buffer[12];
lv_img_dsc_t img_header = {0};

char* time_display(unsigned long time){
unsigned long hours = time / 3600;
Expand Down Expand Up @@ -49,42 +51,83 @@ static void btn_click_resume(lv_event_t * e){
void progress_panel_init(lv_obj_t* panel){
auto panel_width = TFT_HEIGHT - 40;
auto panel_width_margin = panel_width - 30;
const bool has_gcode_preview = printer.print_thumb.data != NULL;

// 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);
if (has_gcode_preview)
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 10);
else
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);
if (has_gcode_preview)
lv_obj_align(bar, LV_ALIGN_TOP_MID, 0, 50);
else
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);
if (has_gcode_preview)
lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 70);
else
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);
if (has_gcode_preview)
lv_obj_align(label, LV_ALIGN_TOP_RIGHT, -10, 70);
else
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);
if (has_gcode_preview)
lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 70);
else
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);

if (has_gcode_preview){
// GCode Preview
lv_obj_t * img = lv_img_create(panel);
lv_img_cache_invalidate_src(&img_header);
memset(&img_header, 0, sizeof(img_header));
img_header.header.always_zero = 0;
img_header.header.w = printer.print_thumb.width_height;
img_header.header.h = printer.print_thumb.width_height;
img_header.data_size = printer.print_thumb.size;
img_header.header.cf = LV_IMG_CF_RAW_ALPHA;
img_header.data = printer.print_thumb.data;

lv_img_set_src(img, &img_header);
if (printer.print_thumb.width_height > 32) {
// Ajusted for 64x64 images
lv_img_set_zoom(img, 512);
lv_obj_align(img, LV_ALIGN_BOTTOM_LEFT, 20 + printer.print_thumb.width_height / 2, (10 + printer.print_thumb.width_height / 2) * -1);
}
else {
// Ajusted for 32x32 images
lv_img_set_zoom(img, 1024);
lv_obj_align(img, LV_ALIGN_BOTTOM_LEFT, 20 + printer.print_thumb.width_height * 1.5, (10 + printer.print_thumb.width_height * 1.5) * -1);
}
}

// Stop Button
lv_obj_t * btn = lv_btn_create(panel);
lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -10, -10);
Expand Down
16 changes: 16 additions & 0 deletions CYD-Klipper/src/ui/panels/settings_panel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,14 @@ static void on_during_print_switch(lv_event_t* e){
WriteGlobalConfig();
}

static void gcode_preview_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.showGcodePreview = checked;
// No effect until a print is started or the device is reset
WriteGlobalConfig();
}

int y_offset = 0;
const int y_element_size = 50;
const int y_seperator_size = 1;
Expand Down Expand Up @@ -197,4 +205,12 @@ void settings_panel_init(lv_obj_t* panel){
lv_obj_add_state(toggle, LV_STATE_CHECKED);

create_settings_widget("Screen On During Print", toggle, panel);

toggle = lv_switch_create(panel);
lv_obj_add_event_cb(toggle, gcode_preview_switch, LV_EVENT_VALUE_CHANGED, NULL);

if (global_config.showGcodePreview)
lv_obj_add_state(toggle, LV_STATE_CHECKED);

create_settings_widget("GCode Preview Image", toggle, panel);
}

0 comments on commit 86aad72

Please sign in to comment.