5 Commits

Author SHA1 Message Date
suchmememanyskill
d9d6789a21 TODO 2025-07-10 15:15:04 +02:00
suchmememanyskill
5df709e083 Don't set padding on root panel 2025-03-04 21:08:38 +01:00
suchmememanyskill
664862100f Feedback from almighty atomique 2025-03-04 21:04:16 +01:00
suchmememanyskill
3f5e02e8f7 Null check in printer state 2025-03-01 13:31:56 +01:00
suchmememanyskill
bbb65725fa New move screen 2025-03-01 13:29:17 +01:00
26 changed files with 401 additions and 1085 deletions

View File

@@ -33,7 +33,7 @@ jobs:
- uses: actions/setup-python@v5 - uses: actions/setup-python@v5
with: with:
python-version: '3.13' python-version: '3.9'
- name: Install PlatformIO Core - name: Install PlatformIO Core
run: pip install --upgrade platformio esptool run: pip install --upgrade platformio esptool

View File

@@ -49,7 +49,7 @@
"streambuf": "cpp", "streambuf": "cpp",
"cinttypes": "cpp", "cinttypes": "cpp",
"typeinfo": "cpp", "typeinfo": "cpp",
"*.tpp": "cpp" "lv_group.h": "c"
}, },
"cmake.configureOnOpen": false "cmake.configureOnOpen": false
} }

View File

@@ -1,69 +0,0 @@
{
"name": "ESP32-JC3248W535C",
"url": "https://www.aliexpress.com/item/1005007566315926.html",
"vendor": "Guition",
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi",
"partitions": "default_16MB.csv"
},
"core": "esp32",
"mcu": "esp32s3",
"variant": "esp32s3",
"f_cpu": "240000000L",
"f_flash": "80000000L",
"extra_flags": [
"-DLCD_WIDTH=320",
"-DLCD_HEIGHT=480",
"-DCYD_SCREEN_GAP_PX=8",
"-DCYD_SCREEN_FONT=lv_font_montserrat_14",
"-DCYD_SCREEN_FONT_SMALL=lv_font_montserrat_12",
"-DCYD_SCREEN_WIDTH_PX=LCD_WIDTH",
"-DCYD_SCREEN_HEIGHT_PX=LCD_HEIGHT",
"-DCYD_SCREEN_SIDEBAR_SIZE_PX=50",
"-DCYD_SCREEN_MIN_BUTTON_HEIGHT_PX=45",
"-DCYD_SCREEN_MIN_BUTTON_WIDTH_PX=45",
"-DLCD_CS=45",
"-DLCD_CLK=47",
"-DLCD_D0=21",
"-DLCD_D1=48",
"-DLCD_D2=40",
"-DLCD_D3=39",
"-DLCD_RST=-1",
"-DLCD_DC=8",
"-DTOUCH_SDA=4",
"-DTOUCH_SCL=8",
"-DTOUCH_ADDR=0x3B",
"-DLCD_BL_PIN=1",
"-DCYD_BOARD_JC3248W535C",
"-DCYD_SCREEN_DISABLE_TOUCH_CALIBRATION",
"-DUSER_SETUP_LOADED",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DCYD_SCREEN_VERTICAL=1"
],
"flash_mode": "qio",
"hwids": [
[
"0X303A",
"0x1001"
]
]
},
"upload": {
"flash_size": "16MB",
"flash_mode": "qio",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 921600
},
"frameworks": ["arduino", "espidf"],
"connectivity": ["wifi", "bluetooth"]
}

View File

@@ -1,66 +0,0 @@
{
"name": "ESP32-JC4827W543C",
"url": "https://s.click.aliexpress.com/e/_oEcVE26",
"vendor": "Guition",
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"memory_type": "qio_opi"
},
"core": "esp32",
"mcu": "esp32s3",
"variant": "esp32s3",
"f_cpu": "240000000L",
"f_flash": "80000000L",
"extra_flags": [
"-DBOARD_HAS_PSRAM",
"-DLCD_WIDTH=480",
"-DLCD_HEIGHT=270",
"-DCYD_SCREEN_GAP_PX=8",
"-DCYD_SCREEN_FONT=lv_font_montserrat_14",
"-DCYD_SCREEN_FONT_SMALL=lv_font_montserrat_12",
"-DCYD_SCREEN_WIDTH_PX=480",
"-DCYD_SCREEN_HEIGHT_PX=272",
"-DCYD_SCREEN_SIDEBAR_SIZE_PX=50",
"-DCYD_SCREEN_MIN_BUTTON_HEIGHT_PX=40",
"-DCYD_SCREEN_MIN_BUTTON_WIDTH_PX=45",
"-DLCD_CS=45",
"-DLCD_CLK=47",
"-DLCD_D0=21",
"-DLCD_D1=48",
"-DLCD_D2=40",
"-DLCD_D3=39",
"-DLCD_RST=-1",
"-DLCD_DC=8",
"-DLCD_BL_PIN=1",
"-DCYD_BOARD_JC4827W543C",
"-DCYD_SCREEN_DISABLE_TOUCH_CALIBRATION",
"-DUSER_SETUP_LOADED",
"-DARDUINO_USB_CDC_ON_BOOT=1",
"-DCYD_S3"
],
"flash_mode": "qio",
"hwids": [
[
"0X303A",
"0x1001"
]
]
},
"upload": {
"flash_size": "4MB",
"flash_mode": "qio",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"require_upload_port": true,
"speed": 921600
},
"frameworks": ["arduino", "espidf"],
"connectivity": ["wifi", "bluetooth"]
}

View File

@@ -1,142 +0,0 @@
{
"build": {
"arduino": {
"ldscript": "esp32s3_out.ld",
"partitions": "default_16MB.csv",
"memory_type": "qio_opi"
},
"core": "esp32",
"extra_flags": [
"'-D ARDUINO_ESP32S3_DEV'",
"'-D BOARD_HAS_PSRAM'",
"'-D ARDUINO_USB_MODE=1'",
"'-D ARDUINO_RUNNING_CORE=1'",
"'-D ARDUINO_EVENT_RUNNING_CORE=1'",
"'-D ARDUINO_USB_CDC_ON_BOOT=0'",
"'-D JC8048W550'",
"'-D LCD_WIDTH=800'",
"'-D LCD_HEIGHT=480'",
"'-D LVGL_BUFFER_PIXELS=(LCD_WIDTH*LCD_HEIGHT)'",
"'-D LVGL_BUFFER_MALLOC_FLAGS=(MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT)'",
"'-D GPIO_BCKL=2'",
"'-D LCD_ST7262_PAR'",
"'-D ST7262_PANEL_CONFIG_CLK_SRC=LCD_CLK_SRC_PLL160M'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_PCLK_HZ=(14.2*1000000)'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_H_RES=LCD_WIDTH'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_V_RES=LCD_HEIGHT'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_PULSE_WIDTH=4'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_BACK_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_HSYNC_FRONT_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_PULSE_WIDTH=4'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_BACK_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_VSYNC_FRONT_PORCH=8'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_HSYNC_IDLE_LOW=false'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_VSYNC_IDLE_LOW=false'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_DE_IDLE_HIGH=false'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_PCLK_ACTIVE_NEG=true'",
"'-D ST7262_PANEL_CONFIG_TIMINGS_FLAGS_PCLK_IDLE_HIGH=false'",
"'-D ST7262_PANEL_CONFIG_DATA_WIDTH=16'",
"'-D ST7262_PANEL_CONFIG_SRAM_TRANS_ALIGN=4'",
"'-D ST7262_PANEL_CONFIG_PSRAM_TRANS_ALIGN=64'",
"'-D ST7262_PANEL_CONFIG_HSYNC_GPIO_NUM=39'",
"'-D ST7262_PANEL_CONFIG_VSYNC_GPIO_NUM=41'",
"'-D ST7262_PANEL_CONFIG_DE_GPIO_NUM=40'",
"'-D ST7262_PANEL_CONFIG_PCLK_GPIO_NUM=42'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R0=8'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R1=3'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R2=46'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R3=9'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_R4=1'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G0=5'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G1=6'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G2=7'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G3=15'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G4=16'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_G5=4'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B0=45'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B1=48'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B2=47'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B3=21'",
"'-D ST7262_PANEL_CONFIG_DATA_GPIO_B4=14'",
"'-D ST7262_PANEL_CONFIG_DISP_GPIO_NUM=GPIO_NUM_NC'",
"'-D ST7262_PANEL_CONFIG_FLAGS_DISP_ACTIVE_LOW=false'",
"'-D ST7262_PANEL_CONFIG_FLAGS_RELAX_ON_IDLE=false'",
"'-D ST7262_PANEL_CONFIG_FLAGS_FB_IN_PSRAM=true'",
"'-D BOARD_HAS_TOUCH'",
"'-D TOUCH_GT911_I2C'",
"'-D GT911_I2C_HOST=I2C_NUM_0'",
"'-D GT911_I2C_CONFIG_SDA_IO_NUM=19'",
"'-D GT911_I2C_CONFIG_SCL_IO_NUM=20'",
"'-D GT911_I2C_CONFIG_SDA_PULLUP_EN=GPIO_PULLUP_DISABLE'",
"'-D GT911_I2C_CONFIG_SCL_PULLUP_EN=GPIO_PULLUP_DISABLE'",
"'-D GT911_I2C_CONFIG_MASTER_CLK_SPEED=400000'",
"'-D GT911_I2C_CONFIG_CLK_FLAGS=I2C_SCLK_SRC_FLAG_FOR_NOMAL'",
"'-D GT911_IO_I2C_CONFIG_DEV_ADDR=ESP_LCD_TOUCH_IO_I2C_GT911_ADDRESS'",
"'-D GT911_IO_I2C_CONFIG_CONTROL_PHASE_BYTES=1'",
"'-D GT911_IO_I2C_CONFIG_DC_BIT_OFFSET=0'",
"'-D GT911_IO_I2C_CONFIG_LCD_CMD_BITS=16'",
"'-D GT911_IO_I2C_CONFIG_LCD_PARAM_BITS=0'",
"'-D GT911_IO_I2C_CONFIG_FLAGS_DC_LOW_ON_DATA=false'",
"'-D GT911_IO_I2C_CONFIG_FLAGS_DISABLE_CONTROL_PHASE=true'",
"'-D GT911_TOUCH_CONFIG_X_MAX=LCD_WIDTH'",
"'-D GT911_TOUCH_CONFIG_Y_MAX=LCD_HEIGHT'",
"'-D GT911_TOUCH_CONFIG_RST_GPIO_NUM=38'",
"'-D GT911_TOUCH_CONFIG_INT_GPIO_NUM=18'",
"'-D GT911_TOUCH_CONFIG_LEVELS_RESET=0'",
"'-D GT911_TOUCH_CONFIG_LEVELS_INTERRUPT=0'",
"'-D TOUCH_SWAP_XY=false'",
"'-D TOUCH_SWAP_X=false'",
"'-D TOUCH_SWAP_Y=false'",
"'-D BOARD_HAS_TF'",
"'-D TF_CS=10'",
"'-D TF_SPI_MOSI=11'",
"'-D TF_SPI_SCLK=12'",
"'-D TF_SPI_MISO=13'",
"-DCYD_SCREEN_HEIGHT_PX=LCD_HEIGHT",
"-DCYD_SCREEN_WIDTH_PX=LCD_WIDTH",
"-DROTATION_INVERTED=LV_DISP_ROT_180",
"-DROTATION_NORMAL=LV_DISP_ROT_NONE",
"-DCYD_SCREEN_GAP_PX=15",
"-DCYD_SCREEN_MIN_BUTTON_HEIGHT_PX=60",
"-DCYD_SCREEN_MIN_BUTTON_WIDTH_PX=60",
"-DCYD_SCREEN_FONT=lv_font_montserrat_22",
"-DCYD_SCREEN_FONT_SMALL=lv_font_montserrat_16",
"-DCYD_SCREEN_SIDEBAR_SIZE_PX=70",
"-DCYD_SCREEN_DRIVER_ESP32_SMARTDISPLAY=0",
"-DCYD_SCREEN_DISABLE_TOUCH_CALIBRATION=1"
],
"f_cpu": "240000000L",
"f_flash": "80000000L",
"flash_mode": "qio",
"hwids": [
[
"0x303A",
"0x1001"
]
],
"mcu": "esp32s3",
"variant": "esp32s3"
},
"connectivity": [
"wifi"
],
"debug": {
"openocd_target": "esp32s3.cfg"
},
"frameworks": [
"arduino",
"espidf"
],
"name": "esp32-JC8048W550",
"upload": {
"flash_size": "16MB",
"maximum_ram_size": 327680,
"maximum_size": 16777216,
"use_1200bps_touch": true,
"wait_for_upload_port": true,
"require_upload_port": true,
"speed": 460800
},
"url": "https://www.aliexpress.com/item/1005006715581887.html",
"vendor": "Guition"
}

View File

@@ -14,21 +14,21 @@ board = esp32dev
framework = arduino framework = arduino
monitor_speed = 115200 monitor_speed = 115200
debug_build_flags = -Os debug_build_flags = -Os
lib_deps = lib_deps =
https://github.com/suchmememanyskill/esp32-smartdisplay#9c1d737 https://github.com/suchmememanyskill/esp32-smartdisplay#9c1d737
bblanchon/ArduinoJson@^7.0.0 bblanchon/ArduinoJson@^7.0.0
plageoj/UrlEncode@^1.0.1 plageoj/UrlEncode@^1.0.1
knolleary/PubSubClient@^2.8 knolleary/PubSubClient@^2.8
WiFiClientSecure WiFiClientSecure
monitor_filters = esp32_exception_decoder monitor_filters = esp32_exception_decoder
build_flags = build_flags =
-DLV_CONF_PATH="../../../../src/conf/lv_conf.h" -DLV_CONF_PATH="../../../../src/conf/lv_conf.h"
extra_scripts = extra_scripts =
pre:extract_commit.py pre:extract_commit.py
[env:esp32-2432S028R] [env:esp32-2432S028R]
board = esp32-2432S028R board = esp32-2432S028R
lib_deps = lib_deps =
SPI SPI
https://github.com/suchmememanyskill/lvgl https://github.com/suchmememanyskill/lvgl
https://github.com/Bodmer/TFT_eSPI.git https://github.com/Bodmer/TFT_eSPI.git
@@ -40,7 +40,7 @@ lib_deps =
[env:esp32-3248S035C] [env:esp32-3248S035C]
board = esp32-3248S035C board = esp32-3248S035C
lib_deps = lib_deps =
SPI SPI
https://github.com/suchmememanyskill/lvgl https://github.com/suchmememanyskill/lvgl
https://github.com/Bodmer/TFT_eSPI.git https://github.com/Bodmer/TFT_eSPI.git
@@ -52,7 +52,7 @@ lib_deps =
[env:esp32-3248S035C-V] [env:esp32-3248S035C-V]
board = esp32-3248S035C-vertical board = esp32-3248S035C-vertical
lib_deps = lib_deps =
SPI SPI
https://github.com/suchmememanyskill/lvgl https://github.com/suchmememanyskill/lvgl
https://github.com/Bodmer/TFT_eSPI.git https://github.com/Bodmer/TFT_eSPI.git
@@ -97,7 +97,7 @@ board = esp32-2432S022C-vertical
[env:esp32-CROWPANEL-28R] [env:esp32-CROWPANEL-28R]
board = esp32-CROWPANEL-28R board = esp32-CROWPANEL-28R
lib_deps = lib_deps =
SPI SPI
https://github.com/suchmememanyskill/lvgl https://github.com/suchmememanyskill/lvgl
https://github.com/Bodmer/TFT_eSPI.git https://github.com/Bodmer/TFT_eSPI.git
@@ -108,37 +108,12 @@ lib_deps =
[env:esp32-CROWPANEL-35C] [env:esp32-CROWPANEL-35C]
board = esp32-CROWPANEL-35C board = esp32-CROWPANEL-35C
lib_deps = lib_deps =
SPI SPI
https://github.com/suchmememanyskill/lvgl https://github.com/suchmememanyskill/lvgl
https://github.com/lovyan03/LovyanGFX@1.2.7 https://github.com/lovyan03/LovyanGFX@1.2.0
bblanchon/ArduinoJson@^7.0.0 bblanchon/ArduinoJson@^7.0.0
plageoj/UrlEncode@^1.0.1 plageoj/UrlEncode@^1.0.1
knolleary/PubSubClient@^2.8 knolleary/PubSubClient@^2.8
WiFiClientSecure WiFiClientSecure
[env:esp32-JC8048W550]
board = esp32-JC8048W550
[env:ESP32-JC3248W535C]
board = esp32-JC3248W535C
lib_deps =
SPI
moononournation/GFX Library for Arduino
lvgl/lvgl@^8.4.0
plageoj/UrlEncode
bblanchon/ArduinoJson@^7.0.0
knolleary/PubSubClient@^2.8
WiFiClientSecure
[env:esp32-JC4827W543C]
board = esp32-JC4827W543C
lib_deps =
SPI
https://github.com/moononournation/Arduino_GFX#v1.4.9
https://github.com/mmMicky/TouchLib#ccaedcd9155ef8a6560ae9f594ea92e32c68020f
lvgl/lvgl@^8.4.0
plageoj/UrlEncode
bblanchon/ArduinoJson@^7.0.0
knolleary/PubSubClient@^2.8
WiFiClientSecure

View File

@@ -2,7 +2,7 @@
#include "../printer_integration.hpp" #include "../printer_integration.hpp"
#include <ArduinoJson.h> #include <ArduinoJson.h>
#include <WiFiClientSecure.h> #include <WifiClientSecure.h>
enum BambuSpeedProfile enum BambuSpeedProfile
{ {

View File

@@ -161,7 +161,7 @@ struct
}; };
} __internal_bambu_file_state = {}; } __internal_bambu_file_state = {};
#define SET_BOOL_STATE(bool_name, func_name) static void func_name (lv_event_t * e) { bool_name = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); } #define SET_BOOL_STATE(bool_name, func_name) static void func_name (lv_event_t * e) { auto state = lv_obj_get_state(lv_event_get_target(e)); bool_name = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); }
SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_use_ams, set_bambu_option_use_ams) SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_use_ams, set_bambu_option_use_ams)
SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_timelapse, set_bambu_option_timelapse) SET_BOOL_STATE(__internal_bambu_file_state.bambu_option_timelapse, set_bambu_option_timelapse)

View File

@@ -1,184 +0,0 @@
#ifdef CYD_BOARD_JC3248W535C
#include "../screen_driver.h"
#include <databus/Arduino_ESP32QSPI.h>
#include <display/Arduino_AXS15231B.h>
#include <canvas/Arduino_Canvas.h>
#include "lvgl.h"
#include "../lv_setup.h"
#include "../../conf/global_config.h"
#include <Wire.h>
#define CPU_FREQ_HIGH 240
#define CPU_FREQ_LOW 80
struct TouchPoint {
uint8_t gesture;
uint8_t num;
uint8_t x_h : 4;
uint8_t _pad1 : 2;
uint8_t event : 2;
uint8_t x_l;
uint8_t y_h : 4;
uint8_t _pad2 : 4;
uint8_t y_l;
} __attribute__((packed));
static Arduino_ESP32QSPI qspiBus(
LCD_CS, LCD_CLK,
LCD_D0, LCD_D1,
LCD_D2, LCD_D3,
false);
Arduino_GFX *gfx = new Arduino_AXS15231B(
&qspiBus, -1, 2, true,
LCD_WIDTH, LCD_HEIGHT,
0, 0, 0, 0);
#ifdef CYD_SCREEN_VERTICAL
static bool horizontal = false;
static Arduino_Canvas canvas(CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX, gfx, 0, 0);
#else
static bool horizontal = true;
static Arduino_Canvas canvas(CYD_SCREEN_HEIGHT_PX, CYD_SCREEN_WIDTH_PX, gfx, 0, 0);
#endif
static lv_disp_draw_buf_t draw_buf;
static lv_color_t *buf = nullptr;
static lv_disp_t *main_disp = nullptr;
void screen_setBrightness(uint8_t brightness)
{
uint32_t duty = (4095UL * brightness) / 255UL;
ledcWrite(0, duty);
}
void screen_lv_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p)
{
int x = area->x1;
int y = area->y1;
int w = area->x2 - area->x1 + 1;
int h = area->y2 - area->y1 + 1;
canvas.draw16bitRGBBitmap(x, y, (uint16_t *)color_p, w, h);
canvas.flush();
lv_disp_flush_ready(disp);
}
// Reads 1 touch point from AXS15231B controller at I2C addr 0x3B
bool read_touch(uint16_t &x, uint16_t &y) {
const uint8_t addr = 0x3B;
const uint8_t read_cmd[11] = {
0xB5, 0xAB, 0xA5, 0x5A, 0x00, 0x00,
0x00, 8, // length of expected reply (MSB, LSB)
0x00, 0x00, 0x00
};
Wire.beginTransmission(addr);
Wire.write(read_cmd, sizeof(read_cmd));
if (Wire.endTransmission(false) != 0) {
return false;
}
uint8_t data[8] = {0};
if (Wire.requestFrom(addr, (uint8_t)sizeof(data)) != sizeof(data)) {
return false;
}
for (uint8_t i = 0; i < sizeof(data); i++) {
data[i] = Wire.read();
}
TouchPoint *p = (TouchPoint *)data;
if (p->num > 0 && p->num <= 2) {
x = ((p->x_h & 0x0F) << 8) | p->x_l;
y = ((p->y_h & 0x0F) << 8) | p->y_l;
// Clamp to screen bounds
if (x >= CYD_SCREEN_WIDTH_PX) x = CYD_SCREEN_WIDTH_PX - 1;
if (y >= CYD_SCREEN_HEIGHT_PX) y = CYD_SCREEN_HEIGHT_PX - 1;
return true;
}
return false;
}
void screen_lv_touchRead(lv_indev_drv_t * /*indev_driver*/, lv_indev_data_t *data)
{
uint16_t x, y;
if (read_touch(x, y)) {
x = min(x, uint16_t(CYD_SCREEN_WIDTH_PX - 1));
y = min(y, uint16_t(CYD_SCREEN_HEIGHT_PX - 1));
// Adjust coordinates based on screen rotation
if (global_config.rotate_screen) {
// Assuming rotation = 2 (180 degrees)
x = CYD_SCREEN_WIDTH_PX - x;
y = CYD_SCREEN_HEIGHT_PX - y;
}
data->state = LV_INDEV_STATE_PR;
data->point.x = x;
data->point.y = y;
} else {
data->state = LV_INDEV_STATE_REL;
}
}
void set_invert_display()
{
gfx->invertDisplay(global_config.printer_config[global_config.printer_index].invert_colors);
}
void screen_setup()
{
pinMode(LCD_BL_PIN, OUTPUT);
ledcSetup(0, 5000, 12);
ledcAttachPin(LCD_BL_PIN, 0);
screen_setBrightness(255);
// gfx->begin();
canvas.begin();
gfx->invertDisplay(true); // OK after begin()
gfx->setRotation(global_config.rotate_screen ? 2 : 0);
canvas.fillScreen(0x0000);
canvas.flush();
Wire.begin(TOUCH_SDA, TOUCH_SCL);
lv_init();
// Allocate full canvas buffer for LVGL
buf = (lv_color_t *)heap_caps_malloc(
CYD_SCREEN_WIDTH_PX * CYD_SCREEN_HEIGHT_PX * sizeof(lv_color_t),
MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
assert(buf);
lv_disp_draw_buf_init(&draw_buf, buf, NULL, CYD_SCREEN_WIDTH_PX * CYD_SCREEN_HEIGHT_PX);
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.flush_cb = screen_lv_flush;
disp_drv.draw_buf = &draw_buf;
disp_drv.hor_res = CYD_SCREEN_WIDTH_PX;
disp_drv.ver_res = CYD_SCREEN_HEIGHT_PX;
if(horizontal){
main_disp = lv_disp_drv_register(&disp_drv);
lv_disp_set_rotation(main_disp, LV_DISP_ROT_90);
} else {
lv_disp_drv_register(&disp_drv);
}
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = screen_lv_touchRead;
lv_indev_drv_register(&indev_drv);
}
#endif // CYD_BOARD_JC3248W535C

View File

@@ -1,85 +0,0 @@
#ifdef CYD_BOARD_JC4827W543C
#include "../screen_driver.h"
#include <Arduino_GFX_Library.h>
#include "lvgl.h"
#include "../lv_setup.h"
#include "../../conf/global_config.h"
#include "ESP32-JC4827W543C_touch.h"
#define CPU_FREQ_HIGH 240
#define CPU_FREQ_LOW 80
Arduino_DataBus *bus = new Arduino_ESP32QSPI(LCD_CS, LCD_CLK, LCD_D0, LCD_D1, LCD_D2, LCD_D3);
Arduino_NV3041A *panel = new Arduino_NV3041A(bus, LCD_RST, 0, true);
static lv_disp_draw_buf_t draw_buf;
static lv_disp_drv_t disp_drv;
static lv_color_t disp_draw_buf[LCD_WIDTH * 48];
void screen_setBrightness(uint8_t brightness)
{
uint32_t duty = 4095 * brightness / 255;
ledcWrite(0, duty);
}
void screen_lv_flush(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);
panel->startWrite();
panel->setAddrWindow(area->x1, area->y1, w, h);
panel->writePixels((uint16_t *)&color_p->full, w * h);
panel->endWrite();
lv_disp_flush_ready(disp);
}
void IRAM_ATTR screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
if (touch_has_signal() && touch_touched())
{
data->state = LV_INDEV_STATE_PR;
data->point.x = touch_last_x;
data->point.y = touch_last_y;
}
else
{
data->state = LV_INDEV_STATE_REL;
}
}
void set_invert_display()
{
panel->invertDisplay(global_config.printer_config[global_config.printer_index].invert_colors);
}
void screen_setup()
{
pinMode(LCD_BL_PIN, OUTPUT);
ledcSetup(0, 5000, 12);
ledcAttachPin(LCD_BL_PIN, 0);
screen_setBrightness(128);
panel->begin();
panel->setRotation(global_config.rotate_screen ? 2 : 0);
touch_init(panel->width(), panel->height(), panel->getRotation());
lv_init();
lv_disp_draw_buf_init(&draw_buf, disp_draw_buf, NULL, LCD_WIDTH * 48);
lv_disp_drv_init(&disp_drv);
disp_drv.flush_cb = screen_lv_flush;
disp_drv.draw_buf = &draw_buf;
disp_drv.hor_res = CYD_SCREEN_WIDTH_PX;
disp_drv.ver_res = CYD_SCREEN_HEIGHT_PX;
lv_disp_drv_register(&disp_drv);
static lv_indev_drv_t indev_drv;
lv_indev_drv_init(&indev_drv);
indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = screen_lv_touchRead;
lv_indev_drv_register(&indev_drv);
}
#endif // CYD_BOARD_JC4827W543C

View File

@@ -1,196 +0,0 @@
/*******************************************************************************
*
* TouchLib https://github.com/mmMicky/TouchLib
Add Library from ZIP: TouchLib-main.zip
*
* Touch libraries:
* XPT2046: https://github.com/PaulStoffregen/XPT2046_Touchscreen.git
*
* Capacitive touchscreen libraries
* TouchLib: https://github.com/mmMicky/TouchLib.git
******************************************************************************/
/* uncomment for XPT2046 */
// #define TOUCH_XPT2046
// #define TOUCH_XPT2046_SCK 12
// #define TOUCH_XPT2046_MISO 13
// #define TOUCH_XPT2046_MOSI 11
// #define TOUCH_XPT2046_CS 38
// #define TOUCH_XPT2046_INT 3
// #define TOUCH_XPT2046_ROTATION 0
// #define TOUCH_XPT2046_SAMPLES 50
//uncomment for most capacitive touchscreen
#define TOUCH_MODULES_GT911 // GT911 / CST_SELF / CST_MUTUAL / ZTW622 / L58 / FT3267 / FT5x06
#define TOUCH_MODULE_ADDR GT911_SLAVE_ADDRESS1 // CTS328_SLAVE_ADDRESS / L58_SLAVE_ADDRESS / CTS826_SLAVE_ADDRESS / CTS820_SLAVE_ADDRESS / CTS816S_SLAVE_ADDRESS / FT3267_SLAVE_ADDRESS / FT5x06_ADDR / GT911_SLAVE_ADDRESS1 / GT911_SLAVE_ADDRESS2 / ZTW622_SLAVE1_ADDRESS / ZTW622_SLAVE2_ADDRESS
#define TOUCH_SCL 4
#define TOUCH_SDA 8
#define TOUCH_RES 38
#define TOUCH_INT 3
// Please fill below values from Arduino_GFX Example - TouchCalibration
bool touch_swap_xy = false;
int16_t touch_map_x1 = -1;
int16_t touch_map_x2 = -1;
int16_t touch_map_y1 = -1;
int16_t touch_map_y2 = -1;
int16_t touch_max_x = 0, touch_max_y = 0;
int16_t touch_raw_x = 0, touch_raw_y = 0;
int16_t touch_last_x = 0, touch_last_y = 0;
#if defined(TOUCH_XPT2046)
#include <XPT2046_Touchscreen.h>
#include <SPI.h>
XPT2046_Touchscreen ts(TOUCH_XPT2046_CS, TOUCH_XPT2046_INT);
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
#include <Wire.h>
#include <TouchLib.h>
TouchLib touch(Wire, TOUCH_SDA, TOUCH_SCL, TOUCH_MODULE_ADDR);
#endif // TouchLib
void touch_init(int16_t w, int16_t h, uint8_t r)
{
touch_max_x = w - 1;
touch_max_y = h - 1;
if (touch_map_x1 == -1)
{
switch (r)
{
case 3:
touch_swap_xy = true;
touch_map_x1 = touch_max_x;
touch_map_x2 = 0;
touch_map_y1 = 0;
touch_map_y2 = touch_max_y;
break;
case 2:
touch_swap_xy = false;
touch_map_x1 = touch_max_x;
touch_map_x2 = 0;
touch_map_y1 = touch_max_y;
touch_map_y2 = 0;
break;
case 1:
touch_swap_xy = true;
touch_map_x1 = 0;
touch_map_x2 = touch_max_x;
touch_map_y1 = touch_max_y;
touch_map_y2 = 0;
break;
default: // case 0:
touch_swap_xy = false;
touch_map_x1 = 0;
touch_map_x2 = touch_max_x;
touch_map_y1 = 0;
touch_map_y2 = touch_max_y;
break;
}
}
#if defined(TOUCH_XPT2046)
SPI.begin(TOUCH_XPT2046_SCK, TOUCH_XPT2046_MISO, TOUCH_XPT2046_MOSI, TOUCH_XPT2046_CS);
ts.begin();
ts.setRotation(TOUCH_XPT2046_ROTATION);
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
// Reset touchscreen
#if (TOUCH_RES > 0)
pinMode(TOUCH_RES, OUTPUT);
digitalWrite(TOUCH_RES, 0);
delay(200);
digitalWrite(TOUCH_RES, 1);
delay(200);
#endif
Wire.begin(TOUCH_SDA, TOUCH_SCL);
touch.init();
#endif // TouchLib
}
bool touch_has_signal()
{
#if defined(TOUCH_XPT2046)
return ts.tirqTouched();
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
// TODO: implement TOUCH_INT
return true;
#endif // TouchLib
return false;
}
void translate_touch_raw()
{
if (touch_swap_xy)
{
touch_last_x = map(touch_raw_y, touch_map_x1, touch_map_x2, 0, touch_max_x);
touch_last_y = map(touch_raw_x, touch_map_y1, touch_map_y2, 0, touch_max_y);
}
else
{
touch_last_x = map(touch_raw_x, touch_map_x1, touch_map_x2, 0, touch_max_x);
touch_last_y = map(touch_raw_y, touch_map_y1, touch_map_y2, 0, touch_max_y);
}
// Serial.printf("touch_raw_x: %d, touch_raw_y: %d, touch_last_x: %d, touch_last_y: %d\n", touch_raw_x, touch_raw_y, touch_last_x, touch_last_y);
}
bool touch_touched()
{
#if defined(TOUCH_XPT2046)
if (ts.touched())
{
TS_Point p = ts.getPoint();
touch_raw_x = p.x;
touch_raw_y = p.y;
int max_z = p.z;
int count = 0;
while ((ts.touched()) && (count < TOUCH_XPT2046_SAMPLES))
{
count++;
TS_Point p = ts.getPoint();
if (p.z > max_z)
{
touch_raw_x = p.x;
touch_raw_y = p.y;
max_z = p.z;
}
// Serial.printf("touch_raw_x: %d, touch_raw_y: %d, p.z: %d\n", touch_raw_x, touch_raw_y, p.z);
}
translate_touch_raw();
return true;
}
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
if (touch.read())
{
TP_Point t = touch.getPoint(0);
touch_raw_x = t.x;
touch_raw_y = t.y;
touch_last_x = touch_raw_x;
touch_last_y = touch_raw_y;
translate_touch_raw();
return true;
}
#endif // TouchLib
return false;
}
bool touch_released()
{
#if defined(TOUCH_XPT2046)
return true;
#elif defined(TOUCH_MODULE_ADDR) // TouchLib
return false;
#endif // TouchLib
return false;
}

View File

@@ -271,15 +271,9 @@ int SerialKlipperPrinter::get_power_devices_count()
bool SerialKlipperPrinter::set_power_device_state(const char* device_name, bool state) bool SerialKlipperPrinter::set_power_device_state(const char* device_name, bool state)
{ {
String request = "/machine/device_power/device?device=" + urlEncode(device_name) + "&action=" + (state ? "on" : "off"); String request = "/machine/device_power/device?device=" + urlEncode(device_name) + "&action=" + (state ? "on" : "off");
return make_serial_request_nocontent(HttpPost, request.c_str()); return make_serial_request_nocontent(HttpGet, request.c_str());
} }
#ifdef CYD_S3
#define MAX_FILE_LIST_SIZE 200
#else
#define MAX_FILE_LIST_SIZE 20
#endif
Files SerialKlipperPrinter::get_files() Files SerialKlipperPrinter::get_files()
{ {
Files files_result = {0}; Files files_result = {0};
@@ -297,7 +291,7 @@ Files SerialKlipperPrinter::get_files()
return files_result; return files_result;
} }
parse_file_list(doc, files, MAX_FILE_LIST_SIZE); parse_file_list(doc, files, 20);
files_result.available_files = (char**)malloc(sizeof(char*) * files.size()); files_result.available_files = (char**)malloc(sizeof(char*) * files.size());

View File

@@ -18,13 +18,16 @@ void KlipperPrinter::parse_state(JsonDocument &in)
const char *state = status["webhooks"]["state"]; const char *state = status["webhooks"]["state"];
const char *message = status["webhooks"]["state_message"]; const char *message = status["webhooks"]["state_message"];
if (strcmp(state, "ready") == 0 && printer_data.state == PrinterStateError) if (state != NULL)
{ {
printer_data.state = PrinterStateIdle; if (strcmp(state, "ready") == 0 && printer_data.state == PrinterStateError)
} {
else if ((strcmp(state, "shutdown") == 0 || strcmp(state, "error") == 0) && printer_data.state != PrinterStateError) printer_data.state = PrinterStateIdle;
{ }
printer_data.state = PrinterStateError; else if ((strcmp(state, "shutdown") == 0 || strcmp(state, "error") == 0) && printer_data.state != PrinterStateError)
{
printer_data.state = PrinterStateError;
}
} }
if (message != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, message))) if (message != NULL && (printer_data.state_message == NULL || strcmp(printer_data.state_message, message)))
@@ -56,6 +59,12 @@ void KlipperPrinter::parse_state(JsonDocument &in)
{ {
const char *homed_axis = status["toolhead"]["homed_axes"]; const char *homed_axis = status["toolhead"]["homed_axes"];
printer_data.homed_axis = strcmp(homed_axis, "xyz") == 0; printer_data.homed_axis = strcmp(homed_axis, "xyz") == 0;
for (int i = 0; i < 3; i++)
{
printer_data.position_min[i] = status["toolhead"]["axis_minimum"][i];
printer_data.position_max[i] = status["toolhead"]["axis_maximum"][i];
}
} }
if (status.containsKey("gcode_move")) if (status.containsKey("gcode_move"))

View File

@@ -82,6 +82,8 @@ typedef struct _PrinterData {
float temperatures[10]; float temperatures[10];
float target_temperatures[10]; float target_temperatures[10];
float position[3]; float position[3];
float position_min[3];
float position_max[3];
float elapsed_time_s; float elapsed_time_s;
float printed_time_s; float printed_time_s;
float remaining_time_s; float remaining_time_s;

View File

@@ -47,7 +47,8 @@ int macros_add_macros_to_panel(lv_obj_t * root_panel, BasePrinter* printer)
static void power_device_toggle(lv_event_t * e) static void power_device_toggle(lv_event_t * e)
{ {
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
DoubleStorage* device = (DoubleStorage*)lv_event_get_user_data(e); DoubleStorage* device = (DoubleStorage*)lv_event_get_user_data(e);
LOG_F(("Power Device: %s, State: %d -> %d\n", device->power_device_name, !checked, checked)) LOG_F(("Power Device: %s, State: %d -> %d\n", device->power_device_name, !checked, checked))

View File

@@ -344,18 +344,24 @@ static void root_panel_state_update(lv_event_t * e){
if (last_homing_state == get_current_printer_data()->homed_axis) if (last_homing_state == get_current_printer_data()->homed_axis)
return; return;
PrinterType printer_type = get_current_printer()->printer_config->printer_type;
bool is_klipper = printer_type == PrinterTypeKlipper || printer_type == PrinterTypeKlipperSerial;
lv_obj_t * panel = lv_event_get_target(e); lv_obj_t * panel = lv_event_get_target(e);
last_homing_state = get_current_printer_data()->homed_axis; last_homing_state = get_current_printer_data()->homed_axis;
lv_obj_clean(panel); lv_obj_clean(panel);
if (get_current_printer_data()->homed_axis) if (get_current_printer_data()->homed_axis && is_klipper)
move_panel_slider_init(panel);
else if (get_current_printer_data()->homed_axis)
root_panel_steppers_locked(panel); root_panel_steppers_locked(panel);
else else
root_panel_steppers_unlocked(panel); root_panel_steppers_unlocked(panel);
} }
void move_panel_init(lv_obj_t* panel){ void move_panel_init(lv_obj_t* panel)
{
if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting){ if (get_current_printer_data()->state == PrinterState::PrinterStatePrinting){
stats_panel_init(panel); stats_panel_init(panel);
return; return;

View File

@@ -0,0 +1,257 @@
#include "panel.h"
#include "lvgl.h"
#include "../../core/data_setup.h"
#include "../nav_buttons.h"
#include "../ui_utils.h"
#include "../../core/printer_integration.hpp"
#include "../../core/current_printer.h"
static void line_custom_set(const char * axis, const char *text)
{
float pos = atof(text);
if (pos < 0 || pos > 500)
return;
current_printer_move_printer(axis, pos, false);
}
static void x_line_custom_callback(lv_event_t * e)
{
const char * text = lv_textarea_get_text(lv_event_get_target(e));
line_custom_set("X", text);
}
static void y_line_custom_callback(lv_event_t * e)
{
const char * text = lv_textarea_get_text(lv_event_get_target(e));
line_custom_set("Y", text);
}
static void z_line_custom_callback(lv_event_t * e)
{
const char * text = lv_textarea_get_text(lv_event_get_target(e));
line_custom_set("Z", text);
}
static void x_line_custom(lv_event_t * e)
{
lv_create_keyboard_text_entry(x_line_custom_callback, "Set X position", LV_KEYBOARD_MODE_NUMBER, LV_PCT(75), 6);
}
static void y_line_custom(lv_event_t * e)
{
lv_create_keyboard_text_entry(y_line_custom_callback, "Set Y position", LV_KEYBOARD_MODE_NUMBER, LV_PCT(75), 6);
}
static void z_line_custom(lv_event_t * e)
{
lv_create_keyboard_text_entry(z_line_custom_callback, "Set Z position", LV_KEYBOARD_MODE_NUMBER, LV_PCT(75), 6);
}
static void pos_update(lv_event_t * e, const char* target_template, float target)
{
lv_obj_t* obj = lv_event_get_target(e);
lv_obj_t* slider = (lv_obj_t*)lv_event_get_user_data(e);
if (lv_slider_is_dragged(slider))
{
return;
}
if (lv_obj_check_type(obj, &lv_label_class))
{
char pos_buff[12];
sprintf(pos_buff, target_template, target);
lv_label_set_text(obj, pos_buff);
}
else
{
lv_slider_set_value(obj, target, LV_ANIM_ON);
}
}
static void x_pos_update(lv_event_t * e)
{
pos_update(e, "%.1f " LV_SYMBOL_EDIT, get_current_printer_data()->position[0]);
}
static void y_pos_update(lv_event_t * e)
{
pos_update(e, "%.1f", get_current_printer_data()->position[1]);
}
static void z_pos_update(lv_event_t * e)
{
pos_update(e, "%.2f", get_current_printer_data()->position[2]);
}
static void x_slider_update(lv_event_t * e)
{
current_printer_move_printer("X", lv_slider_get_value(lv_event_get_target(e)), false);
}
static void y_slider_update(lv_event_t * e)
{
current_printer_move_printer("Y", lv_slider_get_value(lv_event_get_target(e)), false);
}
static void z_slider_update(lv_event_t * e)
{
current_printer_move_printer("Z", lv_slider_get_value(lv_event_get_target(e)), false);
}
static void home_button_click(lv_event_t * e)
{
current_printer_execute_feature(PrinterFeatures::PrinterFeatureHome);
}
static void disable_steppers_button_click(lv_event_t * e)
{
current_printer_execute_feature(PrinterFeatures::PrinterFeatureDisableSteppers);
}
static void set_label_slider_position(lv_event_t * e)
{
lv_obj_t* slider = lv_event_get_target(e);
lv_obj_t* label = (lv_obj_t*)lv_event_get_user_data(e);
if (lv_slider_is_dragged(slider))
{
lv_label_set_text_fmt(label, "%d", lv_slider_get_value(slider));
}
}
static void switch_to_params_panel_button_click(lv_event_t * e)
{
lv_obj_t * panel = lv_event_get_target(e);
nav_buttons_setup(PANEL_STATS);
}
static void make_vertical_slider(
lv_obj_t* parent,
const char* axis,
lv_event_cb_t position_change,
lv_event_cb_t on_slider_change,
lv_event_cb_t on_edit,
float min,
float max)
{
lv_obj_t* root = lv_create_empty_panel(parent);
lv_layout_flex_column(root);
lv_obj_set_size(root, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 1.5, LV_PCT(100));
lv_obj_set_style_pad_column(root, 10, 0);
lv_obj_clear_flag(root, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_t* sub_root = lv_create_empty_panel(root);
lv_layout_flex_column(sub_root);
lv_obj_set_height(sub_root, LV_SIZE_CONTENT);
lv_obj_add_flag(sub_root, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(sub_root, on_edit, LV_EVENT_CLICKED, NULL);
lv_obj_t* top_label = lv_label_create(sub_root);
lv_msg_subsribe_obj(DATA_PRINTER_DATA, top_label, NULL);
lv_obj_t* one_below_label = lv_label_create(sub_root);
lv_label_set_text(one_below_label, LV_SYMBOL_EDIT);
lv_obj_t* two_below_label = lv_label_create(sub_root);
lv_label_set_text_fmt(two_below_label, "%s+", axis);
lv_obj_t* slider = lv_slider_create(root);
lv_obj_set_flex_grow(slider, 1);
lv_obj_set_width(slider, CYD_SCREEN_MIN_BUTTON_WIDTH_PX / 2);
lv_slider_set_range(slider, min, max);
lv_obj_add_event_cb(slider, on_slider_change, LV_EVENT_RELEASED, NULL);
lv_obj_add_event_cb(slider, position_change, LV_EVENT_MSG_RECEIVED, slider);
lv_obj_add_event_cb(slider, set_label_slider_position, LV_EVENT_VALUE_CHANGED, top_label);
lv_msg_subsribe_obj(DATA_PRINTER_DATA, slider, NULL);
lv_obj_t* last_label = lv_label_create(root);
lv_label_set_text_fmt(last_label, "%s-", axis);
lv_obj_add_event_cb(top_label, position_change, LV_EVENT_MSG_RECEIVED, slider);
}
/* TODO: Make vertical button row with +1, +0.1, -0.1, -1, maybe with MAX - 30 */
static void make_horizontal_slider(
lv_obj_t* parent,
const char* axis,
lv_event_cb_t position_change,
lv_event_cb_t on_slider_change,
lv_event_cb_t on_edit,
float min,
float max)
{
lv_obj_t* root = lv_create_empty_panel(parent);
lv_layout_flex_column(root);
lv_obj_set_size(root, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_t* upper = lv_create_empty_panel(root);
lv_layout_flex_row(upper, LV_FLEX_ALIGN_SPACE_BETWEEN);
lv_obj_set_size(upper, LV_PCT(100), LV_SIZE_CONTENT);
lv_obj_add_flag(upper, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_event_cb(upper, on_edit, LV_EVENT_CLICKED, NULL);
lv_obj_t* left_label = lv_label_create(upper);
lv_label_set_text_fmt(left_label, "%s-", axis);
lv_obj_t* position_label = lv_label_create(upper);
lv_msg_subsribe_obj(DATA_PRINTER_DATA, position_label, NULL);
lv_obj_t* right_label = lv_label_create(upper);
lv_label_set_text_fmt(right_label, "%s+", axis);
lv_obj_t* slider = lv_slider_create(root);
lv_obj_set_size(slider, LV_PCT(100), CYD_SCREEN_MIN_BUTTON_HEIGHT_PX / 2);
lv_slider_set_range(slider, min, max);
lv_obj_add_event_cb(slider, on_slider_change, LV_EVENT_RELEASED, NULL);
lv_obj_add_event_cb(slider, position_change, LV_EVENT_MSG_RECEIVED, slider);
lv_obj_add_event_cb(slider, set_label_slider_position, LV_EVENT_VALUE_CHANGED, position_label);
lv_msg_subsribe_obj(DATA_PRINTER_DATA, slider, NULL);
lv_obj_set_style_pad_bottom(root, 10, 0);
lv_obj_set_style_pad_bottom(upper, 10, 0);
lv_obj_set_style_pad_column(upper, 10, 0);
lv_obj_add_event_cb(position_label, position_change, LV_EVENT_MSG_RECEIVED, slider);
}
static void create_button(lv_obj_t* parent, lv_event_cb_t on_click, const char* text)
{
lv_obj_t* btn = lv_btn_create(parent);
lv_obj_set_width(btn, LV_PCT(100));
lv_obj_set_flex_grow(btn, 1);
lv_obj_add_event_cb(btn, on_click, LV_EVENT_CLICKED, NULL);
lv_obj_t* label = lv_label_create(btn);
lv_obj_center(label);
lv_label_set_text(label, text);
}
void move_panel_slider_init(lv_obj_t* panel)
{
lv_obj_t * sub_panel = lv_create_empty_panel(panel);
lv_obj_set_size(sub_panel, LV_PCT(100), LV_PCT(100));
lv_layout_flex_row(sub_panel);
lv_obj_t* left = lv_create_empty_panel(sub_panel);
lv_layout_flex_column(left);
lv_obj_set_flex_grow(left, 1);
lv_obj_set_height(left, LV_PCT(100));
float* position_min = get_current_printer_data()->position_min;
float* position_max = get_current_printer_data()->position_max;
make_horizontal_slider(left, "X", x_pos_update, x_slider_update, x_line_custom, position_min[0], position_max[0]);
make_vertical_slider(sub_panel, "Y", y_pos_update, y_slider_update, y_line_custom, position_min[1], position_max[1]);
make_vertical_slider(sub_panel, "Z", z_pos_update, z_slider_update, z_line_custom, position_min[2], position_max[2]);
create_button(left, home_button_click, LV_SYMBOL_HOME " Home XYZ");
create_button(left, disable_steppers_button_click, LV_SYMBOL_EYE_CLOSE " Free Motors");
create_button(left, switch_to_params_panel_button_click, LV_SYMBOL_SETTINGS " Parameters");
lv_obj_set_style_pad_right(left, 10, 0);
lv_obj_set_style_pad_all(sub_panel, 10, 0);
}

View File

@@ -12,5 +12,6 @@ void stats_panel_init(lv_obj_t* panel);
void printer_panel_init(lv_obj_t* panel); void printer_panel_init(lv_obj_t* panel);
void error_panel_init(lv_obj_t* panel); void error_panel_init(lv_obj_t* panel);
void connecting_panel_init(lv_obj_t* panel); void connecting_panel_init(lv_obj_t* panel);
void move_panel_slider_init(lv_obj_t* panel);
void settings_section_device(lv_obj_t* panel); void settings_section_device(lv_obj_t* panel);

View File

@@ -15,7 +15,8 @@
#endif // REPO_VERSION #endif // REPO_VERSION
static void invert_color_switch(lv_event_t * e){ static void invert_color_switch(lv_event_t * e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.printer_config[global_config.printer_index].invert_colors = checked; global_config.printer_config[global_config.printer_index].invert_colors = checked;
write_global_config(); write_global_config();
set_invert_display(); set_invert_display();
@@ -45,14 +46,16 @@ static void reset_ip_click(lv_event_t * e){
} }
static void light_mode_switch(lv_event_t * e){ static void light_mode_switch(lv_event_t * e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
get_current_printer()->printer_config->light_mode = checked; get_current_printer()->printer_config->light_mode = checked;
write_global_config(); write_global_config();
set_color_scheme(); set_color_scheme();
} }
static void filament_move_mode_switch(lv_event_t * e){ static void filament_move_mode_switch(lv_event_t * e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
get_current_printer()->printer_config->custom_filament_move_macros = checked; get_current_printer()->printer_config->custom_filament_move_macros = checked;
write_global_config(); write_global_config();
} }
@@ -94,44 +97,51 @@ static void wake_timeout_dropdown(lv_event_t * e){
} }
static void dualusb_screen_fix_switch(lv_event_t* e){ static void dualusb_screen_fix_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.display_mode = checked; global_config.display_mode = checked;
write_global_config(); write_global_config();
ESP.restart(); ESP.restart();
} }
static void disable_m117_messaging_switch(lv_event_t* e){ static void disable_m117_messaging_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.disable_m117_messaging = checked; global_config.disable_m117_messaging = checked;
write_global_config(); write_global_config();
} }
static void sort_macros_switch(lv_event_t* e){ static void sort_macros_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.sort_macros = checked; global_config.sort_macros = checked;
write_global_config(); write_global_config();
} }
static void show_estop_switch(lv_event_t* e){ static void show_estop_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.show_estop = checked; global_config.show_estop = checked;
write_global_config(); write_global_config();
} }
static void full_filenames_switch(lv_event_t* e){ static void full_filenames_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.full_filenames = checked; global_config.full_filenames = checked;
write_global_config(); write_global_config();
} }
static void double_size_gcode_img_switch(lv_event_t* e){ static void double_size_gcode_img_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.double_size_gcode_img = checked; global_config.double_size_gcode_img = checked;
write_global_config(); write_global_config();
} }
static void rotate_screen_switch(lv_event_t* e){ static void rotate_screen_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.rotate_screen = checked; global_config.rotate_screen = checked;
global_config.screen_calibrated = false; global_config.screen_calibrated = false;
write_global_config(); write_global_config();
@@ -139,7 +149,8 @@ static void rotate_screen_switch(lv_event_t* e){
} }
static void on_during_print_switch(lv_event_t* e){ static void on_during_print_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.on_during_print = checked; global_config.on_during_print = checked;
check_if_screen_needs_to_be_disabled(); check_if_screen_needs_to_be_disabled();
write_global_config(); write_global_config();
@@ -150,13 +161,15 @@ static void btn_ota_do_update(lv_event_t * e){
} }
static void auto_ota_update_switch(lv_event_t* e){ static void auto_ota_update_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.auto_ota_update = checked; global_config.auto_ota_update = checked;
write_global_config(); write_global_config();
} }
static void multi_printer_switch(lv_event_t* e){ static void multi_printer_switch(lv_event_t* e){
bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); auto state = lv_obj_get_state(lv_event_get_target(e));
bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
global_config.multi_printer_mode = checked; global_config.multi_printer_mode = checked;
write_global_config(); write_global_config();
nav_buttons_setup(PANEL_SETTINGS); nav_buttons_setup(PANEL_SETTINGS);

View File

@@ -161,7 +161,9 @@ static void set_temp_via_preset(lv_event_t * e){
} }
static void btn_toggleable_edit(lv_event_t * e){ static void btn_toggleable_edit(lv_event_t * e){
temp_edit_mode = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); lv_obj_t * btn = lv_event_get_target(e);
auto state = lv_obj_get_state(btn);
temp_edit_mode = (state & LV_STATE_CHECKED == LV_STATE_CHECKED);
} }
static void btn_retract(lv_event_t * e){ static void btn_retract(lv_event_t * e){

View File

@@ -5,49 +5,11 @@
#define MAX_COMDLINE_SIZE 80 #define MAX_COMDLINE_SIZE 80
#define MAX_WORDS 6 #define MAX_WORDS 6
#define BACKSPACE_CHAR 0x08
#define ESCAPE_CHAR '\x1b'
#define CSI_CHAR '['
#define LEFT_ARROW_CHAR 'D'
#define RIGHT_ARROW_CHAR 'C'
#define DELETE_KEY_1_CHAR '3'
#define DELETE_KEY_2_CHAR '~'
#define PRINT_CHAR_START 32
#define PRINT_CHAR_END 126
namespace serial_console namespace serial_console
{ {
bool global_disable_serial_console = false; bool global_disable_serial_console = false;
/**
* @brief Redraws the characters from the current cursor position to the end of the buffer on the serial console.
*
* This function is used to update the terminal display when characters are inserted or deleted
* in the middle of the input buffer. It:
* - Saves the current cursor position
* - Clears the line from the cursor to the end
* - Prints characters from 'cur' to 'len'
* - Restores the original cursor position
*
* @param cur Current cursor position within the buffer
* @param len Current length of the buffer (number of characters entered)
* @param buf Character buffer containing the input string
*/
static inline void redraw(const int cur, const int len, char *buf) {
if (!temporary_config.remote_echo)
return;
Serial.print("\x1b[s");
Serial.print("\x1b[K");
// Reprint characters from cur to end
for (int i = cur; i < len; i++) {
Serial.print((char)buf[i]);
}
Serial.print(" \x1b[u");
}
/* /*
* read_string_until: Non-blocking replacement for Serial.readStringUntil().. * read_string_until: Non-blocking replacement for Serial.readStringUntil()..
* With delimeter '\n' acts as 'read line'. * With delimeter '\n' acts as 'read line'.
@@ -58,7 +20,6 @@ namespace serial_console
bool read_string_until(char delimiter, char *result, int max_len) bool read_string_until(char delimiter, char *result, int max_len)
{ {
static int index = 0; static int index = 0;
static int cur = 0;
int c; // read character, -1 if none int c; // read character, -1 if none
int cnt = 100; // limit on amount of iterations in one go; we're supposed to be non-blocking! int cnt = 100; // limit on amount of iterations in one go; we're supposed to be non-blocking!
@@ -67,75 +28,43 @@ namespace serial_console
--cnt; --cnt;
// backspaceF // backspaceF
if (c == BACKSPACE_CHAR && cur > 0) { if (c == 8)
// shift characters left from cursor position {
memmove(&result[cur - 1], &result[cur], index - cur); if (index > 0)
{
if(temporary_config.remote_echo) Serial.print("\x08 \x08"); // overwrite last character with space and move cursor 1 back.
index--; index--;
cur--;
// move cursor left on terminal and redraw updated string
if(temporary_config.remote_echo) Serial.print("\x1b[D");
redraw(cur, index, result);
// handle ANSI escape sequences (arrow keys, delete key)
} else if (c == ESCAPE_CHAR) {
if ((c = Serial.read()) == -1)
break;
// Expect '[' character
if (c != CSI_CHAR)
continue;
if ((c = Serial.read()) == -1)
break;
// Left arrow key
if (c == LEFT_ARROW_CHAR && cur > 0) {
// move cursor left on terminal
if(temporary_config.remote_echo) Serial.print("\x1b[D");
cur--;
// Right arrow key
} else if(c == RIGHT_ARROW_CHAR && cur < index) {
// move cursor right on terminal
if(temporary_config.remote_echo) Serial.print("\x1b[C");
cur++;
// Delete key
} else if(c == DELETE_KEY_1_CHAR) {
if ((c = Serial.read()) == -1)
break;
if (c == DELETE_KEY_2_CHAR && cur < index) {
memmove(&result[cur], &result[cur + 1], index - cur - 1);
index--;
redraw(cur, index, result);
}
} }
continue;
}
// Handle printable characters if(temporary_config.remote_echo) Serial.print((char)c); // echo
} else if (c >= PRINT_CHAR_START && c <= PRINT_CHAR_END) {
// Append character at the end // Buffer overflow handling:
if (index < max_len - 1 && cur == index) { // start treating current buffer as invalid:
if(temporary_config.remote_echo) Serial.print((char)c); // - stop collecting more data
result[index++] = c; // - return false on delimeter, flushing everything collected,
cur++; // - restart collection from scratch after delimeter,
// Insert character in the middl // - return control as normal.
} else if (index < max_len - 1) {
memmove(&result[cur + 1], &result[cur], index - cur); if (index >= max_len - 1)
result[cur] = c; {
index++; if (c == delimiter) // got delimeter: flush buffer quietly, restart collection.
if(temporary_config.remote_echo) Serial.print((char)c); {
cur++;
redraw(cur, index, result);
} else if (c == delimiter) { // got delimeter: flush buffer quietly, restart collection.
index = 0; index = 0;
cur = 0;
return false; return false;
} }
// delimiter was found else
} else if (c == delimiter) { continue; // discard any data past the end of the buffer, keep reading
}
if(temporary_config.remote_echo) Serial.println(); result[index++] = c;
// delimiter was found
if (c == delimiter)
{
result[index] = '\0'; // Null-terminate the string result[index] = '\0'; // Null-terminate the string
index = 0; index = 0;
cur = 0;
return true; // Success: Delimiter found return true; // Success: Delimiter found
} }
} }

View File

@@ -42,21 +42,6 @@ If you found this project helpful, please consider a donation [to my Ko-Fi](http
Thank you! Thank you!
### Where to buy hardware
All links below are affiliate links. Please also check yourself if there is a cheaper version available than the ones below. I have only linked ones that i have personally bought.
*ESP32-2432S028R (2.8" Resistive, Cheapest)*
- [USB C + microB version](https://s.click.aliexpress.com/e/_omjsYBJ)
- [Another USB C + microB version](https://s.click.aliexpress.com/e/_olKBkmz)
- [microB version](https://s.click.aliexpress.com/e/_oCWhgmN)
*ESP32-2432S032C (3.2" Capacitive)*
- [Only the capacitive version is supported! USB-C](https://s.click.aliexpress.com/e/_okbSGmd)
- [IPS version (not that great of a screen), Only the capacitive version is supported! USB-C](https://s.click.aliexpress.com/e/_oFygVwt)
*ESP32-3248S035C (3.5" Capacitive)*
- [microB version](https://s.click.aliexpress.com/e/_oCqygE9)
### Screenshots ### Screenshots
(Quite literally shots of the screen. I'm sorry) (Quite literally shots of the screen. I'm sorry)

View File

@@ -8,7 +8,7 @@
font-family: 'Roboto', sans-serif; font-family: 'Roboto', sans-serif;
} }
TT { TT {
font-family: 'Terminal', monospace; font-family: 'Terminal', monospace;
background-color: #080a0b; background-color: #080a0b;
} }
@@ -24,8 +24,7 @@
max-width: 750px; max-width: 750px;
} }
.main > section > :not(:first-child), .main > section > :not(:first-child) {
.indent {
margin-left: 20px; margin-left: 20px;
} }
@@ -45,17 +44,6 @@
#changelog-body { #changelog-body {
white-space: break-spaces; white-space: break-spaces;
} }
.where-to-get details summary::marker
{
content: '';
}
.where-to-get details[open] summary p
{
display: none;
}
</style> </style>
<script type="module" src="https://unpkg.com/esp-web-tools@9/dist/web/install-button.js?module"></script> <script type="module" src="https://unpkg.com/esp-web-tools@9/dist/web/install-button.js?module"></script>
<script src="//code.iconify.design/1/1.0.6/iconify.min.js"></script> <script src="//code.iconify.design/1/1.0.6/iconify.min.js"></script>
@@ -95,34 +83,6 @@
<p>If you found this project helpful, please consider a donation to <a href="https://ko-fi.com/suchmememanyskill">my Ko-Fi</a>.<br>It would help out a lot in the development of this project, due to the need to buy the screens.<br>Thank you!</p> <p>If you found this project helpful, please consider a donation to <a href="https://ko-fi.com/suchmememanyskill">my Ko-Fi</a>.<br>It would help out a lot in the development of this project, due to the need to buy the screens.<br>Thank you!</p>
</section> </section>
<section class="where-to-get">
<details>
<summary>
<h3><span class="iconify" data-icon="mdi-shopping" style="color:orange; filter: drop-shadow(0 0 0.75rem orange);"></span> Where to buy hardware</h3>
<p class="indent">(Click to expand)</p>
</summary>
<section class="indent">
<p>All links below are affiliate links. Please also check yourself if there is a cheaper version available than the ones below. I have only linked ones that i have personally bought.</p>
<i>ESP32-2432S028R (2.8" Resistive, Cheapest)</i>
<ul>
<li><a href="https://s.click.aliexpress.com/e/_omjsYBJ">USB C + microB version</a></li>
<li><a href="https://s.click.aliexpress.com/e/_olKBkmz">Another USB C + microB version</a></li>
<li><a href="https://s.click.aliexpress.com/e/_oCWhgmN">microB version</a></li>
</ul>
<i>ESP32-2432S032C (3.2" Capacitive)</i>
<ul>
<li><a href="https://s.click.aliexpress.com/e/_okbSGmd">Only the capacitive version is supported! USB-C</a></li>
<li><a href="https://s.click.aliexpress.com/e/_oFygVwt">IPS version (not that great of a screen), Only the capacitive version is supported! USB-C</a></li>
</ul>
<i>ESP32-3248S035C (3.5" Capacitive)</i>
<ul>
<li><a href="https://s.click.aliexpress.com/e/_oCqygE9">microB version</a></li>
</ul>
</section>
</details>
</section>
<section class="issues"> <section class="issues">
<h3><span class="iconify" data-icon="mdi-github" style="color: white; filter: drop-shadow(0 0 0.75rem gray);"></span> Report Issues</h3> <h3><span class="iconify" data-icon="mdi-github" style="color: white; filter: drop-shadow(0 0 0.75rem gray);"></span> Report Issues</h3>
<p>If you experience any issues with this project, or have any feature requests for the project, please report them on the <a href="https://github.com/suchmememanyskill/CYD-Klipper/issues">issues tab on Github</a>.</p> <p>If you experience any issues with this project, or have any feature requests for the project, please report them on the <a href="https://github.com/suchmememanyskill/CYD-Klipper/issues">issues tab on Github</a>.</p>
@@ -132,7 +92,16 @@
<h3><span class="iconify" data-icon="mdi-download"></span> Install</h3> <h3><span class="iconify" data-icon="mdi-download"></span> Install</h3>
<p>Select your device from the list below and click 'Connect'.<br>Note: You may need to hold the 'BOOT' button on the device while pressing install.<br><br>The 2.8" Resistive and 3.5" Capacitive models are best suited (in my opinion) for CYD-Klipper.<br><br>Note for any resistive models: You can clear touch calibration by holding the BOOT button for 8 seconds while the screen is on.</p> <p>Select your device from the list below and click 'Connect'.<br>Note: You may need to hold the 'BOOT' button on the device while pressing install.<br><br>The 2.8" Resistive and 3.5" Capacitive models are best suited (in my opinion) for CYD-Klipper.<br><br>Note for any resistive models: You can clear touch calibration by holding the BOOT button for 8 seconds while the screen is on.</p>
<select id="select-install-btn" onchange="setInstallButton(getElementById('select-install-btn').value)"> <select id="select-install-btn" onchange="setInstallButton(getElementById('select-install-btn').value)">
{{%PORTS%}} <option value="esp32-2432S024C-SD">ESP32-2432S024 (2.4" Capacitive)</option>
<option selected value="esp32-2432S028R">ESP32-2432S028 (2.8" Resistive)</option>
<option value="esp32-2432S032C-SD">ESP32-2432S032 (3.2" Capacitive)</option>
<option value="esp32-3248S035C">ESP32-3248S035 (3.5" Capacitive)</option>
<option value="esp32-3248S035C-V">ESP32-3248S035 (3.5" Capacitive) Vertical Orientation</option>
<option value="esp32-4827S043C-SD">ESP32-4827S043 (4.3" 480x270 Capacitive)</option>
<option value="esp32-8048S043C-SD">ESP32-8048S043 (4.3" 800x480 Capacitive)</option>
<option value="esp32-8048S043C-SD-alt">ESP32-8048S043 Alt (4.3" 800x480 Capacitive)</option>
<option value="esp32-CROWPANEL-28R">ESP32-CROWPANEL-28R (2.8" Resistive)</option>
<option value="esp32-CROWPANEL-35C">ESP32-CROWPANEL-35C (3.5" Capacitive)</option>
</select> </select>
<span id="install-btn"></span> <span id="install-btn"></span>
</section> </section>

67
ci.json
View File

@@ -1,67 +0,0 @@
{
"esp32-2432S024C-SD": {
"name": "ESP32-2432S024 (2.4\" Capacitive)",
"site": true,
"s3": false
},
"esp32-2432S028R": {
"name": "ESP32-2432S028 (2.8\" Resistive)",
"site": true,
"s3": false,
"default": true
},
"esp32-2432S032C-SD": {
"name": "ESP32-2432S032 (3.2\" Capacitive)",
"site": true,
"s3": false
},
"esp32-3248S035C": {
"name": "ESP32-3248S035 (3.5\" Capacitive)",
"site": true,
"s3": false
},
"esp32-3248S035C-V": {
"name": "ESP32-3248S035 (3.5\" Capacitive) Vertical Orientation",
"site": true,
"s3": false
},
"esp32-4827S043C-SD": {
"name": "ESP32-4827S043 (4.3\" 480x270 Capacitive)",
"site": true,
"s3": true
},
"esp32-8048S043C-SD": {
"name": "ESP32-8048S043 (4.3\" 800x480 Capacitive)",
"site": true,
"s3": true
},
"esp32-8048S043C-SD-alt": {
"name": "ESP32-8048S043 Alt (4.3\" 800x480 Capacitive)",
"site": true,
"s3": true
},
"esp32-CROWPANEL-28R": {
"name": "ESP32-CROWPANEL-28R (2.8\" Resistive)",
"site": true,
"s3": false,
"brand": "CrowPanel"
},
"esp32-CROWPANEL-35C": {
"name": "ESP32-CROWPANEL-35C (3.5\" Capacitive)",
"site": true,
"s3": true,
"brand": "CrowPanel"
},
"esp32-JC4827W543C": {
"name": "ESP-JC4827W543C (4.3\" Capacitive)",
"site": true,
"s3": true,
"brand": "Guition"
},
"esp32-JC8048W550": {
"name": "Guition JC8048W550 (5\" Capacitive)",
"site": true,
"s3": true,
"brand": "Guition"
}
}

76
ci.py
View File

@@ -1,19 +1,40 @@
import subprocess, os, shutil, json import subprocess, os, shutil, json
CYD_PORTS = [
"esp32-3248S035C",
"esp32-2432S028R",
"esp32-2432S032C-SD",
"esp32-8048S043C-SD",
"esp32-8048S043C-SD-alt",
"esp32-2432S024C-SD",
"esp32-4827S043C-SD",
"esp32-3248S035C-V",
#"esp32-4827S043R-SD",
"esp32-CROWPANEL-28R",
"esp32-CROWPANEL-35C",
]
ESP_S3_CHIPS = [
"esp32-8048S043C-SD",
"esp32-8048S043C-SD-alt",
"esp32-4827S043C-SD",
"esp32-CROWPANEL-35C",
]
BASE_DIR = os.getcwd() BASE_DIR = os.getcwd()
def get_manifest(base_path : str, device_name : str, is_s3 : bool): def get_manifest(base_path : str, device_name : str):
return { return {
"name": f"to {device_name}", "name": f"to {device_name}",
"funding_url": "https://ko-fi.com/suchmememanyskill", "funding_url": "https://ko-fi.com/suchmememanyskill",
"new_install_prompt_erase": True, "new_install_prompt_erase": True,
"builds": [ "builds": [
{ {
"chipFamily": "ESP32-S3" if is_s3 else "ESP32", "chipFamily": "ESP32-S3" if device_name in ESP_S3_CHIPS else "ESP32",
"parts": [ "parts": [
{ {
"path": f"{base_path}/bootloader.bin", "path": f"{base_path}/bootloader.bin",
"offset": 0 if is_s3 else 0x1000 "offset": 0 if device_name in ESP_S3_CHIPS else 0x1000
}, },
{ {
"path": f"{base_path}/partitions.bin", "path": f"{base_path}/partitions.bin",
@@ -38,7 +59,6 @@ def extract_commit() -> str:
repo_version = extract_commit() repo_version = extract_commit()
configurations = [] configurations = []
site_sections : dict[str, dict] = {"CYD": []}
def add_configuration(board : str): def add_configuration(board : str):
configurations.append({ configurations.append({
@@ -47,32 +67,10 @@ def add_configuration(board : str):
"URL": f"https://suchmememanyskill.github.io/CYD-Klipper/out/{board}/firmware.bin" "URL": f"https://suchmememanyskill.github.io/CYD-Klipper/out/{board}/firmware.bin"
}) })
def add_site_section(port : str, data : dict[str, bool|str]):
brand = data["brand"] if "brand" in data else "CYD"
if brand not in site_sections:
site_sections[brand] = []
site_sections[brand].append({
"name": data["name"],
"port": port,
"default": "default" in data and data["default"],
})
if os.path.exists("out"): if os.path.exists("out"):
shutil.rmtree("out") shutil.rmtree("out")
if not os.path.exists("_site"): for port in CYD_PORTS:
os.makedirs("_site")
with open("./ci.json", "r") as fp:
ci_data : dict[str, dict[str, bool|str]] = json.load(fp)
for port, data in ci_data.items():
if "skip" in data and data["skip"]:
print(f"Skipping {port}...")
continue
port_path = f"out/{port}" port_path = f"out/{port}"
os.chdir(BASE_DIR) os.chdir(BASE_DIR)
os.makedirs(port_path, exist_ok=True) os.makedirs(port_path, exist_ok=True)
@@ -84,21 +82,18 @@ for port, data in ci_data.items():
shutil.copy(os.path.join(os.path.expanduser("~"), ".platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin"), f"{port_path}/boot_app0.bin") shutil.copy(os.path.join(os.path.expanduser("~"), ".platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin"), f"{port_path}/boot_app0.bin")
os.chdir(port_path) os.chdir(port_path)
if (bool(data["s3"])): if (port in ESP_S3_CHIPS):
subprocess.run(["esptool", "--chip", "esp32s3", "merge_bin", "-o", "merged_firmware.bin", "--flash_mode", "dio", "--flash_freq", "80m", "--flash_size", "16MB", "0x0000", "bootloader.bin", "0x8000", "partitions.bin", "0xe000", "boot_app0.bin", "0x10000", "firmware.bin"], check=True) subprocess.run(["python3", "-m", "esptool", "--chip", "esp32s3", "merge_bin", "-o", "merged_firmware.bin", "--flash_mode", "dio", "--flash_freq", "80m", "--flash_size", "16MB", "0x0000", "bootloader.bin", "0x8000", "partitions.bin", "0xe000", "boot_app0.bin", "0x10000", "firmware.bin"], check=True)
else: else:
subprocess.run(["esptool", "--chip", "esp32", "merge_bin", "-o", "merged_firmware.bin", "--flash_mode", "dio", "--flash_freq", "40m", "--flash_size", "4MB", "0x1000", "bootloader.bin", "0x8000", "partitions.bin", "0xe000", "boot_app0.bin", "0x10000", "firmware.bin"], check=True) subprocess.run(["python3", "-m", "esptool", "--chip", "esp32", "merge_bin", "-o", "merged_firmware.bin", "--flash_mode", "dio", "--flash_freq", "40m", "--flash_size", "4MB", "0x1000", "bootloader.bin", "0x8000", "partitions.bin", "0xe000", "boot_app0.bin", "0x10000", "firmware.bin"], check=True)
os.chdir(BASE_DIR) os.chdir(BASE_DIR)
with open(f"./_site/{port}.json", "w") as f: with open(f"./_site/{port}.json", "w") as f:
json.dump(get_manifest(port_path, port, bool(data["s3"])), f) json.dump(get_manifest(port_path, port), f)
add_configuration(port) add_configuration(port)
if "site" in data and data["site"]:
add_site_section(port, data)
os.chdir(BASE_DIR) os.chdir(BASE_DIR)
out_dir = "./_site/out" out_dir = "./_site/out"
if os.path.exists(out_dir): if os.path.exists(out_dir):
@@ -107,16 +102,3 @@ shutil.copytree("./out", out_dir)
with open("./_site/OTA.json", "w") as f: with open("./_site/OTA.json", "w") as f:
json.dump({"Configurations": configurations}, f) json.dump({"Configurations": configurations}, f)
with open("./_site/index.html", "w") as fp:
with open("./template.html", "r") as template_fp:
template = template_fp.read()
insert_html = ""
for brand, sections in site_sections.items():
option_htmls = [f"<option {'selected' if x['default'] else ''} value=\"{x['port']}\">{x['name']}</option>" for x in sections]
section_html = f"<optgroup label=\"{brand}\">{''.join(option_htmls)}</optgroup>"
insert_html += section_html
fp.write(template.replace("{{%PORTS%}}", insert_html))

View File

@@ -4,11 +4,11 @@ services:
ports: ports:
- "7125:7125" - "7125:7125"
- "8110:8110" - "8110:8110"
image: ghcr.io/mainsail-crew/virtual-klipper-printer:latest image: ghcr.io/mainsail-crew/virtual-klipper-printer:master
webui: webui:
container_name: mainsail container_name: mainsail
volumes: volumes:
- ./config.json:/usr/share/nginx/html/config.json:ro - ./config.json:/usr/share/nginx/html/config.json:ro
ports: ports:
- 6969:80 - 6969:80
image: ghcr.io/mainsail-crew/mainsail image: ghcr.io/mainsail-crew/mainsail