diff --git a/.github/workflows/compile.yaml b/.github/workflows/compile.yaml index 950656f..a13ec5e 100644 --- a/.github/workflows/compile.yaml +++ b/.github/workflows/compile.yaml @@ -33,7 +33,7 @@ jobs: - uses: actions/setup-python@v5 with: - python-version: '3.9' + python-version: '3.13' - name: Install PlatformIO Core run: pip install --upgrade platformio esptool diff --git a/CYD-Klipper/.vscode/settings.json b/CYD-Klipper/.vscode/settings.json index e1ffb15..96d51cd 100644 --- a/CYD-Klipper/.vscode/settings.json +++ b/CYD-Klipper/.vscode/settings.json @@ -48,7 +48,8 @@ "stdexcept": "cpp", "streambuf": "cpp", "cinttypes": "cpp", - "typeinfo": "cpp" + "typeinfo": "cpp", + "*.tpp": "cpp" }, "cmake.configureOnOpen": false } \ No newline at end of file diff --git a/CYD-Klipper/boards/esp32-JC3248W535C.json b/CYD-Klipper/boards/esp32-JC3248W535C.json new file mode 100644 index 0000000..2a670e6 --- /dev/null +++ b/CYD-Klipper/boards/esp32-JC3248W535C.json @@ -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"] + } + \ No newline at end of file diff --git a/CYD-Klipper/boards/esp32-JC4827W543C.json b/CYD-Klipper/boards/esp32-JC4827W543C.json new file mode 100644 index 0000000..9cb8acf --- /dev/null +++ b/CYD-Klipper/boards/esp32-JC4827W543C.json @@ -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"] + } + \ No newline at end of file diff --git a/CYD-Klipper/boards/esp32-JC8048W550.json b/CYD-Klipper/boards/esp32-JC8048W550.json new file mode 100644 index 0000000..4b3b03c --- /dev/null +++ b/CYD-Klipper/boards/esp32-JC8048W550.json @@ -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" +} diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index ee36d08..930ee96 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -14,21 +14,21 @@ board = esp32dev framework = arduino monitor_speed = 115200 debug_build_flags = -Os -lib_deps = +lib_deps = https://github.com/suchmememanyskill/esp32-smartdisplay#9c1d737 bblanchon/ArduinoJson@^7.0.0 plageoj/UrlEncode@^1.0.1 knolleary/PubSubClient@^2.8 WiFiClientSecure monitor_filters = esp32_exception_decoder -build_flags = +build_flags = -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" -extra_scripts = +extra_scripts = pre:extract_commit.py [env:esp32-2432S028R] board = esp32-2432S028R -lib_deps = +lib_deps = SPI https://github.com/suchmememanyskill/lvgl https://github.com/Bodmer/TFT_eSPI.git @@ -40,7 +40,7 @@ lib_deps = [env:esp32-3248S035C] board = esp32-3248S035C -lib_deps = +lib_deps = SPI https://github.com/suchmememanyskill/lvgl https://github.com/Bodmer/TFT_eSPI.git @@ -52,7 +52,7 @@ lib_deps = [env:esp32-3248S035C-V] board = esp32-3248S035C-vertical -lib_deps = +lib_deps = SPI https://github.com/suchmememanyskill/lvgl https://github.com/Bodmer/TFT_eSPI.git @@ -97,7 +97,7 @@ board = esp32-2432S022C-vertical [env:esp32-CROWPANEL-28R] board = esp32-CROWPANEL-28R -lib_deps = +lib_deps = SPI https://github.com/suchmememanyskill/lvgl https://github.com/Bodmer/TFT_eSPI.git @@ -108,12 +108,37 @@ lib_deps = [env:esp32-CROWPANEL-35C] board = esp32-CROWPANEL-35C -lib_deps = +lib_deps = SPI 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 plageoj/UrlEncode@^1.0.1 knolleary/PubSubClient@^2.8 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 \ No newline at end of file diff --git a/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp b/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp index f6494be..00ccf60 100644 --- a/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp +++ b/CYD-Klipper/src/core/bambu/bambu_printer_panels.cpp @@ -161,7 +161,7 @@ struct }; } __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_timelapse, set_bambu_option_timelapse) diff --git a/CYD-Klipper/src/core/device/ESP32-JC3248W535C.cpp b/CYD-Klipper/src/core/device/ESP32-JC3248W535C.cpp new file mode 100644 index 0000000..71f91b7 --- /dev/null +++ b/CYD-Klipper/src/core/device/ESP32-JC3248W535C.cpp @@ -0,0 +1,184 @@ +#ifdef CYD_BOARD_JC3248W535C + +#include "../screen_driver.h" +#include +#include +#include +#include "lvgl.h" +#include "../lv_setup.h" +#include "../../conf/global_config.h" +#include +#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 diff --git a/CYD-Klipper/src/core/device/ESP32-JC4827W543C.cpp b/CYD-Klipper/src/core/device/ESP32-JC4827W543C.cpp new file mode 100644 index 0000000..0804109 --- /dev/null +++ b/CYD-Klipper/src/core/device/ESP32-JC4827W543C.cpp @@ -0,0 +1,85 @@ +#ifdef CYD_BOARD_JC4827W543C + +#include "../screen_driver.h" +#include +#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 diff --git a/CYD-Klipper/src/core/device/ESP32-JC4827W543C_touch.h b/CYD-Klipper/src/core/device/ESP32-JC4827W543C_touch.h new file mode 100644 index 0000000..a5fce22 --- /dev/null +++ b/CYD-Klipper/src/core/device/ESP32-JC4827W543C_touch.h @@ -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 +#include +XPT2046_Touchscreen ts(TOUCH_XPT2046_CS, TOUCH_XPT2046_INT); + +#elif defined(TOUCH_MODULE_ADDR) // TouchLib +#include +#include +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; +} diff --git a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp index bc96566..10ffabe 100644 --- a/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp +++ b/CYD-Klipper/src/core/klipper-serial/serial_klipper_printer_integration.cpp @@ -274,6 +274,12 @@ bool SerialKlipperPrinter::set_power_device_state(const char* device_name, bool 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 files_result = {0}; @@ -291,7 +297,7 @@ Files SerialKlipperPrinter::get_files() 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()); diff --git a/CYD-Klipper/src/ui/macros.cpp b/CYD-Klipper/src/ui/macros.cpp index 727479e..abebac9 100644 --- a/CYD-Klipper/src/ui/macros.cpp +++ b/CYD-Klipper/src/ui/macros.cpp @@ -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) { - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); DoubleStorage* device = (DoubleStorage*)lv_event_get_user_data(e); LOG_F(("Power Device: %s, State: %d -> %d\n", device->power_device_name, !checked, checked)) diff --git a/CYD-Klipper/src/ui/panels/settings_panel.cpp b/CYD-Klipper/src/ui/panels/settings_panel.cpp index 8fbce5b..be527f3 100644 --- a/CYD-Klipper/src/ui/panels/settings_panel.cpp +++ b/CYD-Klipper/src/ui/panels/settings_panel.cpp @@ -15,8 +15,7 @@ #endif // REPO_VERSION static void invert_color_switch(lv_event_t * e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.printer_config[global_config.printer_index].invert_colors = checked; write_global_config(); 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){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); get_current_printer()->printer_config->light_mode = checked; write_global_config(); set_color_scheme(); } static void filament_move_mode_switch(lv_event_t * e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); get_current_printer()->printer_config->custom_filament_move_macros = checked; 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){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.display_mode = checked; write_global_config(); ESP.restart(); } static void disable_m117_messaging_switch(lv_event_t* e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.disable_m117_messaging = checked; write_global_config(); } static void sort_macros_switch(lv_event_t* e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.sort_macros = checked; write_global_config(); } static void show_estop_switch(lv_event_t* e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.show_estop = checked; write_global_config(); } static void full_filenames_switch(lv_event_t* e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.full_filenames = checked; write_global_config(); } static void double_size_gcode_img_switch(lv_event_t* e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.double_size_gcode_img = checked; write_global_config(); } static void rotate_screen_switch(lv_event_t* e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.rotate_screen = checked; global_config.screen_calibrated = false; 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){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.on_during_print = checked; check_if_screen_needs_to_be_disabled(); 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){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.auto_ota_update = checked; write_global_config(); } static void multi_printer_switch(lv_event_t* e){ - auto state = lv_obj_get_state(lv_event_get_target(e)); - bool checked = (state & LV_STATE_CHECKED == LV_STATE_CHECKED); + bool checked = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); global_config.multi_printer_mode = checked; write_global_config(); nav_buttons_setup(PANEL_SETTINGS); diff --git a/CYD-Klipper/src/ui/panels/temp_panel.cpp b/CYD-Klipper/src/ui/panels/temp_panel.cpp index bbdfc9a..5a6306d 100644 --- a/CYD-Klipper/src/ui/panels/temp_panel.cpp +++ b/CYD-Klipper/src/ui/panels/temp_panel.cpp @@ -161,9 +161,7 @@ static void set_temp_via_preset(lv_event_t * e){ } static void btn_toggleable_edit(lv_event_t * e){ - 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); + temp_edit_mode = lv_obj_has_state(lv_event_get_target(e), LV_STATE_CHECKED); } static void btn_retract(lv_event_t * e){ diff --git a/CYD-Klipper/src/ui/serial/serial_console.cpp b/CYD-Klipper/src/ui/serial/serial_console.cpp index 0615cee..06a7a46 100644 --- a/CYD-Klipper/src/ui/serial/serial_console.cpp +++ b/CYD-Klipper/src/ui/serial/serial_console.cpp @@ -5,11 +5,49 @@ #define MAX_COMDLINE_SIZE 80 #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 { 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().. * 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) { static int index = 0; + static int cur = 0; 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! @@ -28,43 +67,75 @@ namespace serial_console --cnt; // backspaceF - if (c == 8) - { - if (index > 0) - { - if(temporary_config.remote_echo) Serial.print("\x08 \x08"); // overwrite last character with space and move cursor 1 back. + if (c == BACKSPACE_CHAR && cur > 0) { + // shift characters left from cursor position + memmove(&result[cur - 1], &result[cur], index - cur); 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 - - // Buffer overflow handling: - // start treating current buffer as invalid: - // - stop collecting more data - // - return false on delimeter, flushing everything collected, - // - restart collection from scratch after delimeter, - // - return control as normal. - - if (index >= max_len - 1) - { - if (c == delimiter) // got delimeter: flush buffer quietly, restart collection. - { + // Handle printable characters + } else if (c >= PRINT_CHAR_START && c <= PRINT_CHAR_END) { + // Append character at the end + if (index < max_len - 1 && cur == index) { + if(temporary_config.remote_echo) Serial.print((char)c); + result[index++] = c; + cur++; + // Insert character in the middl + } else if (index < max_len - 1) { + memmove(&result[cur + 1], &result[cur], index - cur); + result[cur] = c; + 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; + cur = 0; return false; } - else - continue; // discard any data past the end of the buffer, keep reading - } - - result[index++] = c; - // delimiter was found - if (c == delimiter) - { + } else if (c == delimiter) { + + if(temporary_config.remote_echo) Serial.println(); result[index] = '\0'; // Null-terminate the string index = 0; + cur = 0; return true; // Success: Delimiter found } } diff --git a/ci.json b/ci.json new file mode 100644 index 0000000..03a87ac --- /dev/null +++ b/ci.json @@ -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" + } +} \ No newline at end of file diff --git a/ci.py b/ci.py index 2aa9040..37dce57 100644 --- a/ci.py +++ b/ci.py @@ -1,40 +1,19 @@ 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() -def get_manifest(base_path : str, device_name : str): +def get_manifest(base_path : str, device_name : str, is_s3 : bool): return { "name": f"to {device_name}", "funding_url": "https://ko-fi.com/suchmememanyskill", "new_install_prompt_erase": True, "builds": [ { - "chipFamily": "ESP32-S3" if device_name in ESP_S3_CHIPS else "ESP32", + "chipFamily": "ESP32-S3" if is_s3 else "ESP32", "parts": [ { "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", @@ -59,6 +38,7 @@ def extract_commit() -> str: repo_version = extract_commit() configurations = [] +site_sections : dict[str, dict] = {"CYD": []} def add_configuration(board : str): configurations.append({ @@ -67,10 +47,32 @@ def add_configuration(board : str): "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"): 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}" os.chdir(BASE_DIR) 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") os.chdir(port_path) - if (port in ESP_S3_CHIPS): - 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) + if (bool(data["s3"])): + 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: - 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) 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) + if "site" in data and data["site"]: + add_site_section(port, data) + os.chdir(BASE_DIR) out_dir = "./_site/out" if os.path.exists(out_dir): @@ -102,3 +107,16 @@ shutil.copytree("./out", out_dir) with open("./_site/OTA.json", "w") as 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"" for x in sections] + section_html = f"{''.join(option_htmls)}" + insert_html += section_html + + fp.write(template.replace("{{%PORTS%}}", insert_html)) \ No newline at end of file diff --git a/_site/index.html b/template.html similarity index 88% rename from _site/index.html rename to template.html index b3766a9..619b09f 100644 --- a/_site/index.html +++ b/template.html @@ -132,15 +132,7 @@

Install

Select your device from the list below and click 'Connect'.
Note: You may need to hold the 'BOOT' button on the device while pressing install.

The 2.8" Resistive and 3.5" Capacitive models are best suited (in my opinion) for CYD-Klipper.

Note for any resistive models: You can clear touch calibration by holding the BOOT button for 8 seconds while the screen is on.