22 Commits

Author SHA1 Message Date
suchmememanyskill
c8e34598ca Merge branch 'master' of https://github.com/suchmememanyskill/CYD-Klipper-Display 2025-09-30 00:19:48 +02:00
suchmememanyskill
77086b8ecf update virtual printer 2025-09-30 00:19:41 +02:00
Sims
93f3935480 Fix #178 2025-08-19 00:51:29 +02:00
suchmememanyskill
3e23ba935d Merge branch 'dev' 2025-08-18 23:29:01 +02:00
Stefan Naewe
07d5f95b00 use correct spelling for WiFiClientSecure.h (#202)
It's "WiFiClient..." and not "WifiClient..."

Signed-off-by: Stefan Naewe <stefan.naewe@gmail.com>
2025-08-10 14:14:53 +02:00
suchmememanyskill
19fb87d0bb Add support for esp32-JC3248W535C 2025-07-10 14:55:16 +02:00
suchmememanyskill
d126697cb0 Better CI pipeline 2025-07-10 00:45:25 +02:00
suchmememanyskill
63a0ca5233 Fix bad code 2025-07-09 23:55:50 +02:00
suchmememanyskill
c929b5e270 Merge main 2025-07-09 23:49:04 +02:00
Dylan Pryke-Watanabe
b6c2b505e0 Add support for JC3248W535C (Guition 3.5" ESP32-S3 Display) (#189)
* Guition Display outputs to screen

* Fix Display Flushing and Touch Screen works now!

* fix UI rotations

* set default orientation to 2

* Start trying to implement horizontal software rotation

* remove -w flag

* cleanup

* Rename to JC3248W535C

* Update lv_conf.h

* replace URL
2025-07-09 23:44:27 +02:00
Madrajib Lab
40932518ae serial_console: Add support to handle delete/arrow keys (#195)
This change adds support to serial console to handle delete
left & right arrow and backspace key by changing
result buffer based on the keypress and emulating the movement
with espace characters in the terminal.

This patch also takes care of buffer flow handling by checking
the cur and index with the max available length for each operations.
2025-07-09 23:42:57 +02:00
Madrajib Lab
266b5d76b1 lvgl API: use lv_obj_has_state to check state value (#198) 2025-07-09 23:42:29 +02:00
Madrajib Lab
4067f94407 platfromio: Update LovyanGFX from 1.2.0 to 1.2.7 (#196) 2025-07-09 23:41:46 +02:00
Evgeny Kapusta
5b7770246e feat: add Guition JC8048W550 display support (#185)
* Update readme

* Update README.md

* Add aliexpress links

* feat: add Guition JC8048W550 display support

* feat: adjust configuration for board

* feat: add option for jc8048w550 on page and in ci script

* fix: missing CYD_PORTS entry

---------

Co-authored-by: Sims <38142618+suchmememanyskill@users.noreply.github.com>
2025-05-02 23:42:06 +02:00
Sims
7c564e8ab8 Merge pull request #166 from suchmememanyskill/dev
Hopefully fix webflash for s3
2025-02-09 01:57:02 +01:00
Sims
e6b5d17f6a Merge pull request #164 from suchmememanyskill/dev
v2.1.0
2025-02-01 19:39:18 +01:00
suchmememanyskill
8f46b9972d Add aliexpress links 2025-01-15 22:18:36 +01:00
Sims
5756b31744 Update README.md 2025-01-10 18:15:56 +01:00
suchmememanyskill
99b70622fe Update readme 2025-01-09 23:14:15 +01:00
Sims
b3d405b355 Merge pull request #139 from suchmememanyskill/dev
v2.0.0 - Happy new year!
2025-01-09 23:05:35 +01:00
Sims
9a96f9336f Merge pull request #125 from suchmememanyskill/dev
v1.8.0
2024-08-31 11:49:48 +02:00
Sims
5c46764c7c Merge pull request #122 from suchmememanyskill/dev
v1.7.0
2024-08-02 21:39:42 +02:00
21 changed files with 1077 additions and 117 deletions

View File

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

View File

@@ -48,7 +48,8 @@
"stdexcept": "cpp", "stdexcept": "cpp",
"streambuf": "cpp", "streambuf": "cpp",
"cinttypes": "cpp", "cinttypes": "cpp",
"typeinfo": "cpp" "typeinfo": "cpp",
"*.tpp": "cpp"
}, },
"cmake.configureOnOpen": false "cmake.configureOnOpen": false
} }

View File

@@ -0,0 +1,69 @@
{
"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

@@ -0,0 +1,66 @@
{
"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

@@ -0,0 +1,142 @@
{
"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,12 +108,37 @@ 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.0 https://github.com/lovyan03/LovyanGFX@1.2.7
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) { auto state = lv_obj_get_state(lv_event_get_target(e)); bool_name = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); } #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); }
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

@@ -0,0 +1,184 @@
#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

@@ -0,0 +1,85 @@
#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

@@ -0,0 +1,196 @@
/*******************************************************************************
*
* 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,9 +271,15 @@ 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(HttpGet, request.c_str()); return make_serial_request_nocontent(HttpPost, 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};
@@ -291,7 +297,7 @@ Files SerialKlipperPrinter::get_files()
return files_result; return files_result;
} }
parse_file_list(doc, files, 20); parse_file_list(doc, files, MAX_FILE_LIST_SIZE);
files_result.available_files = (char**)malloc(sizeof(char*) * files.size()); files_result.available_files = (char**)malloc(sizeof(char*) * files.size());

View File

@@ -47,8 +47,7 @@ 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)
{ {
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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

@@ -15,8 +15,7 @@
#endif // REPO_VERSION #endif // REPO_VERSION
static void invert_color_switch(lv_event_t * e){ static void invert_color_switch(lv_event_t * e){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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();
@@ -46,16 +45,14 @@ 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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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();
} }
@@ -97,51 +94,44 @@ 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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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();
@@ -149,8 +139,7 @@ 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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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();
@@ -161,15 +150,13 @@ 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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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){
auto state = lv_obj_get_state(lv_event_get_target(e)); bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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,9 +161,7 @@ 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){
lv_obj_t * btn = lv_event_get_target(e); temp_edit_mode = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED);
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,11 +5,49 @@
#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'.
@@ -20,6 +58,7 @@ 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!
@@ -28,43 +67,75 @@ namespace serial_console
--cnt; --cnt;
// backspaceF // backspaceF
if (c == 8) if (c == BACKSPACE_CHAR && cur > 0) {
{ // shift characters left from cursor position
if (index > 0) memmove(&result[cur - 1], &result[cur], index - cur);
{
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;
}
if(temporary_config.remote_echo) Serial.print((char)c); // echo // Handle printable characters
} else if (c >= PRINT_CHAR_START && c <= PRINT_CHAR_END) {
// Buffer overflow handling: // Append character at the end
// start treating current buffer as invalid: if (index < max_len - 1 && cur == index) {
// - stop collecting more data if(temporary_config.remote_echo) Serial.print((char)c);
// - return false on delimeter, flushing everything collected, result[index++] = c;
// - restart collection from scratch after delimeter, cur++;
// - return control as normal. // Insert character in the middl
} else if (index < max_len - 1) {
if (index >= max_len - 1) memmove(&result[cur + 1], &result[cur], index - cur);
{ result[cur] = c;
if (c == delimiter) // got delimeter: flush buffer quietly, restart collection. index++;
{ 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;
} }
else
continue; // discard any data past the end of the buffer, keep reading
}
result[index++] = c;
// delimiter was found // delimiter was found
if (c == delimiter) } else if (c == delimiter) {
{
if(temporary_config.remote_echo) Serial.println();
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,6 +42,21 @@ 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)

67
ci.json Normal file
View File

@@ -0,0 +1,67 @@
{
"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,40 +1,19 @@
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): def get_manifest(base_path : str, device_name : str, is_s3 : bool):
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 device_name in ESP_S3_CHIPS else "ESP32", "chipFamily": "ESP32-S3" if is_s3 else "ESP32",
"parts": [ "parts": [
{ {
"path": f"{base_path}/bootloader.bin", "path": f"{base_path}/bootloader.bin",
"offset": 0 if device_name in ESP_S3_CHIPS else 0x1000 "offset": 0 if is_s3 else 0x1000
}, },
{ {
"path": f"{base_path}/partitions.bin", "path": f"{base_path}/partitions.bin",
@@ -59,6 +38,7 @@ 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({
@@ -67,10 +47,32 @@ 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")
for port in CYD_PORTS: if not os.path.exists("_site"):
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)
@@ -82,18 +84,21 @@ for port in CYD_PORTS:
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 (port in ESP_S3_CHIPS): if (bool(data["s3"])):
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) 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)
else: else:
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) 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)
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), f) json.dump(get_manifest(port_path, port, bool(data["s3"])), 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):
@@ -102,3 +107,16 @@ 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

@@ -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,7 +24,8 @@
max-width: 750px; max-width: 750px;
} }
.main > section > :not(:first-child) { .main > section > :not(:first-child),
.indent {
margin-left: 20px; margin-left: 20px;
} }
@@ -44,6 +45,17 @@
#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>
@@ -83,6 +95,34 @@
<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>
@@ -92,16 +132,7 @@
<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)">
<option value="esp32-2432S024C-SD">ESP32-2432S024 (2.4" Capacitive)</option> {{%PORTS%}}
<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>

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:master image: ghcr.io/mainsail-crew/virtual-klipper-printer:latest
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