diff --git a/.github/workflows/compile.yaml b/.github/workflows/compile.yaml index 179f9e4..ab781aa 100644 --- a/.github/workflows/compile.yaml +++ b/.github/workflows/compile.yaml @@ -4,7 +4,7 @@ permissions: pages: write id-token: write -on: [push, pull_request] +on: [push, pull_request, workflow_dispatch] jobs: build: @@ -17,7 +17,7 @@ jobs: path: | ~/.cache/pip ~/.platformio/.cache - key: ${{ runner.os }}-pio + key: ${{ runner.os }}-pio-cyd-klipper - uses: actions/setup-python@v4 with: @@ -28,27 +28,13 @@ jobs: - name: Build PlatformIO Project run: | - cd CYD-Klipper - pio run - - - name: Make output dir - run: | - mkdir -p output - - - name: Build Binary - run: | - cp ./CYD-Klipper/.pio/build/esp32dev/bootloader.bin output - cp ./CYD-Klipper/.pio/build/esp32dev/partitions.bin output - cp ./CYD-Klipper/.pio/build/esp32dev/firmware.bin output - cp ~/.platformio/packages/framework-arduinoespressif32/tools/partitions/boot_app0.bin output - python3 -m esptool --chip esp32 merge_bin -o ./output/merged-firmware.bin --flash_mode dio --flash_freq 40m --flash_size 4MB 0x1000 ./output/bootloader.bin 0x8000 ./output/partitions.bin 0xe000 ./output/boot_app0.bin 0x10000 ./output/firmware.bin - cp -r ./output ./_site + python3 ci.py - name: Upload artifact uses: actions/upload-artifact@v3 with: name: firmware - path: ./output + path: ./out - name: Upload GitHub Page Artifact uses: actions/upload-pages-artifact@v2 @@ -59,7 +45,7 @@ jobs: url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build - if: github.event_name == 'push' && github.ref == 'refs/heads/master' + if: github.event_name != 'pull_request' && github.ref == 'refs/heads/master' steps: - name: Print GitHub event name run: | diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e69de29 diff --git a/CYD-Klipper/.vscode/settings.json b/CYD-Klipper/.vscode/settings.json index 75d2259..e9997e2 100644 --- a/CYD-Klipper/.vscode/settings.json +++ b/CYD-Klipper/.vscode/settings.json @@ -9,6 +9,9 @@ "vector": "cpp", "string_view": "cpp", "initializer_list": "cpp", - "algorithm": "cpp" + "algorithm": "cpp", + "cstddef": "cpp", + "functional": "cpp", + "*.tcc": "cpp" } } \ No newline at end of file diff --git a/CYD-Klipper/boards/README.md b/CYD-Klipper/boards/README.md new file mode 100644 index 0000000..c9de6d8 --- /dev/null +++ b/CYD-Klipper/boards/README.md @@ -0,0 +1,3 @@ +# Boards + +Contains specialised CYD definitions from [platformio-espressif32-sunton](https://github.com/rzeldent/platformio-espressif32-sunton) \ No newline at end of file diff --git a/CYD-Klipper/boards/esp32-2432S028R.json b/CYD-Klipper/boards/esp32-2432S028R.json new file mode 100644 index 0000000..640ec47 --- /dev/null +++ b/CYD-Klipper/boards/esp32-2432S028R.json @@ -0,0 +1,66 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DUSER_SETUP_LOADED=1", + "-DILI9341_2_DRIVER=1", + "-DTFT_BACKLIGHT_ON=HIGH", + "-DTFT_BL=21", + "-DTFT_MISO=12", + "-DTFT_MOSI=13", + "-DTFT_SCLK=14", + "-DTFT_CS=15", + "-DTFT_DC=2", + "-DTFT_RST=-1", + "-DLOAD_GCLD=1", + "-DLOAD_FONT2=1", + "-DLOAD_GFXFF=1", + "-DSMOOTH_FONT=1", + "-DSPI_FREQUENCY=55000000", + "-DSPI_READ_FREQUENCY=20000000", + "-DSPI_TOUCH_FREQUENCY=2500000", + "-DTOUCH_CS=-1", + + "-DCYD_SCREEN_HEIGHT_PX=240", + "-DCYD_SCREEN_WIDTH_PX=320", + "-DCYD_SCREEN_GAP_PX=8", + "-DCYD_SCREEN_MIN_BUTTON_HEIGHT_PX=35", + "-DCYD_SCREEN_MIN_BUTTON_WIDTH_PX=35", + "-DCYD_SCREEN_FONT=lv_font_montserrat_14", + "-DCYD_SCREEN_FONT_SMALL=lv_font_montserrat_10", + "-DCYD_SCREEN_SIDEBAR_SIZE_PX=40", + "-DCYD_SCREEN_DRIVER_ESP32_2432S028R=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "esp32-2432S028R", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.aliexpress.com/item/1005004502250619.html", + "vendor": "Sunton" + } \ No newline at end of file diff --git a/CYD-Klipper/boards/esp32-3248S035C-smartdisplay.json b/CYD-Klipper/boards/esp32-3248S035C-smartdisplay.json new file mode 100644 index 0000000..07da97e --- /dev/null +++ b/CYD-Klipper/boards/esp32-3248S035C-smartdisplay.json @@ -0,0 +1,108 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "'-D ARDUINO_ESP32_DEV'", + "'-D ESP32_3248S035C'", + "'-D LCD_WIDTH=320'", + "'-D LCD_HEIGHT=480'", + "'-D BCKL=27'", + "'-D LCD_ST7796_SPI'", + "'-D ST7796_SPI_HOST=SPI2_HOST'", + "'-D ST7796_SPI_DMA_CHANNEL=SPI_DMA_CH_AUTO'", + "'-D ST7796_SPI_BUS_MOSI_IO_NUM=13'", + "'-D ST7796_SPI_BUS_MISO_IO_NUM=12'", + "'-D ST7796_SPI_BUS_SCLK_IO_NUM=14'", + "'-D ST7796_SPI_BUS_QUADWP_IO_NUM=GPIO_NUM_NC'", + "'-D ST7796_SPI_BUS_QUADHD_IO_NUM=GPIO_NUM_NC'", + "'-D ST7796_SPI_CONFIG_CS_GPIO_NUM=15'", + "'-D ST7796_SPI_CONFIG_DC_GPIO_NUM=2'", + "'-D ST7796_SPI_CONFIG_SPI_MODE=SPI_MODE0'", + "'-D ST7796_SPI_CONFIG_PCLK_HZ=24000000'", + "'-D ST7796_SPI_CONFIG_TRANS_QUEUE_DEPTH=10'", + "'-D ST7796_SPI_CONFIG_LCD_CMD_BITS=8'", + "'-D ST7796_SPI_CONFIG_LCD_PARAM_BITS=8'", + "'-D ST7796_SPI_CONFIG_FLAGS_DC_AS_CMD_PHASE=false'", + "'-D ST7796_SPI_CONFIG_FLAGS_DC_LOW_ON_DATA=false'", + "'-D ST7796_SPI_CONFIG_FLAGS_OCTAL_MODE=false'", + "'-D ST7796_SPI_CONFIG_FLAGS_LSB_FIRST=false'", + "'-D ST7796_DEV_CONFIG_RESET_GPIO_NUM=GPIO_NUM_NC'", + "'-D ST7796_DEV_CONFIG_COLOR_SPACE=ESP_LCD_COLOR_SPACE_BGR'", + "'-D ST7796_DEV_CONFIG_BITS_PER_PIXEL=16'", + "'-D ST7796_DEV_CONFIG_FLAGS_RESET_ACTIVE_HIGH=false'", + "'-D ST7796_DEV_CONFIG_VENDOR_CONFIG=NULL'", + "'-D LCD_SWAP_XY=false'", + "'-D LCD_MIRROR_X=true'", + "'-D LCD_MIRROR_Y=false'", + "'-D BOARD_HAS_TOUCH'", + "'-D TOUCH_GT911_I2C'", + "'-D GT911_I2C_HOST=0'", + "'-D GT911_I2C_CONFIG_SDA_IO_NUM=33'", + "'-D GT911_I2C_CONFIG_SCL_IO_NUM=32'", + "'-D GT911_I2C_CONFIG_SDA_PULLUP_EN=GPIO_PULLUP_ENABLE'", + "'-D GT911_I2C_CONFIG_SCL_PULLUP_EN=GPIO_PULLUP_ENABLE'", + "'-D GT911_I2C_CONFIG_MASTER_CLK_SPEED=400000'", + "'-D GT911_I2C_CONFIG_CLK_FLAGS=0'", + "'-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=25'", + "'-D GT911_TOUCH_CONFIG_INT_GPIO_NUM=21'", + "'-D GT911_TOUCH_CONFIG_LEVELS_RESET=0'", + "'-D GT911_TOUCH_CONFIG_LEVELS_INTERRUPT=0'", + "'-D TOUCH_SWAP_XY=true'", + "'-D TOUCH_SWAP_X=false'", + "'-D TOUCH_SWAP_Y=false'", + "'-D BOARD_HAS_TF'", + "'-D TF_CS=5'", + "'-D TF_SPI_MOSI=23'", + "'-D TF_SPI_SCLK=18'", + "'-D TF_SPI_MISO=19'", + "'-D BOARD_HAS_RGB_LED'", + "'-D RGB_LED_R=4'", + "'-D RGB_LED_G=16'", + "'-D RGB_LED_B=17'", + "'-D BOARD_HAS_CDS'", + "'-D CDS=34'", + "'-D BOARD_HAS_SPEAK'", + "'-D SPEAK=26'" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "esp32-3248S035C", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.aliexpress.com/item/1005004632953455.html", + "vendor": "Sunton" + } \ No newline at end of file diff --git a/CYD-Klipper/boards/esp32-3248S035C.json b/CYD-Klipper/boards/esp32-3248S035C.json new file mode 100644 index 0000000..d62a8bb --- /dev/null +++ b/CYD-Klipper/boards/esp32-3248S035C.json @@ -0,0 +1,67 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DUSER_SETUP_LOADED=1", + "-DST7796_DRIVER=1", + "-DTFT_BL=27", + "-DTFT_BACKLIGHT_ON=HIGH", + "-DTFT_MISO=12", + "-DTFT_MOSI=13", + "-DTFT_SCLK=14", + "-DTFT_CS=15", + "-DTFT_DC=2", + "-DTFT_RST=-1", + "-DLOAD_GCLD=1", + "-DLOAD_FONT2=1", + "-DLOAD_GFXFF=1", + "-DSMOOTH_FONT=1", + "-DSPI_FREQUENCY=55000000", + "-DSPI_READ_FREQUENCY=20000000", + "-DSPI_TOUCH_FREQUENCY=2500000", + "-DTOUCH_CS=-1", + + "-DCYD_SCREEN_HEIGHT_PX=320", + "-DCYD_SCREEN_WIDTH_PX=480", + "-DCYD_SCREEN_GAP_PX=10", + "-DCYD_SCREEN_MIN_BUTTON_HEIGHT_PX=40", + "-DCYD_SCREEN_MIN_BUTTON_WIDTH_PX=40", + "-DCYD_SCREEN_FONT=lv_font_montserrat_16", + "-DCYD_SCREEN_FONT_SMALL=lv_font_montserrat_12", + "-DCYD_SCREEN_SIDEBAR_SIZE_PX=50", + "-DCYD_SCREEN_DRIVER_ESP32_3248S035C=1", + "-DCYD_SCREEN_DISABLE_TOUCH_CALIBRATION=1" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "esp32-3248S035C", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.aliexpress.com/item/1005004632953455.html", + "vendor": "Sunton" + } \ No newline at end of file diff --git a/CYD-Klipper/extract_commit.py b/CYD-Klipper/extract_commit.py new file mode 100644 index 0000000..106d4bb --- /dev/null +++ b/CYD-Klipper/extract_commit.py @@ -0,0 +1,23 @@ +import subprocess + +def extract_commit() -> tuple[str, str]: # Version, Commit + git_describe_output = subprocess.run(["git", "describe", "--tags"], stdout=subprocess.PIPE, text=True, check=True).stdout.strip() + split_output = git_describe_output.split("-") + return split_output[0], split_output[2][1:] + +try: + data = extract_commit() + version = f"{data[0]}\\ ({data[1]})" +except: + version = "Unknown" + + +flag = "-D REPO_VERSION=\\\"" + version + "\\\"" +print(f"Version: {version}") +print(f"Flag: {flag}") + +Import("env") + +env.Append( + BUILD_FLAGS=[flag] +) \ No newline at end of file diff --git a/CYD-Klipper/platformio.ini b/CYD-Klipper/platformio.ini index c04f71d..5a6c0ed 100644 --- a/CYD-Klipper/platformio.ini +++ b/CYD-Klipper/platformio.ini @@ -8,36 +8,52 @@ ; Please visit documentation for the other options and examples ; https://docs.platformio.org/page/projectconf.html -[env:esp32dev] +[env] platform = espressif32 board = esp32dev framework = arduino monitor_speed = 115200 lib_deps = - SPI - lvgl/lvgl@^8.3.9 - https://github.com/Bodmer/TFT_eSPI.git - https://github.com/PaulStoffregen/XPT2046_Touchscreen.git + https://github.com/suchmememanyskill/esp32-smartdisplay bblanchon/ArduinoJson@^7.0.0 + plageoj/UrlEncode@^1.0.1 monitor_filters = esp32_exception_decoder build_flags = -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" - -DUSER_SETUP_LOADED=1 - -DILI9341_2_DRIVER=1 - -DTFT_WIDTH=240 - -DTFT_HEIGHT=320 - -DTFT_BL=21 - -DTFT_BACKLIGHT_ON=HIGH - -DTFT_MISO=12 - -DTFT_MOSI=13 - -DTFT_SCLK=14 - -DTFT_CS=15 - -DTFT_DC=2 - -DTFT_RST=-1 - -DLOAD_GCLD=1 - -DLOAD_FONT2=1 - -DLOAD_GFXFF=1 - -DSMOOTH_FONT=1 - -DSPI_FREQUENCY=55000000 - -DSPI_READ_FREQUENCY=20000000 - -DSPI_TOUCH_FREQUENCY=2500000 +extra_scripts = + pre:extract_commit.py + +[env:esp32-2432S028R] +board = esp32-2432S028R +lib_deps = + SPI + https://github.com/suchmememanyskill/lvgl + https://github.com/Bodmer/TFT_eSPI.git + https://github.com/PaulStoffregen/XPT2046_Touchscreen.git + bblanchon/ArduinoJson@^7.0.0 + plageoj/UrlEncode@^1.0.1 + +[env:esp32-3248S035C] +board = esp32-3248S035C +lib_deps = + SPI + https://github.com/suchmememanyskill/lvgl + https://github.com/Bodmer/TFT_eSPI.git + https://github.com/OperatorB/gt911-arduino-fixed-reset.git + bblanchon/ArduinoJson@^7.0.0 + plageoj/UrlEncode@^1.0.1 + +# Terribly slow. Only use for development +# [env:esp32-3248S035C-smartdisplay] +# board = esp32-3248S035C-smartdisplay +# build_flags = +# -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" +# -DCYD_SCREEN_HEIGHT_PX=320 +# -DCYD_SCREEN_WIDTH_PX=480 +# -DCYD_SCREEN_GAP_PX=10 +# -DCYD_SCREEN_MIN_BUTTON_HEIGHT_PX=40 +# -DCYD_SCREEN_MIN_BUTTON_WIDTH_PX=40 +# -DCYD_SCREEN_FONT=lv_font_montserrat_16 +# -DCYD_SCREEN_FONT_SMALL=lv_font_montserrat_12 +# -DCYD_SCREEN_SIDEBAR_SIZE_PX=50 +# -DCYD_SCREEN_DRIVER_ESP32_SMARTDISPLAY=1 \ No newline at end of file diff --git a/CYD-Klipper/src/conf/lv_conf.h b/CYD-Klipper/src/conf/lv_conf.h index d5979b6..b1be702 100644 --- a/CYD-Klipper/src/conf/lv_conf.h +++ b/CYD-Klipper/src/conf/lv_conf.h @@ -327,9 +327,9 @@ *https://fonts.google.com/specimen/Montserrat*/ #define LV_FONT_MONTSERRAT_8 0 #define LV_FONT_MONTSERRAT_10 1 -#define LV_FONT_MONTSERRAT_12 0 +#define LV_FONT_MONTSERRAT_12 1 #define LV_FONT_MONTSERRAT_14 1 -#define LV_FONT_MONTSERRAT_16 0 +#define LV_FONT_MONTSERRAT_16 1 #define LV_FONT_MONTSERRAT_18 0 #define LV_FONT_MONTSERRAT_20 0 #define LV_FONT_MONTSERRAT_22 0 diff --git a/CYD-Klipper/src/core/data_setup.cpp b/CYD-Klipper/src/core/data_setup.cpp index b02b986..d240d6d 100644 --- a/CYD-Klipper/src/core/data_setup.cpp +++ b/CYD-Klipper/src/core/data_setup.cpp @@ -6,6 +6,7 @@ #include #include #include "macros_query.h" +#include const char *printer_state_messages[] = { "Error", @@ -43,8 +44,9 @@ void unfreeze_render_thread(){ void send_gcode(bool wait, const char *gcode) { + Serial.printf("Sending gcode: %s\n", gcode); char buff[256] = {}; - sprintf(buff, "http://%s:%d/printer/gcode/script?script=%s", global_config.klipperHost, global_config.klipperPort, gcode); + sprintf(buff, "http://%s:%d/printer/gcode/script?script=%s", global_config.klipperHost, global_config.klipperPort, urlEncode(gcode).c_str()); HTTPClient client; client.begin(buff); @@ -67,7 +69,7 @@ void fetch_printer_data() { freeze_request_thread(); char buff[256] = {}; - sprintf(buff, "http://%s:%d/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks", global_config.klipperHost, global_config.klipperPort); + sprintf(buff, "http://%s:%d/printer/objects/query?extruder&heater_bed&toolhead&gcode_move&virtual_sdcard&print_stats&webhooks&fan", global_config.klipperHost, global_config.klipperPort); HTTPClient client; client.useHTTP10(true); client.begin(buff); @@ -119,6 +121,7 @@ void fetch_printer_data() printer.extruder_temp = status["extruder"]["temperature"]; printer.extruder_target_temp = status["extruder"]["target"]; bool can_extrude = status["extruder"]["can_extrude"]; + printer.pressure_advance = status["extruder"]["pressure_advance"]; printer.can_extrude = can_extrude == true; } @@ -139,8 +142,20 @@ void fetch_printer_data() printer.position[0] = status["gcode_move"]["gcode_position"][0]; printer.position[1] = status["gcode_move"]["gcode_position"][1]; printer.position[2] = status["gcode_move"]["gcode_position"][2]; + printer.gcode_offset[0] = status["gcode_move"]["homing_origin"][0]; + printer.gcode_offset[1] = status["gcode_move"]["homing_origin"][1]; + printer.gcode_offset[2] = status["gcode_move"]["homing_origin"][2]; bool absolute_coords = status["gcode_move"]["absolute_coordinates"]; printer.absolute_coords = absolute_coords == true; + printer.speed_mult = status["gcode_move"]["speed_factor"]; + printer.extrude_mult = status["gcode_move"]["extrude_factor"]; + printer.feedrate_mm_per_s = status["gcode_move"]["speed"]; + printer.feedrate_mm_per_s /= 60; // convert mm/m to mm/s + } + + if (status.containsKey("fan")) + { + printer.fan_speed = status["fan"]["speed"]; } if (status.containsKey("virtual_sdcard")) @@ -155,6 +170,8 @@ void fetch_printer_data() printer.print_filename = filename_buff; printer.elapsed_time_s = status["print_stats"]["print_duration"]; printer.filament_used_mm = status["print_stats"]["filament_used"]; + printer.total_layers = status["print_stats"]["info"]["total_layer"]; + printer.current_layer = status["print_stats"]["info"]["current_layer"]; const char *state = status["print_stats"]["state"]; diff --git a/CYD-Klipper/src/core/data_setup.h b/CYD-Klipper/src/core/data_setup.h index fc0a44f..57e4e74 100644 --- a/CYD-Klipper/src/core/data_setup.h +++ b/CYD-Klipper/src/core/data_setup.h @@ -25,6 +25,14 @@ typedef struct _Printer { float filament_used_mm; char* print_filename; // 0 -> 1 float print_progress; + float fan_speed; // 0 -> 1 + float gcode_offset[3]; + float speed_mult; + float extrude_mult; + int total_layers; + int current_layer; + float pressure_advance; + int feedrate_mm_per_s; } Printer; extern Printer printer; diff --git a/CYD-Klipper/src/core/screen_driver.cpp b/CYD-Klipper/src/core/device/ESP32-2432S028R.cpp similarity index 58% rename from CYD-Klipper/src/core/screen_driver.cpp rename to CYD-Klipper/src/core/device/ESP32-2432S028R.cpp index ae06f78..0332dfa 100644 --- a/CYD-Klipper/src/core/screen_driver.cpp +++ b/CYD-Klipper/src/core/device/ESP32-2432S028R.cpp @@ -1,22 +1,30 @@ -#include "screen_driver.h" +#ifdef CYD_SCREEN_DRIVER_ESP32_2432S028R +#include "../screen_driver.h" + #include #include -#include "../conf/global_config.h" +#include "../../conf/global_config.h" #include "lvgl.h" +#include +#include +#include "../lv_setup.h" + +#define XPT2046_IRQ 36 +#define XPT2046_MOSI 32 +#define XPT2046_MISO 39 +#define XPT2046_CLK 25 +#define XPT2046_CS 33 +#define CPU_FREQ_HIGH 240 +#define CPU_FREQ_LOW 80 SPIClass touchscreen_spi = SPIClass(HSPI); XPT2046_Touchscreen touchscreen(XPT2046_CS, XPT2046_IRQ); -uint32_t LV_EVENT_GET_COMP_CHILD; - static lv_disp_draw_buf_t draw_buf; -static lv_color_t buf[TFT_WIDTH * TFT_HEIGHT / 10]; +static lv_color_t buf[CYD_SCREEN_HEIGHT_PX * CYD_SCREEN_WIDTH_PX / 10]; TFT_eSPI tft = TFT_eSPI(); -bool isScreenInSleep = false; -lv_timer_t *screenSleepTimer; - TS_Point touchscreen_point() { TS_Point p = touchscreen.getPoint(); @@ -91,61 +99,6 @@ void screen_setBrightness(byte brightness) ledcWrite(0, duty); } -void set_screen_brightness() -{ - if (global_config.brightness < 32) - screen_setBrightness(255); - else - screen_setBrightness(global_config.brightness); -} - -void screen_timer_wake() -{ - lv_timer_reset(screenSleepTimer); - isScreenInSleep = false; - set_screen_brightness(); - - // Reset cpu freq - setCpuFrequencyMhz(CPU_FREQ_HIGH); - Serial.printf("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()); -} - -void screen_timer_sleep(lv_timer_t *timer) -{ - screen_setBrightness(0); - isScreenInSleep = true; - - // Screen is off, no need to make the cpu run fast, the user won't notice ;) - setCpuFrequencyMhz(CPU_FREQ_LOW); - Serial.printf("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()); -} - -void screen_timer_setup() -{ - screenSleepTimer = lv_timer_create(screen_timer_sleep, global_config.screenTimeout * 1000 * 60, NULL); - lv_timer_pause(screenSleepTimer); -} - -void screen_timer_start() -{ - lv_timer_resume(screenSleepTimer); -} - -void screen_timer_stop() -{ - lv_timer_pause(screenSleepTimer); -} - -void screen_timer_period(uint32_t period) -{ - lv_timer_set_period(screenSleepTimer, period); -} - -void set_screen_timer_period() -{ - screen_timer_period(global_config.screenTimeout * 1000 * 60); -} - 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); @@ -161,19 +114,8 @@ void screen_lv_flush(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *col void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) { - if (touchscreen.tirqTouched() && touchscreen.touched()) { - lv_timer_reset(screenSleepTimer); - // dont pass first touch after power on - if (isScreenInSleep) - { - screen_timer_wake(); - while (touchscreen.touched()) - ; - return; - } - TS_Point p = touchscreen_point(); data->state = LV_INDEV_STATE_PR; data->point.x = p.x; @@ -185,25 +127,6 @@ void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) } } -void set_color_scheme(){ - lv_disp_t *dispp = lv_disp_get_default(); - lv_color_t main_color = {0}; - COLOR_DEF color_def = color_defs[global_config.color_scheme]; - - if (color_defs[global_config.color_scheme].primary_color_light > 0){ - main_color = lv_palette_lighten(color_def.primary_color, color_def.primary_color_light); - } - else if (color_defs[global_config.color_scheme].primary_color_light < 0) { - main_color = lv_palette_darken(color_def.primary_color, color_def.primary_color_light * -1); - } - else { - main_color = lv_palette_main(color_defs[global_config.color_scheme].primary_color); - } - - lv_theme_t *theme = lv_theme_default_init(dispp, main_color, lv_palette_main(color_def.secondary_color), !global_config.lightMode, LV_FONT_DEFAULT); - lv_disp_set_theme(dispp, theme); -} - void set_invert_display(){ tft.invertDisplay(global_config.invertColors); } @@ -229,31 +152,25 @@ void screen_setup() touchscreen_spi.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS); touchscreen.begin(touchscreen_spi); - touchscreen_calibrate(); + touchscreen_calibrate(false); - lv_disp_draw_buf_init(&draw_buf, buf, NULL, TFT_WIDTH * TFT_HEIGHT / 10); + lv_disp_draw_buf_init(&draw_buf, buf, NULL, CYD_SCREEN_HEIGHT_PX * CYD_SCREEN_WIDTH_PX / 10); /*Initialize the display*/ static lv_disp_drv_t disp_drv; lv_disp_drv_init(&disp_drv); - disp_drv.hor_res = TFT_HEIGHT; - disp_drv.ver_res = TFT_WIDTH; + disp_drv.hor_res = CYD_SCREEN_WIDTH_PX; + disp_drv.ver_res = CYD_SCREEN_HEIGHT_PX; disp_drv.flush_cb = screen_lv_flush; disp_drv.draw_buf = &draw_buf; lv_disp_drv_register(&disp_drv); - /*Initialize the (dummy) input device driver*/ 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); +} - screen_timer_setup(); - screen_timer_start(); - - /*Initialize the graphics library */ - LV_EVENT_GET_COMP_CHILD = lv_event_register_id(); - set_color_scheme(); -} \ No newline at end of file +#endif // CYD_SCREEN_DRIVER_ESP32_2432S028R \ No newline at end of file diff --git a/CYD-Klipper/src/core/device/ESP32-3248S035C.cpp b/CYD-Klipper/src/core/device/ESP32-3248S035C.cpp new file mode 100644 index 0000000..630107f --- /dev/null +++ b/CYD-Klipper/src/core/device/ESP32-3248S035C.cpp @@ -0,0 +1,135 @@ +#ifdef CYD_SCREEN_DRIVER_ESP32_3248S035C + +#include "lvgl.h" +#include +#include +#include "../../conf/global_config.h" +#include "../lv_setup.h" + +#define TOUCH_SDA 33 +#define TOUCH_SCL 32 +#define TOUCH_INT 21 +#define TOUCH_RST 25 +#define TOUCH_WIDTH 320 +#define TOUCH_HEIGHT 480 + +#define LED_PIN_R 4 +#define LED_PIN_G 16 +#define LED_PIN_B 17 + +TAMC_GT911 tp = TAMC_GT911(TOUCH_SDA, TOUCH_SCL, TOUCH_INT, TOUCH_RST, TOUCH_WIDTH, TOUCH_HEIGHT); + +static lv_disp_draw_buf_t draw_buf; +static lv_color_t buf[CYD_SCREEN_HEIGHT_PX * CYD_SCREEN_WIDTH_PX / 10]; + +TFT_eSPI tft = TFT_eSPI(); + +void screen_setBrightness(byte brightness) +{ + // calculate duty, 4095 from 2 ^ 12 - 1 + uint32_t duty = (4095 / 255) * brightness; + + // write duty to LEDC + 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); + + tft.startWrite(); + tft.setAddrWindow(area->x1, area->y1, w, h); + tft.pushColors((uint16_t *)&color_p->full, w * h, true); + tft.endWrite(); + + lv_disp_flush_ready(disp); +} + +void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) +{ + tp.read(); + if (!tp.isTouched) + { + data->state = LV_INDEV_STATE_REL; + } + else + { + data->state = LV_INDEV_STATE_PR; + for (int i = 0; i < tp.touches; i++) + { + uint16_t magicX; // fix GT911 driver - orientation and handle rotation + uint16_t magicY; + if (!global_config.rotateScreen) + { + magicY = tp.points[i].x; + magicX = TOUCH_HEIGHT - tp.points[i].y; + } + else + { + magicY = TOUCH_WIDTH - tp.points[i].x; + magicX = tp.points[i].y; + } + + data->point.x = magicX; + data->point.y = magicY; + } + } +} + +void set_invert_display() +{ + tft.invertDisplay(global_config.invertColors); +} + +void set_LED_color(uint8_t rgbVal[3]) +{ + analogWrite(LED_PIN_R, 255 - rgbVal[0]); + analogWrite(LED_PIN_G, 255 - rgbVal[1]); + analogWrite(LED_PIN_B, 255 - rgbVal[2]); +} + +void LED_init() +{ + pinMode(LED_PIN_R, OUTPUT); + pinMode(LED_PIN_G, OUTPUT); + pinMode(LED_PIN_B, OUTPUT); + uint8_t rgbVal[3] = {0, 0, 0}; + set_LED_color(rgbVal); +} + +void screen_setup() +{ + // Initialize the touchscreen + tp.begin(); + tp.setRotation(ROTATION_NORMAL); + // Initialize LVGL + lv_init(); + // Initialize the display + tft.init(); + ledcSetup(0, 5000, 12); + ledcAttachPin(TFT_BL, 0); + tft.setRotation(global_config.rotateScreen ? 3 : 1); + tft.fillScreen(TFT_BLACK); + set_screen_brightness(); + set_invert_display(); + LED_init(); + + lv_disp_draw_buf_init(&draw_buf, buf, NULL, TFT_WIDTH * TFT_HEIGHT / 10); + static lv_disp_drv_t disp_drv; + lv_disp_drv_init(&disp_drv); + disp_drv.hor_res = TFT_HEIGHT; + disp_drv.ver_res = TFT_WIDTH; + disp_drv.flush_cb = screen_lv_flush; + disp_drv.draw_buf = &draw_buf; + lv_disp_drv_register(&disp_drv); + + // Initialize the (dummy) input device driver + 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_SCREEN_DRIVER_ESP32_3248S035C \ No newline at end of file diff --git a/CYD-Klipper/src/core/device/ESP32-smartdisplay.cpp b/CYD-Klipper/src/core/device/ESP32-smartdisplay.cpp new file mode 100644 index 0000000..3855bd6 --- /dev/null +++ b/CYD-Klipper/src/core/device/ESP32-smartdisplay.cpp @@ -0,0 +1,32 @@ + +#ifdef CYD_SCREEN_DRIVER_ESP32_SMARTDISPLAY + +#include "../screen_driver.h" +#include +#include "../../conf/global_config.h" +#include "lvgl.h" +#include "../lv_setup.h" + +void touchscreen_calibrate(bool force) +{ + // TODO: Stubbed + return; +} + +void screen_setBrightness(byte brightness) +{ + smartdisplay_lcd_set_backlight(brightness / 255.0f); +} + +void set_invert_display(){ + // Stubbed +} + +void screen_setup() +{ + smartdisplay_init(); + + lv_disp_set_rotation(lv_disp_get_default(), (global_config.rotateScreen) ? LV_DISP_ROT_270 : LV_DISP_ROT_90); +} + +#endif // CYD_SCREEN_DRIVER_ESP32_SMARTDISPLAY \ No newline at end of file diff --git a/CYD-Klipper/src/core/files_query.cpp b/CYD-Klipper/src/core/files_query.cpp index 85acfa1..0fce127 100644 --- a/CYD-Klipper/src/core/files_query.cpp +++ b/CYD-Klipper/src/core/files_query.cpp @@ -31,6 +31,7 @@ FILESYSTEM_FILE* get_files(int limit){ sprintf(buff, "http://%s:%d/server/files/list", global_config.klipperHost, global_config.klipperPort); HTTPClient client; client.useHTTP10(true); + client.setTimeout(5000); client.begin(buff); int httpCode = client.GET(); auto timer_parse = millis(); @@ -53,8 +54,10 @@ FILESYSTEM_FILE* get_files(int limit){ file_iter++; } + + if (file_iter == files.end() && files.size() >= limit) + continue; - // Little inefficient as it always allocates a string, even if it doesn't have to f.name = (char*)malloc(strlen(path) + 1); if (f.name == NULL){ Serial.println("Failed to allocate memory"); diff --git a/CYD-Klipper/src/core/lv_setup.cpp b/CYD-Klipper/src/core/lv_setup.cpp new file mode 100644 index 0000000..4506d04 --- /dev/null +++ b/CYD-Klipper/src/core/lv_setup.cpp @@ -0,0 +1,146 @@ +#include "lv_setup.h" +#include "screen_driver.h" +#include "../conf/global_config.h" +#include + +#ifndef CPU_FREQ_HIGH +#define CPU_FREQ_HIGH 240 +#endif +#ifndef CPU_FREQ_LOW +#define CPU_FREQ_LOW 80 +#endif + +bool isScreenInSleep = false; +lv_timer_t *screenSleepTimer; +static lv_style_t default_label_style; + +void set_screen_brightness() +{ + if (global_config.brightness < 32) + screen_setBrightness(255); + else + screen_setBrightness(global_config.brightness); +} + +void screen_timer_wake() +{ +#ifndef CYD_SCREEN_DISABLE_TIMEOUT + lv_timer_reset(screenSleepTimer); + + if (!isScreenInSleep){ + return; + } + + isScreenInSleep = false; + set_screen_brightness(); + + // Reset cpu freq + setCpuFrequencyMhz(CPU_FREQ_HIGH); + Serial.printf("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()); +#endif +} + +void screen_timer_sleep(lv_timer_t *timer) +{ +#ifndef CYD_SCREEN_DISABLE_TIMEOUT + screen_setBrightness(0); + isScreenInSleep = true; + + // Screen is off, no need to make the cpu run fast, the user won't notice ;) + setCpuFrequencyMhz(CPU_FREQ_LOW); + Serial.printf("CPU Speed: %d MHz\n", ESP.getCpuFreqMHz()); +#endif +} + +void screen_timer_setup() +{ + screenSleepTimer = lv_timer_create(screen_timer_sleep, global_config.screenTimeout * 1000 * 60, NULL); + lv_timer_pause(screenSleepTimer); +} + +void screen_timer_start() +{ + lv_timer_resume(screenSleepTimer); +} + +void screen_timer_stop() +{ + lv_timer_pause(screenSleepTimer); +} + +void screen_timer_period(unsigned int period) +{ + lv_timer_set_period(screenSleepTimer, period); +} + +void set_screen_timer_period() +{ + screen_timer_period(global_config.screenTimeout * 1000 * 60); +} + +void set_color_scheme() +{ + lv_disp_t *dispp = lv_disp_get_default(); + lv_color_t main_color = {0}; + COLOR_DEF color_def = color_defs[global_config.color_scheme]; + + if (color_defs[global_config.color_scheme].primary_color_light > 0){ + main_color = lv_palette_lighten(color_def.primary_color, color_def.primary_color_light); + } + else if (color_defs[global_config.color_scheme].primary_color_light < 0) { + main_color = lv_palette_darken(color_def.primary_color, color_def.primary_color_light * -1); + } + else { + main_color = lv_palette_main(color_defs[global_config.color_scheme].primary_color); + } + + lv_theme_t *theme = lv_theme_default_init(dispp, main_color, lv_palette_main(color_def.secondary_color), !global_config.lightMode, &CYD_SCREEN_FONT); + lv_disp_set_theme(dispp, theme); +} + +static lv_indev_drv_read_cb_t original_driver = NULL; + +void lv_touch_intercept(lv_indev_drv_t *indev_driver, lv_indev_data_t *data) +{ + original_driver(indev_driver, data); + + if (data->state == LV_INDEV_STATE_PR) { + if (is_screen_asleep()) { + while (data->state == LV_INDEV_STATE_PR) { + original_driver(indev_driver, data); + delay(20); + } + + data->state = LV_INDEV_STATE_REL; + } + + screen_timer_wake(); + } +} + +void lv_setup() +{ + lv_style_init(&default_label_style); + lv_style_set_text_font(&default_label_style, &CYD_SCREEN_FONT); + + screen_timer_setup(); + screen_timer_start(); + set_color_scheme(); + + if (original_driver != NULL) + return; + + lv_indev_t * display_driver = lv_indev_get_next(NULL); + original_driver = display_driver->driver->read_cb; + display_driver->driver->read_cb = lv_touch_intercept; +} + +bool is_screen_asleep() +{ + return isScreenInSleep; +} + +lv_style_t * get_default_label_style() +{ + return &default_label_style; +} \ No newline at end of file diff --git a/CYD-Klipper/src/core/lv_setup.h b/CYD-Klipper/src/core/lv_setup.h new file mode 100644 index 0000000..5927d5a --- /dev/null +++ b/CYD-Klipper/src/core/lv_setup.h @@ -0,0 +1,16 @@ +#pragma once + +#include "lvgl.h" + +typedef void (*lv_indev_drv_read_cb_t)(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data); + +void set_screen_brightness(); +void set_screen_timer_period(); +void screen_timer_wake(); +void screen_timer_start(); +void screen_timer_stop(); +void set_color_scheme(); +void lv_setup(); +bool is_screen_asleep(); + +lv_style_t * get_default_label_style(); \ No newline at end of file diff --git a/CYD-Klipper/src/core/macros_query.cpp b/CYD-Klipper/src/core/macros_query.cpp index 909f4fc..2ed0c0c 100644 --- a/CYD-Klipper/src/core/macros_query.cpp +++ b/CYD-Klipper/src/core/macros_query.cpp @@ -4,15 +4,16 @@ #include #include "../conf/global_config.h" #include +#include static char* macros[64] = {0}; static int macros_count = 0; -static void on_state_change(void * s, lv_msg_t * m) { - if (printer.state == PRINTER_STATE_ERROR || printer.state == PRINTER_STATE_PAUSED){ - return; - } +static char* power_devices[16] = {0}; +static bool power_device_states[16] = {0}; +static int power_devices_count = 0; +static void _macros_query_internal(){ String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/printer/gcode/help"; HTTPClient client; client.useHTTP10(true); @@ -41,8 +42,68 @@ static void on_state_change(void * s, lv_msg_t * m) { } } +void _power_devices_query_internal(){ + String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/machine/device_power/devices"; + HTTPClient client; + client.useHTTP10(true); + client.setTimeout(500); + client.begin(url.c_str()); + int httpCode = client.GET(); + if (httpCode == 200){ + JsonDocument doc; + deserializeJson(doc, client.getStream()); + auto result = doc["result"]["devices"].as(); + + for (int i = 0; i < power_devices_count; i++){ + free(power_devices[i]); + } + + power_devices_count = 0; + + for (auto i : result){ + const char * device_name = i["device"]; + const char * device_state = i["status"]; + power_devices[power_devices_count] = (char*)malloc(strlen(device_name) + 1); + strcpy(power_devices[power_devices_count], device_name); + power_device_states[power_devices_count] = strcmp(device_state, "on") == 0; + power_devices_count++; + } + } +} + +static void on_state_change(void * s, lv_msg_t * m) { + if (printer.state == PRINTER_STATE_ERROR || printer.state == PRINTER_STATE_PAUSED){ + return; + } + + _macros_query_internal(); + _power_devices_query_internal(); +} + +bool set_power_state(const char* device_name, bool state) { + String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/machine/device_power/device?device=" + urlEncode(device_name) + "&action=" + (state ? "on" : "off"); + HTTPClient client; + client.useHTTP10(true); + client.begin(url.c_str()); + if (client.POST("") != 200) + return false; + + for (int i = 0; i < power_devices_count; i++){ + if (strcmp(power_devices[i], device_name) == 0){ + power_device_states[i] = state; + return true; + } + } + + return true; +} + MACROSQUERY macros_query() { - return {(const char**)macros, macros_count}; + return {(const char**)macros, (unsigned int)macros_count}; +} + +POWERQUERY power_devices_query() { + return {(const char**)power_devices, (const bool*)power_device_states, (unsigned int)power_devices_count}; } void macros_query_setup(){ diff --git a/CYD-Klipper/src/core/macros_query.h b/CYD-Klipper/src/core/macros_query.h index 5fdee3f..6d58c25 100644 --- a/CYD-Klipper/src/core/macros_query.h +++ b/CYD-Klipper/src/core/macros_query.h @@ -5,5 +5,14 @@ typedef struct { uint32_t count; } MACROSQUERY; +typedef struct { + const char** power_devices; + const bool* power_states; + uint32_t count; +} POWERQUERY; + MACROSQUERY macros_query(); -void macros_query_setup(); \ No newline at end of file +POWERQUERY power_devices_query(); +void macros_query_setup(); +bool set_power_state(const char* device_name, bool state); +void _power_devices_query_internal(); \ No newline at end of file diff --git a/CYD-Klipper/src/core/screen_driver.h b/CYD-Klipper/src/core/screen_driver.h index 90f808e..e8f8e1a 100644 --- a/CYD-Klipper/src/core/screen_driver.h +++ b/CYD-Klipper/src/core/screen_driver.h @@ -1,35 +1,7 @@ #pragma once // Adapted from https://github.com/xperiments-in/xtouch/blob/main/src/devices/2.8/screen.h -#ifndef _SCREEN_DRIVER_INIT -#define _SCREEN_DRIVER_INIT - -#define CPU_FREQ_HIGH 240 -#define CPU_FREQ_LOW 80 - -#include -#include - -#define XPT2046_IRQ 36 -#define XPT2046_MOSI 32 -#define XPT2046_MISO 39 -#define XPT2046_CLK 25 -#define XPT2046_CS 33 - -TS_Point touchscreen_point(); void touchscreen_calibrate(bool force = false); -void screen_setBrightness(byte brightness); -void screen_timer_setup(); -void screen_timer_start(); -void screen_timer_stop(); -void screen_timer_period(uint32_t period); -void set_color_scheme(); +void screen_setBrightness(unsigned char brightness); void screen_setup(); -void set_invert_display(); -void screen_timer_wake(); -void set_screen_timer_period(); -void set_screen_brightness(); - -extern TFT_eSPI tft; - -#endif // _SCREEN_DRIVER_INIT \ No newline at end of file +void set_invert_display(); \ No newline at end of file diff --git a/CYD-Klipper/src/main.cpp b/CYD-Klipper/src/main.cpp index a517416..75225d2 100644 --- a/CYD-Klipper/src/main.cpp +++ b/CYD-Klipper/src/main.cpp @@ -6,22 +6,15 @@ #include "core/data_setup.h" #include "ui/main_ui.h" #include "ui/nav_buttons.h" - -static void event_handler(lv_event_t * e){ - lv_event_code_t code = lv_event_get_code(e); - - if(code == LV_EVENT_CLICKED) { - global_config.version = 0; - WriteGlobalConfig(); - ESP.restart(); - } -} +#include +#include "core/lv_setup.h" void setup() { Serial.begin(115200); Serial.println("Hello World"); LoadGlobalConfig(); screen_setup(); + lv_setup(); Serial.println("Screen init done"); wifi_init(); diff --git a/CYD-Klipper/src/ui/ip_setup.cpp b/CYD-Klipper/src/ui/ip_setup.cpp index deb6fda..9ebf367 100644 --- a/CYD-Klipper/src/ui/ip_setup.cpp +++ b/CYD-Klipper/src/ui/ip_setup.cpp @@ -1,15 +1,32 @@ #include "ip_setup.h" #include "../conf/global_config.h" #include "lvgl.h" -#include #include #include "core/data_setup.h" +#include "ui_utils.h" +#include "../core/macros_query.h" +#include "panels/panel.h" bool connect_ok = false; -lv_obj_t * ipEntry; +lv_obj_t * hostEntry; lv_obj_t * portEntry; lv_obj_t * label = NULL; +/* Create a custom keyboard to allow hostnames or ip addresses (a-z, 0 - 9, and -) */ +static const char * kb_map[] = { + "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", LV_SYMBOL_BACKSPACE, "\n", + "q", "w", "e", "r", "t", "y", "u", "i", "o", "p", "\n", + "a", "s", "d", "f", "g", "h", "j", "k", "l", LV_SYMBOL_OK, "\n", + LV_SYMBOL_LEFT, "z", "x", "c", "v", "b", "n", "m", ".", "-", LV_SYMBOL_RIGHT, NULL +}; + +static const lv_btnmatrix_ctrl_t kb_ctrl[] = { + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, LV_KEYBOARD_CTRL_BTN_FLAGS | 6, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, LV_KEYBOARD_CTRL_BTN_FLAGS | 5, + LV_KEYBOARD_CTRL_BTN_FLAGS | 6, 4, 4, 4, 4, 4, 4, 4, 4, 4, LV_KEYBOARD_CTRL_BTN_FLAGS | 6 +}; + void ip_init_inner(); bool verify_ip(){ @@ -44,7 +61,7 @@ static void ta_event_cb(lv_event_t * e) { } else if (code == LV_EVENT_READY) { - strcpy(global_config.klipperHost, lv_textarea_get_text(ipEntry)); + strcpy(global_config.klipperHost, lv_textarea_get_text(hostEntry)); global_config.klipperPort = atoi(lv_textarea_get_text(portEntry)); if (verify_ip()) @@ -58,6 +75,19 @@ static void ta_event_cb(lv_event_t * e) { lv_label_set_text(label, "Failed to connect"); } } + else + { + return; + } + + if (lv_obj_has_flag(ta, LV_OBJ_FLAG_USER_1)) + { + lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_USER_1); + } + else + { + lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_NUMBER); + } } static void reset_btn_event_handler(lv_event_t * e){ @@ -69,47 +99,101 @@ static void reset_btn_event_handler(lv_event_t * e){ } } -void ip_init_inner(){ +static void power_devices_button(lv_event_t * e) { + lv_obj_t * panel = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_style_bg_opa(panel, LV_OPA_COVER, 0); + lv_layout_flex_column(panel); + lv_obj_set_size(panel, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX); + lv_obj_align(panel, LV_ALIGN_TOP_LEFT, 0, CYD_SCREEN_GAP_PX); + + lv_obj_t * button = lv_btn_create(panel); + lv_obj_set_size(button, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(button, destroy_event_user_data, LV_EVENT_CLICKED, panel); + + lv_obj_t * label = lv_label_create_ex(button); + lv_label_set_text(label, LV_SYMBOL_CLOSE " Close"); + lv_obj_center(label); + + macros_panel_add_power_devices_to_panel(panel, power_devices_query()); +} + +void redraw_connect_screen(){ lv_obj_clean(lv_scr_act()); - if (global_config.ipConfigured) { - label = lv_label_create(lv_scr_act()); - lv_label_set_text(label, "Connecting to Klipper"); - lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); + label = lv_label_create_ex(lv_scr_act()); + lv_label_set_text(label, "Connecting to Klipper"); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); - lv_obj_t * resetBtn = lv_btn_create(lv_scr_act()); - lv_obj_add_event_cb(resetBtn, reset_btn_event_handler, LV_EVENT_ALL, NULL); - lv_obj_align(resetBtn, LV_ALIGN_CENTER, 0, 40); + lv_obj_t * button_row = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_size(button_row, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_layout_flex_row(button_row, LV_FLEX_ALIGN_CENTER); + lv_obj_align(button_row, LV_ALIGN_CENTER, 0, CYD_SCREEN_GAP_PX + CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_t * btnLabel = lv_label_create(resetBtn); - lv_label_set_text(btnLabel, "Reset"); - lv_obj_center(btnLabel); - return; + lv_obj_t * reset_btn = lv_btn_create(button_row); + lv_obj_add_event_cb(reset_btn, reset_btn_event_handler, LV_EVENT_CLICKED, NULL); + lv_obj_set_height(reset_btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + lv_obj_t * btn_label = lv_label_create_ex(reset_btn); + lv_label_set_text(btn_label, "Reset"); + lv_obj_center(btn_label); + + if (power_devices_query().count >= 1){ + lv_obj_t * power_devices_btn = lv_btn_create(button_row); + lv_obj_add_event_cb(power_devices_btn, power_devices_button, LV_EVENT_CLICKED, NULL); + lv_obj_set_height(power_devices_btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + btn_label = lv_label_create_ex(power_devices_btn); + lv_label_set_text(btn_label, "Power Devices"); + lv_obj_center(btn_label); } +} - lv_obj_t * keyboard = lv_keyboard_create(lv_scr_act()); - label = lv_label_create(lv_scr_act()); - lv_label_set_text(label, "Enter Klipper IP and Port"); - lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 10 + 2); +void ip_init_inner(){ + if (global_config.ipConfigured) { + redraw_connect_screen(); + return; + } - ipEntry = lv_textarea_create(lv_scr_act()); - lv_textarea_set_one_line(ipEntry, true); - lv_textarea_set_max_length(ipEntry, 63); - lv_textarea_set_text(ipEntry, ""); - lv_obj_align(ipEntry, LV_ALIGN_TOP_LEFT, 10, 40); - lv_obj_add_event_cb(ipEntry, ta_event_cb, LV_EVENT_ALL, keyboard); - lv_obj_set_size(ipEntry, TFT_HEIGHT - 20 - 100, 60); + lv_obj_clean(lv_scr_act()); - portEntry = lv_textarea_create(lv_scr_act()); + lv_obj_t * root = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_size(root, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_layout_flex_column(root); + + lv_obj_t * top_root = lv_create_empty_panel(root); + lv_obj_set_width(top_root, CYD_SCREEN_WIDTH_PX); + lv_layout_flex_column(top_root); + lv_obj_set_flex_grow(top_root, 1); + lv_obj_set_style_pad_all(top_root, CYD_SCREEN_GAP_PX, 0); + + label = lv_label_create_ex(top_root); + lv_label_set_text(label, "Enter Klipper IP/Hostname and Port"); + lv_obj_set_width(label, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); + + lv_obj_t * textbow_row = lv_create_empty_panel(top_root); + lv_obj_set_width(textbow_row, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); + lv_obj_set_flex_grow(textbow_row, 1); + lv_layout_flex_row(textbow_row); + + hostEntry = lv_textarea_create(textbow_row); + lv_textarea_set_one_line(hostEntry, true); + lv_obj_add_flag(hostEntry, LV_OBJ_FLAG_USER_1); + lv_textarea_set_max_length(hostEntry, 63); + lv_textarea_set_text(hostEntry, ""); + lv_obj_set_flex_grow(hostEntry, 3); + + portEntry = lv_textarea_create(textbow_row); lv_textarea_set_one_line(portEntry, true); lv_textarea_set_max_length(portEntry, 5); lv_textarea_set_text(portEntry, "80"); - lv_obj_align(portEntry, LV_ALIGN_TOP_LEFT, TFT_HEIGHT - 20 - 80, 40); + lv_obj_set_flex_grow(portEntry, 1); + + lv_obj_t * keyboard = lv_keyboard_create(root); + lv_keyboard_set_map(keyboard, LV_KEYBOARD_MODE_USER_1, kb_map, kb_ctrl); + lv_obj_add_event_cb(hostEntry, ta_event_cb, LV_EVENT_ALL, keyboard); lv_obj_add_event_cb(portEntry, ta_event_cb, LV_EVENT_ALL, keyboard); - lv_obj_set_size(portEntry, 90, 60); - - lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_NUMBER); - lv_keyboard_set_textarea(keyboard, ipEntry); + lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_USER_1); + lv_keyboard_set_textarea(keyboard, hostEntry); } long last_data_update_ip = -10000; @@ -133,6 +217,10 @@ void ip_init(){ retry_count++; String retry_count_text = "Connecting to Klipper (Try " + String(retry_count + 1) + ")"; lv_label_set_text(label, retry_count_text.c_str()); + + _power_devices_query_internal(); + if (power_devices_query().count >= 1) + redraw_connect_screen(); } } } diff --git a/CYD-Klipper/src/ui/main_ui.cpp b/CYD-Klipper/src/ui/main_ui.cpp index cc37bc1..f6bd563 100644 --- a/CYD-Klipper/src/ui/main_ui.cpp +++ b/CYD-Klipper/src/ui/main_ui.cpp @@ -4,6 +4,10 @@ #include "../core/screen_driver.h" #include "lvgl.h" #include "nav_buttons.h" +#include "ui_utils.h" +#include "panels/panel.h" +#include "../core/macros_query.h" +#include "../core/lv_setup.h" char extruder_temp_buff[20]; char bed_temp_buff[20]; @@ -17,38 +21,75 @@ static void btn_click_firmware_restart(lv_event_t * e){ send_gcode(false, "FIRMWARE_RESTART"); } +void error_ui_macros_open(lv_event_t * e){ + lv_obj_t * panel = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_style_bg_opa(panel, LV_OPA_COVER, 0); + lv_layout_flex_column(panel); + lv_obj_set_size(panel, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX); + lv_obj_align(panel, LV_ALIGN_TOP_LEFT, 0, CYD_SCREEN_GAP_PX); + + lv_obj_t * button = lv_btn_create(panel); + lv_obj_set_size(button, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(button, destroy_event_user_data, LV_EVENT_CLICKED, panel); + + lv_obj_t * label = lv_label_create_ex(button); + lv_label_set_text(label, LV_SYMBOL_CLOSE " Close"); + lv_obj_center(label); + + macros_panel_add_power_devices_to_panel(panel, power_devices_query()); +} + void error_ui(){ lv_obj_clean(lv_scr_act()); + + lv_obj_t * panel = lv_create_empty_panel(lv_scr_act()); + lv_layout_flex_column(panel); + lv_obj_set_size(panel, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0); + lv_obj_set_flex_align(panel, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); lv_obj_t * label; - label = lv_label_create(lv_scr_act()); + label = lv_label_create_ex(panel); lv_label_set_text(label, LV_SYMBOL_WARNING " Printer is not ready"); - lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 10); - label = lv_label_create(lv_scr_act()); + label = lv_label_create_ex(panel); lv_label_set_text(label, printer.state_message); - lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 30); - lv_obj_set_size(label, TFT_HEIGHT - 20, TFT_WIDTH - 30); + lv_obj_set_width(label, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); lv_obj_clear_flag(label, LV_OBJ_FLAG_SCROLLABLE); lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); - lv_obj_t * btn = lv_btn_create(lv_scr_act()); - lv_obj_align(btn, LV_ALIGN_BOTTOM_LEFT, 10, -10); - lv_obj_set_size(btn, TFT_HEIGHT / 2 - 15, 30); + lv_obj_t * button_row = lv_create_empty_panel(panel); + lv_obj_set_size(button_row, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_layout_flex_row(button_row); + + lv_obj_t * btn = lv_btn_create(button_row); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_add_event_cb(btn, btn_click_restart, LV_EVENT_CLICKED, NULL); + lv_obj_set_flex_grow(btn, 1); - label = lv_label_create(btn); + label = lv_label_create_ex(btn); lv_label_set_text(label, "Restart"); lv_obj_center(label); - btn = lv_btn_create(lv_scr_act()); - lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -10, -10); - lv_obj_set_size(btn, TFT_HEIGHT / 2 - 15, 30); + btn = lv_btn_create(button_row); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_add_event_cb(btn, btn_click_firmware_restart, LV_EVENT_CLICKED, NULL); + lv_obj_set_flex_grow(btn, 1); - label = lv_label_create(btn); - lv_label_set_text(label, "Firmware Restart"); + label = lv_label_create_ex(btn); + lv_label_set_text(label, "FW Restart"); lv_obj_center(label); + + if (power_devices_query().count >= 1){ + btn = lv_btn_create(button_row); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, error_ui_macros_open, LV_EVENT_CLICKED, NULL); + lv_obj_set_flex_grow(btn, 1); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, "Devices"); + lv_obj_center(label); + } } void check_if_screen_needs_to_be_disabled(){ @@ -72,7 +113,6 @@ static void on_state_change(void * s, lv_msg_t * m){ } } - void main_ui_setup(){ lv_msg_subscribe(DATA_PRINTER_STATE, on_state_change, NULL); on_state_change(NULL, NULL); diff --git a/CYD-Klipper/src/ui/nav_buttons.cpp b/CYD-Klipper/src/ui/nav_buttons.cpp index e056316..cc9796d 100644 --- a/CYD-Klipper/src/ui/nav_buttons.cpp +++ b/CYD-Klipper/src/ui/nav_buttons.cpp @@ -3,6 +3,7 @@ #include "../core/data_setup.h" #include "nav_buttons.h" #include +#include "ui_utils.h" static lv_style_t nav_button_style; @@ -75,92 +76,50 @@ static void btn_click_macros(lv_event_t * e){ nav_buttons_setup(4); } -void nav_buttons_setup(unsigned char active_panel){ - lv_obj_clean(lv_scr_act()); - lv_obj_clear_flag(lv_scr_act(), LV_OBJ_FLAG_SCROLLABLE); - sprintf(temp_buffer, "%.0f/%.0f", printer.extruder_temp, printer.bed_temp); - sprintf(z_pos_buffer, "Z%.2f", printer.position[2]); - - const int button_width = 40; - const int button_height = 60; - const int icon_text_spacing = 10; - - // Files/Print - lv_obj_t * btn = lv_btn_create(lv_scr_act()); - lv_obj_set_size(btn, button_width, button_height); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, 0, 0); +void create_button(const char* icon, const char* name, lv_event_cb_t button_click, lv_event_cb_t label_update, lv_obj_t * root){ + lv_obj_t* btn = lv_btn_create(root); + lv_obj_set_flex_grow(btn, 1); + lv_obj_set_width(btn, CYD_SCREEN_SIDEBAR_SIZE_PX); lv_obj_add_style(btn, &nav_button_style, 0); - lv_obj_add_event_cb(btn, btn_click_files, LV_EVENT_CLICKED, NULL); + if (button_click != NULL) + lv_obj_add_event_cb(btn, button_click, LV_EVENT_CLICKED, NULL); - lv_obj_t * label = lv_label_create(btn); - lv_label_set_text(label, LV_SYMBOL_COPY); - lv_obj_align(label, LV_ALIGN_CENTER, 0, -1 * icon_text_spacing); - - label = lv_label_create(btn); - lv_label_set_text(label, "Idle"); - lv_obj_align(label, LV_ALIGN_CENTER, 0, icon_text_spacing); - lv_obj_add_style(label, &nav_button_text_style, 0); - lv_obj_add_event_cb(label, update_printer_data_time, LV_EVENT_MSG_RECEIVED, NULL); - lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); - - // Move - btn = lv_btn_create(lv_scr_act()); - lv_obj_set_size(btn, button_width, button_height); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, 0, button_height); - lv_obj_add_style(btn, &nav_button_style, 0); - lv_obj_add_event_cb(btn, btn_click_move, LV_EVENT_CLICKED, NULL); - - label = lv_label_create(btn); - lv_label_set_text(label, LV_SYMBOL_CHARGE); - lv_obj_align(label, LV_ALIGN_CENTER, 0, -1 * icon_text_spacing); + lv_obj_t* label = lv_label_create_ex(btn); + lv_label_set_text(label, icon); + lv_obj_align(label, LV_ALIGN_CENTER, 0, -1 * CYD_SCREEN_GAP_PX); label = lv_label_create(btn); - lv_label_set_text(label, z_pos_buffer); - lv_obj_align(label, LV_ALIGN_CENTER, 0, icon_text_spacing); - lv_obj_add_event_cb(label, update_printer_data_z_pos, LV_EVENT_MSG_RECEIVED, NULL); + lv_label_set_text(label, name); + lv_obj_align(label, LV_ALIGN_CENTER, 0, CYD_SCREEN_GAP_PX); + lv_obj_add_event_cb(label, label_update, LV_EVENT_MSG_RECEIVED, NULL); lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); lv_obj_add_style(label, &nav_button_text_style, 0); +} - // Extrude/Temp - btn = lv_btn_create(lv_scr_act()); - lv_obj_set_size(btn, button_width, button_height); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, 0, button_height * 2); - lv_obj_add_style(btn, &nav_button_style, 0); - lv_obj_add_event_cb(btn, btn_click_extrude, LV_EVENT_CLICKED, NULL); +void nav_buttons_setup(unsigned char active_panel){ + lv_obj_clean(lv_scr_act()); + lv_obj_clear_flag(lv_scr_act(), LV_OBJ_FLAG_SCROLLABLE); - label = lv_label_create(btn); - lv_label_set_text(label, LV_SYMBOL_WARNING); - lv_obj_align(label, LV_ALIGN_CENTER, 0, -1 * icon_text_spacing); + lv_obj_t * root_panel = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_size(root_panel, CYD_SCREEN_SIDEBAR_SIZE_PX, CYD_SCREEN_HEIGHT_PX); + lv_obj_align(root_panel, LV_ALIGN_TOP_LEFT, 0, 0); + lv_layout_flex_column(root_panel, LV_FLEX_ALIGN_START, 0, 0); - label = lv_label_create(btn); - lv_label_set_text(label, temp_buffer); - lv_obj_align(label, LV_ALIGN_CENTER, 0, icon_text_spacing); - lv_obj_add_event_cb(label, update_printer_data_temp, LV_EVENT_MSG_RECEIVED, NULL); - lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); - lv_obj_add_style(label, &nav_button_text_style, 0); + // Files/Print + create_button(LV_SYMBOL_COPY, "Idle", btn_click_files, update_printer_data_time, root_panel); - // Settings - btn = lv_btn_create(lv_scr_act()); - lv_obj_set_size(btn, button_width, button_height); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, 0, button_height * 3); - lv_obj_add_style(btn, &nav_button_style, 0); - lv_obj_add_event_cb(btn, btn_click_macros, LV_EVENT_CLICKED, NULL); + // Move + create_button(printer.state == PRINTER_STATE_PRINTING ? LV_SYMBOL_EDIT : LV_SYMBOL_CHARGE, "Z?", btn_click_move, update_printer_data_z_pos, root_panel); - label = lv_label_create(btn); - lv_label_set_text(label, LV_SYMBOL_GPS); - lv_obj_align(label, LV_ALIGN_CENTER, 0, -1 * icon_text_spacing); + // Extrude/Temp + create_button(LV_SYMBOL_WARNING, "?/?", btn_click_extrude, update_printer_data_temp, root_panel); - label = lv_label_create(btn); - lv_label_set_text(label, "Macro"); - lv_obj_align(label, LV_ALIGN_CENTER, 0, icon_text_spacing); - lv_obj_add_style(label, &nav_button_text_style, 0); + // Macros + create_button(LV_SYMBOL_GPS, "Macro", btn_click_macros, NULL, root_panel); - lv_obj_t * panel = lv_obj_create(lv_scr_act()); - lv_obj_set_size(panel, TFT_HEIGHT - button_width, TFT_WIDTH); + lv_obj_t * panel = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_size(panel, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); lv_obj_align(panel, LV_ALIGN_TOP_RIGHT, 0, 0); - lv_obj_set_style_border_width(panel, 0, 0); - lv_obj_set_style_bg_opa(panel, LV_OPA_TRANSP, 0); - lv_obj_set_style_pad_all(panel, 0, 0); switch (active_panel){ case 0: @@ -179,6 +138,8 @@ void nav_buttons_setup(unsigned char active_panel){ macros_panel_init(panel); break; } + + lv_msg_send(DATA_PRINTER_DATA, &printer); } void nav_style_setup(){ @@ -186,5 +147,5 @@ void nav_style_setup(){ lv_style_set_radius(&nav_button_style, 0); lv_style_init(&nav_button_text_style); - lv_style_set_text_font(&nav_button_text_style, &lv_font_montserrat_10); + lv_style_set_text_font(&nav_button_text_style, &CYD_SCREEN_FONT_SMALL); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/macros_panel.cpp b/CYD-Klipper/src/ui/panels/macros_panel.cpp index 16348fb..84abf46 100644 --- a/CYD-Klipper/src/ui/panels/macros_panel.cpp +++ b/CYD-Klipper/src/ui/panels/macros_panel.cpp @@ -3,15 +3,11 @@ #include "../nav_buttons.h" #include "../../core/data_setup.h" #include "../../core/macros_query.h" +#include "../../conf/global_config.h" +#include "../ui_utils.h" #include -int y_offset_macros = 40; -const int y_element_size = 50; -const int y_seperator_size = 1; -const int y_seperator_x_padding = 50; -const int panel_width = TFT_HEIGHT - 40; -const int y_element_x_padding = 30; -const static lv_point_t line_points[] = { {0, 0}, {panel_width - y_seperator_x_padding, 0} }; +const static lv_point_t line_points[] = { {0, 0}, {(short int)((CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2) * 0.85f), 0} }; static void btn_press(lv_event_t * e){ lv_obj_t * btn = lv_event_get_target(e); @@ -24,58 +20,94 @@ static void btn_goto_settings(lv_event_t * e){ nav_buttons_setup(3); } -void create_macro_widget(const char* macro, lv_obj_t* root_panel){ - lv_obj_t * panel = lv_obj_create(root_panel); - lv_obj_set_style_border_width(panel, 0, 0); - lv_obj_set_style_bg_opa(panel, LV_OPA_TRANSP, 0); - lv_obj_set_style_pad_all(panel, 0, 0); - lv_obj_align(panel, LV_ALIGN_TOP_MID, 0, y_offset_macros); - lv_obj_set_size(panel, panel_width - y_element_x_padding, y_element_size); - - lv_obj_t * line = lv_line_create(panel); - lv_line_set_points(line, line_points, 2); - lv_obj_set_style_line_width(line, y_seperator_size, 0); - lv_obj_set_style_line_color(line, lv_color_hex(0xAAAAAA), 0); - lv_obj_align(line, LV_ALIGN_BOTTOM_MID, 0, 0); - - lv_obj_t * label = lv_label_create(panel); - lv_label_set_text(label, macro); - lv_obj_align(label, LV_ALIGN_LEFT_MID, 0, 0); - lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_width(label, (TFT_HEIGHT - 40) * 0.75f); +void macros_panel_add_macros_to_panel(lv_obj_t * root_panel, MACROSQUERY query){ + for (int i = 0; i < query.count; i++){ + const char* macro = query.macros[i]; + + lv_obj_t * panel = lv_create_empty_panel(root_panel); + lv_layout_flex_row(panel, LV_FLEX_ALIGN_END); + lv_obj_set_size(panel, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - lv_obj_t * btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_RIGHT_MID, 0, 0); - lv_obj_add_event_cb(btn, btn_press, LV_EVENT_CLICKED, (void*)macro); + lv_obj_t * label = lv_label_create_ex(panel); + lv_label_set_text(label, macro); + lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); + lv_obj_set_flex_grow(label, 1); - label = lv_label_create(btn); - lv_label_set_text(label, "Run"); - lv_obj_center(label); + lv_obj_t * btn = lv_btn_create(panel); + lv_obj_add_event_cb(btn, btn_press, LV_EVENT_CLICKED, (void*)macro); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, "Run"); + lv_obj_center(label); + + lv_obj_t * line = lv_line_create(root_panel); + lv_line_set_points(line, line_points, 2); + lv_obj_set_style_line_width(line, 1, 0); + lv_obj_set_style_line_color(line, lv_color_hex(0xAAAAAA), 0); + } +} + +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); + const char* power_device_name = (const char*)lv_event_get_user_data(e); + Serial.printf("Power Device: %s, State: %d -> %d\n", power_device_name, !checked, checked); - y_offset_macros += y_element_size; + set_power_state(power_device_name, checked); } -void macros_panel_init(lv_obj_t* panel) { - y_offset_macros = 40; +void macros_panel_add_power_devices_to_panel(lv_obj_t * root_panel, POWERQUERY query){ + for (int i = 0; i < query.count; i++){ + const char* power_device_name = query.power_devices[i]; + const bool power_device_state = query.power_states[i]; + + lv_obj_t * panel = lv_create_empty_panel(root_panel); + lv_layout_flex_row(panel, LV_FLEX_ALIGN_END); + lv_obj_set_size(panel, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_t * label = lv_label_create_ex(panel); + lv_label_set_text(label, power_device_name); + lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); + lv_obj_set_flex_grow(label, 1); + + lv_obj_t * toggle = lv_switch_create(panel); + lv_obj_add_event_cb(toggle, power_device_toggle, LV_EVENT_VALUE_CHANGED, (void*)power_device_name); + lv_obj_set_size(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + if (power_device_state) + lv_obj_add_state(toggle, LV_STATE_CHECKED); + + lv_obj_t * line = lv_line_create(root_panel); + lv_line_set_points(line, line_points, 2); + lv_obj_set_style_line_width(line, 1, 0); + lv_obj_set_style_line_color(line, lv_color_hex(0xAAAAAA), 0); + } +} + +void macros_panel_init(lv_obj_t* panel) { lv_obj_t * btn = lv_btn_create(panel); lv_obj_add_event_cb(btn, btn_goto_settings, LV_EVENT_CLICKED, NULL); - lv_obj_set_size(btn, TFT_HEIGHT - 40 - 20, 30); - lv_obj_align(btn, LV_ALIGN_TOP_MID, 0, 5); + lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(btn, LV_ALIGN_TOP_MID, 0, CYD_SCREEN_GAP_PX); - lv_obj_t * label = lv_label_create(btn); + lv_obj_t * label = lv_label_create_ex(btn); lv_label_set_text(label, LV_SYMBOL_SETTINGS " Screen Settings"); lv_obj_center(label); MACROSQUERY query = macros_query(); - if (query.count == 0){ - label = lv_label_create(panel); + POWERQUERY power = power_devices_query(); + if (query.count == 0 && power.count == 0){ + label = lv_label_create_ex(panel); lv_label_set_text(label, "No macros found.\nMacros with the description\n\"CYD_SCREEN_MACRO\"\nwill show up here."); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); return; } - for (int i = 0; i < query.count; i++){ - create_macro_widget(query.macros[i], panel); - } + lv_obj_t * root_panel = lv_create_empty_panel(panel); + lv_obj_set_size(root_panel, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_MIN_BUTTON_HEIGHT_PX - CYD_SCREEN_GAP_PX * 2); + lv_obj_align(root_panel, LV_ALIGN_TOP_MID, 0, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX + CYD_SCREEN_GAP_PX * 2); + lv_layout_flex_column(root_panel); + + macros_panel_add_power_devices_to_panel(root_panel, power); + macros_panel_add_macros_to_panel(root_panel, query); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/move_panel.cpp b/CYD-Klipper/src/ui/panels/move_panel.cpp index fcde141..8afa9e0 100644 --- a/CYD-Klipper/src/ui/panels/move_panel.cpp +++ b/CYD-Klipper/src/ui/panels/move_panel.cpp @@ -1,7 +1,10 @@ #include "lvgl.h" #include "panel.h" #include "../../core/data_setup.h" -#include +#include "../ui_utils.h" +#include + +static bool last_homing_state = false; static void move_printer(const char* axis, float amount) { if (!printer.homed_axis || printer.state == PRINTER_STATE_PRINTING) @@ -16,9 +19,7 @@ static void move_printer(const char* axis, float amount) { send_gcode(true, "G91"); } - const char * space = "%20"; - - sprintf(gcode, "G1%s%s%s%.1f%sF6000", space, axis, extra, amount, space); + sprintf(gcode, "G1 %s%s%.1f F6000", axis, extra, amount); send_gcode(true, gcode); if (absolute_coords) { @@ -72,7 +73,7 @@ lv_event_cb_t button_callbacks[] = {x_line_button_press, y_line_button_press, z_ lv_event_cb_t position_callbacks[] = {x_pos_update, y_pos_update, z_pos_update}; const float xy_offsets[] = {-100, -10, -1, 1, 10, 100}; -const float z_offsets[] = {-25, -1, -0.1, 0.1, 1, 25}; +const float z_offsets[] = {-10, -1, -0.1, 0.1, 1, 10}; const float* offsets[] = { xy_offsets, xy_offsets, @@ -80,7 +81,7 @@ const float* offsets[] = { }; const char* xy_offset_labels[] = {"-100", "-10", "-1", "+1", "+10", "+100"}; -const char* z_offset_labels[] = {"-25", "-1", "-0.1", "+0.1", "+1", "+25"}; +const char* z_offset_labels[] = {"-10", "-1", "-0.1", "+0.1", "+1", "+10"}; const char** offset_labels[] = { xy_offset_labels, @@ -102,108 +103,103 @@ static void disable_steppers_click(lv_event_t * e) { send_gcode(true, "M18"); } -static void stepper_state_update(lv_event_t * e){ - lv_obj_t * label = lv_event_get_target(e); - lv_label_set_text(label, printer.homed_axis ? LV_SYMBOL_HOME " Steppers locked" : LV_SYMBOL_EYE_CLOSE " Steppers unlocked"); -} +inline void root_panel_steppers_locked(lv_obj_t * root_panel){ + const auto width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2; -void move_panel_init(lv_obj_t* panel){ - lv_obj_clear_flag(panel, LV_OBJ_FLAG_SCROLLABLE); - const int button_size = 40; - const int button_size_vertical = 40; - const int button_padding = 2; - const int x_offset = 15; - int y_pos = 75; - - auto panel_width = TFT_HEIGHT - 40; - - lv_obj_t * home_button = lv_btn_create(panel); - lv_obj_align(home_button, LV_ALIGN_TOP_LEFT, 10, 5); - lv_obj_add_event_cb(home_button, home_button_click, LV_EVENT_CLICKED, NULL); - lv_obj_set_size(home_button, panel_width / 2 - 15, 30); - - lv_obj_t * home_label = lv_label_create(home_button); - lv_label_set_text(home_label, LV_SYMBOL_HOME "Home Axis"); - lv_obj_center(home_label); - - lv_obj_t * disable_steppers_button = lv_btn_create(panel); - lv_obj_align(disable_steppers_button, LV_ALIGN_TOP_RIGHT, -10, 5); - lv_obj_add_event_cb(disable_steppers_button, disable_steppers_click, LV_EVENT_CLICKED, NULL); - lv_obj_set_size(disable_steppers_button, panel_width / 2 - 15, 30); - - lv_obj_t * disable_steppers_label = lv_label_create(disable_steppers_button); - lv_label_set_text(disable_steppers_label, LV_SYMBOL_EYE_CLOSE "Disable Step"); - lv_obj_center(disable_steppers_label); - - lv_obj_t * label = lv_label_create(panel); - lv_label_set_text(label, "???"); - lv_obj_align(label, LV_ALIGN_TOP_MID, 0, 40); - lv_obj_add_event_cb(label, stepper_state_update, LV_EVENT_MSG_RECEIVED, NULL); - lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); - - for (int i = 0; i < 3; i++) { - lv_obj_t * btn = lv_btn_create(panel); - lv_obj_set_size(btn, button_size, button_size_vertical); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x_offset, y_pos); - lv_obj_add_event_cb(btn, button_callbacks[i], LV_EVENT_CLICKED, (void*)(offsets[i])); - - lv_obj_t * label = lv_label_create(btn); - lv_label_set_text(label, offset_labels[i][0]); - lv_obj_center(label); - - btn = lv_btn_create(panel); - lv_obj_set_size(btn, button_size, button_size_vertical); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x_offset + (button_size + button_padding) * 1, y_pos); - lv_obj_add_event_cb(btn, button_callbacks[i], LV_EVENT_CLICKED, (void*)(offsets[i] + 1)); - - label = lv_label_create(btn); - lv_label_set_text(label, offset_labels[i][1]); - lv_obj_center(label); - - btn = lv_btn_create(panel); - lv_obj_set_size(btn, button_size, button_size_vertical); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x_offset + (button_size + button_padding) * 2, y_pos); - lv_obj_add_event_cb(btn, button_callbacks[i], LV_EVENT_CLICKED, (void*)(offsets[i] + 2)); - - label = lv_label_create(btn); - lv_label_set_text(label, offset_labels[i][2]); - lv_obj_center(label); - - btn = lv_btn_create(panel); - lv_obj_set_size(btn, button_size, button_size_vertical); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x_offset + (button_size + button_padding) * 3, y_pos); - lv_obj_add_event_cb(btn, button_callbacks[i], LV_EVENT_CLICKED, (void*)(offsets[i] + 3)); - - label = lv_label_create(btn); - lv_label_set_text(label, offset_labels[i][3]); - lv_obj_center(label); - - btn = lv_btn_create(panel); - lv_obj_set_size(btn, button_size, button_size_vertical); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x_offset + (button_size + button_padding) * 4, y_pos); - lv_obj_add_event_cb(btn, button_callbacks[i], LV_EVENT_CLICKED, (void*)(offsets[i] + 4)); - - label = lv_label_create(btn); - lv_label_set_text(label, offset_labels[i][4]); - lv_obj_center(label); - - btn = lv_btn_create(panel); - lv_obj_set_size(btn, button_size, button_size_vertical); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x_offset + (button_size + button_padding) * 5, y_pos); - lv_obj_add_event_cb(btn, button_callbacks[i], LV_EVENT_CLICKED, (void*)(offsets[i] + 5)); - - label = lv_label_create(btn); - lv_label_set_text(label, offset_labels[i][5]); - lv_obj_center(label); - - label = lv_label_create(panel); + lv_obj_t * panel = lv_create_empty_panel(root_panel); + lv_obj_set_size(panel, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0); + lv_layout_flex_column(panel, LV_FLEX_ALIGN_SPACE_BETWEEN, 0, 0); + + lv_obj_t * home_button_row = lv_create_empty_panel(panel); + lv_obj_set_size(home_button_row, width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_layout_flex_row(home_button_row); + + lv_obj_t * btn = lv_btn_create(home_button_row); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, home_button_click, LV_EVENT_CLICKED, NULL); + lv_obj_set_flex_grow(btn, 1); + + lv_obj_t * label = lv_label_create_ex(btn); + lv_label_set_text(label, LV_SYMBOL_HOME "Home Axis"); + lv_obj_center(label); + + btn = lv_btn_create(home_button_row); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, disable_steppers_click, LV_EVENT_CLICKED, NULL); + lv_obj_set_flex_grow(btn, 1); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, LV_SYMBOL_EYE_CLOSE " Disable Step"); + lv_obj_center(label); + + for (int row = 0; row < 3; row++) { + label = lv_label_create_ex(panel); lv_label_set_text(label, "???"); - lv_obj_align(label, LV_ALIGN_TOP_LEFT, x_offset, y_pos - 15);\ - lv_obj_add_event_cb(label, position_callbacks[i], LV_EVENT_MSG_RECEIVED, NULL); + lv_obj_set_width(label, width); + lv_obj_add_event_cb(label, position_callbacks[row], LV_EVENT_MSG_RECEIVED, NULL); lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); - y_pos += 60; + lv_obj_t * row_panel = lv_create_empty_panel(panel); + lv_obj_set_size(row_panel, width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_layout_flex_row(row_panel); + + for (int col = 0; col < 6; col++) + { + btn = lv_btn_create(row_panel); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, button_callbacks[row], LV_EVENT_CLICKED, (void*)(offsets[row] + col)); + lv_obj_set_flex_grow(btn, 1); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, offset_labels[row][col]); + lv_obj_center(label); + } } - lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +inline void root_panel_steppers_unlocked(lv_obj_t * root_panel){ + lv_obj_t * panel = lv_create_empty_panel(root_panel); + lv_obj_set_size(panel, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0); + lv_layout_flex_column(panel, LV_FLEX_ALIGN_CENTER); + + lv_obj_t * label = lv_label_create_ex(panel); + lv_label_set_text(label, LV_SYMBOL_EYE_CLOSE " Steppers unlocked"); + + lv_obj_t * btn = lv_btn_create(panel); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, home_button_click, LV_EVENT_CLICKED, NULL); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, LV_SYMBOL_HOME "Home Axis"); + lv_obj_center(label); +} + +static void root_panel_state_update(lv_event_t * e){ + if (last_homing_state == printer.homed_axis) + return; + + lv_obj_t * panel = lv_event_get_target(e); + last_homing_state = printer.homed_axis; + + lv_obj_clean(panel); + + if (printer.homed_axis) + root_panel_steppers_locked(panel); + else + root_panel_steppers_unlocked(panel); +} + +void move_panel_init(lv_obj_t* panel){ + if (printer.state == PRINTER_STATE_PRINTING){ + stats_panel_init(panel); + return; + } + + last_homing_state = !printer.homed_axis; + + lv_obj_add_event_cb(panel, root_panel_state_update, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subsribe_obj(DATA_PRINTER_DATA, panel, NULL); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/panel.h b/CYD-Klipper/src/ui/panels/panel.h index ac65776..d69910a 100644 --- a/CYD-Klipper/src/ui/panels/panel.h +++ b/CYD-Klipper/src/ui/panels/panel.h @@ -1,4 +1,5 @@ #include "lvgl.h" +#include "../../core/macros_query.h" #define SIZEOF(arr) (sizeof(arr) / sizeof(*arr)) @@ -7,4 +8,6 @@ void temp_panel_init(lv_obj_t* panel); void print_panel_init(lv_obj_t* panel); void move_panel_init(lv_obj_t* panel); void progress_panel_init(lv_obj_t* panel); -void macros_panel_init(lv_obj_t* panel); \ No newline at end of file +void macros_panel_init(lv_obj_t* panel); +void stats_panel_init(lv_obj_t* panel); +void macros_panel_add_power_devices_to_panel(lv_obj_t * panel, POWERQUERY query); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/print_panel.cpp b/CYD-Klipper/src/ui/panels/print_panel.cpp index e0a1cd6..d9aaaa1 100644 --- a/CYD-Klipper/src/ui/panels/print_panel.cpp +++ b/CYD-Klipper/src/ui/panels/print_panel.cpp @@ -5,6 +5,8 @@ #include "../../conf/global_config.h" #include #include +#include "../ui_utils.h" +#include "../../core/lv_setup.h" FILESYSTEM_FILE* selected_file = NULL; @@ -39,44 +41,42 @@ static void btn_print_file(lv_event_t * e){ Serial.printf("Print start: HTTP %d\n", httpCode); } -static void btn_print_back(lv_event_t * e){ - lv_obj_t * panel = (lv_obj_t*)lv_event_get_user_data(e); - lv_obj_del(panel); -} - static void btn_print_file_verify(lv_event_t * e){ + const auto button_size_mult = 1.3f; + lv_obj_t * btn = lv_event_get_target(e); selected_file = (FILESYSTEM_FILE*)lv_event_get_user_data(e); lv_obj_t * panel = lv_obj_create(lv_scr_act()); - lv_obj_set_size(panel, TFT_HEIGHT - 40, TFT_WIDTH - 30); + lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX * 2, 0); + lv_obj_set_size(panel, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 4, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX * 3); lv_obj_align(panel, LV_ALIGN_CENTER, 0, 0); - lv_obj_t * label = lv_label_create(panel); + lv_obj_t * label = lv_label_create_ex(panel); lv_label_set_text(label, "Print File"); lv_obj_align(label, LV_ALIGN_TOP_LEFT, 0, 0); - label = lv_label_create(panel); + label = lv_label_create_ex(panel); lv_label_set_text(label, selected_file->name); lv_obj_align(label, LV_ALIGN_CENTER, 0, -20); - lv_obj_set_width(label, TFT_HEIGHT - 90); + lv_obj_set_width(label, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 10); lv_label_set_long_mode(label, LV_LABEL_LONG_WRAP); btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_LEFT, 10, -10); - lv_obj_set_size(btn, 40, 40); - lv_obj_add_event_cb(btn, btn_print_back, LV_EVENT_CLICKED, panel); + lv_obj_align(btn, LV_ALIGN_BOTTOM_LEFT, 0, 0); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * button_size_mult, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX * button_size_mult); + lv_obj_add_event_cb(btn, destroy_event_user_data, LV_EVENT_CLICKED, panel); - label = lv_label_create(btn); + label = lv_label_create_ex(btn); lv_label_set_text(label, LV_SYMBOL_CLOSE); lv_obj_center(label); btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -10, -10); - lv_obj_set_size(btn, 40, 40); + lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, 0, 0); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * button_size_mult, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX * button_size_mult); lv_obj_add_event_cb(btn, btn_print_file, LV_EVENT_CLICKED, panel); - label = lv_label_create(btn); + label = lv_label_create_ex(btn); lv_label_set_text(label, LV_SYMBOL_OK); lv_obj_center(label); } @@ -87,18 +87,19 @@ void print_panel_init(lv_obj_t* panel){ return; } - auto panel_width = TFT_HEIGHT - 40; - auto panel_height_margin = TFT_WIDTH - 10; - auto panel_width_margin = panel_width - 10; - lv_obj_t * list = lv_list_create(panel); - lv_obj_set_size(list, panel_width_margin, panel_height_margin); + lv_obj_set_style_radius(list, 0, 0); + lv_obj_set_style_border_width(list, 0, 0); + lv_obj_set_style_bg_opa(list, LV_OPA_TRANSP, 0); + lv_obj_set_size(list, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); lv_obj_align(list, LV_ALIGN_CENTER, 0, 0); FILESYSTEM_FILE* files = get_files(25); int count = 0; while (files != NULL && files->name != NULL && count <= 20){ lv_obj_t * btn = lv_list_add_btn(list, LV_SYMBOL_FILE, files->name); + lv_obj_add_style(btn, get_default_label_style(), 0); + lv_obj_set_style_bg_opa(btn, LV_OPA_TRANSP, 0); lv_obj_add_event_cb(btn, btn_print_file_verify, LV_EVENT_CLICKED, (void*)files); files += 1; @@ -107,7 +108,7 @@ void print_panel_init(lv_obj_t* panel){ if (count <= 0){ lv_obj_del(list); - lv_obj_t * label = lv_label_create(panel); + lv_obj_t * label = lv_label_create_ex(panel); lv_label_set_text(label, "Failed to read files."); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); } diff --git a/CYD-Klipper/src/ui/panels/progress_panel.cpp b/CYD-Klipper/src/ui/panels/progress_panel.cpp index adfe229..d4d3edc 100644 --- a/CYD-Klipper/src/ui/panels/progress_panel.cpp +++ b/CYD-Klipper/src/ui/panels/progress_panel.cpp @@ -1,6 +1,7 @@ #include "panel.h" #include "../../core/data_setup.h" #include +#include "../ui_utils.h" char time_buffer[12]; @@ -47,76 +48,80 @@ static void btn_click_resume(lv_event_t * e){ } void progress_panel_init(lv_obj_t* panel){ - auto panel_width = TFT_HEIGHT - 40; - auto panel_width_margin = panel_width - 30; + auto panel_width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 3; + const auto button_size_mult = 1.3f; + + lv_obj_t * center_panel = lv_create_empty_panel(panel); + lv_obj_align(center_panel, LV_ALIGN_CENTER, 0, 0); + lv_obj_set_size(center_panel, panel_width, LV_SIZE_CONTENT); + lv_layout_flex_column(center_panel); // Filename - lv_obj_t * label = lv_label_create(panel); + lv_obj_t * label = lv_label_create_ex(center_panel); lv_label_set_text(label, printer.print_filename); - lv_obj_align(label, LV_ALIGN_CENTER, 0, -40); lv_label_set_long_mode(label, LV_LABEL_LONG_SCROLL_CIRCULAR); - lv_obj_set_width(label, panel_width_margin); + lv_obj_set_width(label, panel_width); // Progress Bar - lv_obj_t * bar = lv_bar_create(panel); - lv_obj_align(bar, LV_ALIGN_CENTER, 0, 0); - lv_obj_set_size(bar, panel_width_margin, 20); + lv_obj_t * bar = lv_bar_create(center_panel); + lv_obj_set_size(bar, panel_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX * 0.75f); lv_obj_add_event_cb(bar, progress_bar_update, LV_EVENT_MSG_RECEIVED, NULL); lv_msg_subsribe_obj(DATA_PRINTER_DATA, bar, NULL); + // Time + lv_obj_t * time_est_panel = lv_create_empty_panel(center_panel); + lv_obj_set_size(time_est_panel, panel_width, LV_SIZE_CONTENT); + // Elapsed Time - label = lv_label_create(panel); + label = lv_label_create_ex(time_est_panel); lv_label_set_text(label, "???"); - lv_obj_align(label, LV_ALIGN_LEFT_MID, 10, 20); + lv_obj_align(label, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_add_event_cb(label, update_printer_data_elapsed_time, LV_EVENT_MSG_RECEIVED, NULL); lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); // Remaining Time - label = lv_label_create(panel); + label = lv_label_create_ex(time_est_panel); lv_label_set_text(label, "???"); - lv_obj_align(label, LV_ALIGN_RIGHT_MID, -10, 20); + lv_obj_align(label, LV_ALIGN_RIGHT_MID, 0, 0); lv_obj_add_event_cb(label, update_printer_data_remaining_time, LV_EVENT_MSG_RECEIVED, NULL); lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); // Percentage - label = lv_label_create(panel); + label = lv_label_create_ex(time_est_panel); lv_label_set_text(label, "???"); - lv_obj_align(label, LV_ALIGN_CENTER, 0, 20); + lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); lv_obj_add_event_cb(label, update_printer_data_percentage, LV_EVENT_MSG_RECEIVED, NULL); lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); // Stop Button lv_obj_t * btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -10, -10); - lv_obj_set_size(btn, 40, 40); + lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -1 * CYD_SCREEN_GAP_PX, -1 * CYD_SCREEN_GAP_PX); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * button_size_mult, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX * button_size_mult); lv_obj_add_event_cb(btn, btn_click_stop, LV_EVENT_CLICKED, NULL); - label = lv_label_create(btn); + label = lv_label_create_ex(btn); lv_label_set_text(label, LV_SYMBOL_STOP); lv_obj_center(label); // Resume Button if (printer.state == PRINTER_STATE_PAUSED){ btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -60, -10); - lv_obj_set_size(btn, 40, 40); lv_obj_add_event_cb(btn, btn_click_resume, LV_EVENT_CLICKED, NULL); - label = lv_label_create(btn); + label = lv_label_create_ex(btn); lv_label_set_text(label, LV_SYMBOL_PLAY); lv_obj_center(label); } // Pause Button else { btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -60, -10); - lv_obj_set_size(btn, 40, 40); lv_obj_add_event_cb(btn, btn_click_pause, LV_EVENT_CLICKED, NULL); - label = lv_label_create(btn); + label = lv_label_create_ex(btn); lv_label_set_text(label, LV_SYMBOL_PAUSE); lv_obj_center(label); } - lv_msg_send(DATA_PRINTER_DATA, &printer); + lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -2 * CYD_SCREEN_GAP_PX - CYD_SCREEN_MIN_BUTTON_WIDTH_PX * button_size_mult, -1 * CYD_SCREEN_GAP_PX); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * button_size_mult, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX * button_size_mult); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/settings_panel.cpp b/CYD-Klipper/src/ui/panels/settings_panel.cpp index c7404f3..1486ff1 100644 --- a/CYD-Klipper/src/ui/panels/settings_panel.cpp +++ b/CYD-Klipper/src/ui/panels/settings_panel.cpp @@ -3,6 +3,13 @@ #include "../../core/screen_driver.h" #include "../../conf/global_config.h" #include "../main_ui.h" +#include "../ui_utils.h" +#include +#include "../../core/lv_setup.h" + +#ifndef REPO_VERSION + #define REPO_VERSION "Unknown" +#endif // REPO_VERSION static void invert_color_switch(lv_event_t * e){ auto state = lv_obj_get_state(lv_event_get_target(e)); @@ -80,59 +87,54 @@ static void on_during_print_switch(lv_event_t* e){ WriteGlobalConfig(); } -int y_offset = 0; -const int y_element_size = 50; -const int y_seperator_size = 1; -const int y_seperator_x_padding = 50; -const int panel_width = TFT_HEIGHT - 40; -const int y_element_x_padding = 30; -const static lv_point_t line_points[] = { {0, 0}, {panel_width - y_seperator_x_padding, 0} }; - -void create_settings_widget(const char* label_text, lv_obj_t* object, lv_obj_t* root_panel){ - lv_obj_t * panel = lv_obj_create(root_panel); - lv_obj_set_style_border_width(panel, 0, 0); - lv_obj_set_style_bg_opa(panel, LV_OPA_TRANSP, 0); - lv_obj_set_style_pad_all(panel, 0, 0); - lv_obj_align(panel, LV_ALIGN_TOP_MID, 0, y_offset); - lv_obj_set_size(panel, panel_width - y_element_x_padding, y_element_size); - - lv_obj_t * line = lv_line_create(panel); - lv_line_set_points(line, line_points, 2); - lv_obj_set_style_line_width(line, y_seperator_size, 0); - lv_obj_set_style_line_color(line, lv_color_hex(0xAAAAAA), 0); - lv_obj_align(line, LV_ALIGN_BOTTOM_MID, 0, 0); +const static lv_point_t line_points[] = { {0, 0}, {(short int)((CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2) * 0.85f), 0} }; - lv_obj_t * label = lv_label_create(panel); +void create_settings_widget(const char* label_text, lv_obj_t* object, lv_obj_t* root_panel, bool set_height = true){ + lv_obj_t * panel = lv_create_empty_panel(root_panel); + lv_obj_set_size(panel, CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + lv_obj_t * label = lv_label_create_ex(panel); lv_label_set_text(label, label_text); lv_obj_align(label, LV_ALIGN_LEFT_MID, 0, 0); lv_obj_set_parent(object, panel); lv_obj_align(object, LV_ALIGN_RIGHT_MID, 0, 0); - y_offset += y_element_size; + + if (set_height) + lv_obj_set_height(object, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + lv_obj_t * line = lv_line_create(root_panel); + lv_line_set_points(line, line_points, 2); + lv_obj_set_style_line_width(line, 1, 0); + lv_obj_set_style_line_color(line, lv_color_hex(0xAAAAAA), 0); } void settings_panel_init(lv_obj_t* panel){ - y_offset = 0; + lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0); + lv_layout_flex_column(panel); lv_obj_t * btn = lv_btn_create(panel); lv_obj_add_event_cb(btn, reset_wifi_click, LV_EVENT_CLICKED, NULL); - lv_obj_t * label = lv_label_create(btn); + lv_obj_t * label = lv_label_create_ex(btn); lv_label_set_text(label, "Restart"); lv_obj_center(label); create_settings_widget("Configure WiFi", btn, panel); +#ifndef CYD_SCREEN_DISABLE_TOUCH_CALIBRATION btn = lv_btn_create(panel); lv_obj_add_event_cb(btn, reset_calibration_click, LV_EVENT_CLICKED, NULL); - label = lv_label_create(btn); + label = lv_label_create_ex(btn); lv_label_set_text(label, "Restart"); lv_obj_center(label); create_settings_widget("Calibrate Touch", btn, panel); +#endif // CYD_SCREEN_DISABLE_TOUCH_CALIBRATION lv_obj_t * toggle = lv_switch_create(panel); + lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2); lv_obj_add_event_cb(toggle, invert_color_switch, LV_EVENT_VALUE_CHANGED, NULL); if (global_config.invertColors) @@ -142,6 +144,7 @@ void settings_panel_init(lv_obj_t* panel){ toggle = lv_switch_create(panel); + lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2); lv_obj_add_event_cb(toggle, light_mode_switch, LV_EVENT_VALUE_CHANGED, NULL); if (global_config.lightMode) @@ -152,12 +155,14 @@ void settings_panel_init(lv_obj_t* panel){ lv_obj_t * dropdown = lv_dropdown_create(panel); lv_dropdown_set_options(dropdown, "Blue\nGreen\nGrey\nYellow\nOrange\nRed\nPurple"); lv_dropdown_set_selected(dropdown, global_config.color_scheme); + lv_obj_add_style(dropdown, get_default_label_style(), 0); lv_obj_add_event_cb(dropdown, theme_dropdown, LV_EVENT_VALUE_CHANGED, NULL); create_settings_widget("Theme", dropdown, panel); dropdown = lv_dropdown_create(panel); lv_dropdown_set_options(dropdown, brightness_options); + lv_obj_add_style(dropdown, get_default_label_style(), 0); lv_obj_add_event_cb(dropdown, brightness_dropdown, LV_EVENT_VALUE_CHANGED, NULL); for (int i = 0; i < SIZEOF(brightness_options_values); i++){ @@ -169,8 +174,10 @@ void settings_panel_init(lv_obj_t* panel){ create_settings_widget("Brightness", dropdown, panel); +#ifndef CYD_SCREEN_DISABLE_TIMEOUT dropdown = lv_dropdown_create(panel); lv_dropdown_set_options(dropdown, wake_timeout_options); + lv_obj_add_style(dropdown, get_default_label_style(), 0); lv_obj_add_event_cb(dropdown, wake_timeout_dropdown, LV_EVENT_VALUE_CHANGED, NULL); for (int i = 0; i < SIZEOF(wake_timeout_options_values); i++){ @@ -181,8 +188,10 @@ void settings_panel_init(lv_obj_t* panel){ } create_settings_widget("Wake Timeout", dropdown, panel); +#endif toggle = lv_switch_create(panel); + lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2); lv_obj_add_event_cb(toggle, rotate_screen_switch, LV_EVENT_VALUE_CHANGED, NULL); if (global_config.rotateScreen) @@ -190,11 +199,19 @@ void settings_panel_init(lv_obj_t* panel){ create_settings_widget("Rotate Screen", toggle, panel); +#ifndef CYD_SCREEN_DISABLE_TIMEOUT toggle = lv_switch_create(panel); + lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2); lv_obj_add_event_cb(toggle, on_during_print_switch, LV_EVENT_VALUE_CHANGED, NULL); if (global_config.onDuringPrint) lv_obj_add_state(toggle, LV_STATE_CHECKED); create_settings_widget("Screen On During Print", toggle, panel); +#endif + + label = lv_label_create_ex(panel); + lv_label_set_text(label, REPO_VERSION " "); + + create_settings_widget("Version", label, panel, false); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/stats_panel.cpp b/CYD-Klipper/src/ui/panels/stats_panel.cpp new file mode 100644 index 0000000..f28c03d --- /dev/null +++ b/CYD-Klipper/src/ui/panels/stats_panel.cpp @@ -0,0 +1,228 @@ +#include "panel.h" +#include "../ui_utils.h" +#include "../../core/data_setup.h" +#include +#include + +static void set_fan_speed_text(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + char data[64]; + sprintf(data, "Fan: %.0f%%", printer.fan_speed * 100); + lv_label_set_text(label, data); +} + +static void set_fan_speed(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + char gcode[64]; + sprintf(gcode, "M106 S%d", speed); + send_gcode(true, gcode); +} + +const char* fan_speeds[] = { "0%", "15%", "25%", "35%" }; +const int fan_speeds_values[] = { 0, 38, 64, 90 }; + +const char* fan_speeds_2[] = { "50%", "75%", "100%"}; +const int fan_speeds_values_2[] = { 128, 192, 255 }; + +lv_button_column_t fan_speed_columns[] = { + { set_fan_speed, fan_speeds, (const void**)fan_speeds_values, 4}, + { set_fan_speed, fan_speeds_2, (const void**)fan_speeds_values_2, 3} +}; + +static void set_zoffset_text(lv_event_t * e) { + lv_obj_t * label = lv_event_get_target(e); + char data[64]; + sprintf(data, "Z Offset: %.03f", printer.gcode_offset[2]); + lv_label_set_text(label, data); +} + +static void set_zoffset(lv_event_t * e){ + char* offset = (char*)lv_event_get_user_data(e); + char gcode[64]; + sprintf(gcode, "SET_GCODE_OFFSET Z_ADJUST=%s", offset); + send_gcode(true, gcode); +} + +const char* zoffsets[] = { "-0.005", "-0.01", "-0.025", "-0.05" }; +const char* zoffsets_2[] = { "+0.005", "+0.01", "+0.025", "+0.05" }; + +lv_button_column_t zoffset_columns[] = { + { set_zoffset, zoffsets, (const void**)zoffsets, 4}, + { set_zoffset, zoffsets_2, (const void**)zoffsets_2, 4} +}; + +static void set_speed_mult_text(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char data[64]; + sprintf(data, "Speed: %.0f%%", printer.speed_mult * 100); + lv_label_set_text(label, data); +} + +static void set_speed_mult(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + char gcode[64]; + sprintf(gcode, "M220 S%d", speed); + send_gcode(true, gcode); +} + +static void set_speed_mult_offset(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + float result = printer.speed_mult * 100 + speed; + printer.speed_mult = result / 100; + char gcode[64]; + sprintf(gcode, "M220 S%.0f", result); + send_gcode(true, gcode); +} + +const char* speed_presets[] = { "50%", "100%", "150%", "200%" }; +const int speed_presets_values[] = { 50, 100, 150, 200 }; +const char* speed_presets_minus[] = { "-1%", "-5%", "-10%", "-25%" }; +const int speed_presets_minus_values[] = { -1, -5, -10, -25 }; +const char* speed_presets_plus[] = { "+1%", "+5%", "+10%", "+25%" }; +const int speed_presets_plus_values[] = { 1, 5, 10, 25 }; + +lv_button_column_t speed_mult_columns[] = { + { set_speed_mult, speed_presets, (const void**)speed_presets_values, 4}, + { set_speed_mult_offset, speed_presets_minus, (const void**)speed_presets_minus_values, 4}, + { set_speed_mult_offset, speed_presets_plus, (const void**)speed_presets_plus_values, 4} +}; + +static void set_extrude_mult_text(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char data[64]; + sprintf(data, "Flow: %.0f%%", printer.extrude_mult * 100); + lv_label_set_text(label, data); +} + +static void set_extrude_mult(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + char gcode[64]; + sprintf(gcode, "M221 S%d", speed); + send_gcode(true, gcode); +} + +static void set_extrude_mult_offset(lv_event_t * e){ + int speed = (int)lv_event_get_user_data(e); + float result = printer.extrude_mult * 100 + speed; + printer.extrude_mult = result / 100; + char gcode[64]; + sprintf(gcode, "M221 S%.0f", result); + send_gcode(true, gcode); +} + +const char* extrude_presets[] = { "95%", "100%", "105%", "110%" }; +const int extrude_presets_values[] = { 95, 100, 105, 110 }; +const char* extrude_offset[] = { "+5%", "+1%", "-1%", "-5%" }; +const int extrude_offset_values[] = { 5, 1, -1, -5 }; + +lv_button_column_t extrude_mult_columns[] = { + { set_extrude_mult, extrude_presets, (const void**)extrude_presets_values, 4}, + { set_extrude_mult_offset, extrude_offset, (const void**)extrude_offset_values, 4} +}; + +static void open_fan_speed_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_fan_speed_text, fan_speed_columns, 2); + lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +static void open_zoffset_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_zoffset_text, zoffset_columns, 2); + lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +static void open_speed_mult_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_speed_mult_text, speed_mult_columns, 3); + lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +static void open_extrude_mult_panel(lv_event_t * e){ + lv_create_fullscreen_button_matrix_popup(lv_scr_act(), set_extrude_mult_text, extrude_mult_columns, 2); + lv_msg_send(DATA_PRINTER_DATA, &printer); +} + +void create_state_button(lv_obj_t * root, lv_event_cb_t label, lv_event_cb_t button){ + lv_obj_t * btn = lv_btn_create(root); + lv_obj_set_size(btn, CYD_SCREEN_PANEL_WIDTH_PX / 2 - CYD_SCREEN_GAP_PX * 3, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, button, LV_EVENT_CLICKED, NULL); + + lv_obj_t * label_obj = lv_label_create_ex(btn); + lv_obj_add_event_cb(label_obj, label, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subscribe_obj(DATA_PRINTER_DATA, label_obj, NULL); + lv_obj_align(label_obj, LV_ALIGN_CENTER, 0, 0); +} + +static void label_pos(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char x_pos_buff[32]; + sprintf(x_pos_buff, "X%.2f Y%.2f", printer.position[0], printer.position[1]); + lv_label_set_text(label, x_pos_buff); +} + +static void label_filament_used_m(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char filament_buff[32]; + sprintf(filament_buff, "%.2f m", printer.filament_used_mm / 1000); + lv_label_set_text(label, filament_buff); +} + +static void label_total_layers(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char layers_buff[32]; + sprintf(layers_buff, "%d of %d", printer.current_layer, printer.total_layers); + lv_label_set_text(label, layers_buff); +} + +static void label_pressure_advance(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char pressure_buff[32]; + sprintf(pressure_buff, "%.3f", printer.pressure_advance); + lv_label_set_text(label, pressure_buff); +} + +static void label_feedrate(lv_event_t * e){ + lv_obj_t * label = lv_event_get_target(e); + char feedrate_buff[32]; + sprintf(feedrate_buff, "%d mm/s", printer.feedrate_mm_per_s); + lv_label_set_text(label, feedrate_buff); +} + +void create_stat_text_block(lv_obj_t * root, const char* label, lv_event_cb_t value){ + lv_obj_t * panel = lv_create_empty_panel(root); + lv_obj_set_size(panel, LV_SIZE_CONTENT, LV_SIZE_CONTENT); + lv_layout_flex_column(panel , LV_FLEX_ALIGN_START, CYD_SCREEN_GAP_PX / 2, CYD_SCREEN_GAP_PX / 2); + lv_obj_set_flex_align(panel, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + + lv_obj_t * label_obj = lv_label_create_ex(panel); + lv_label_set_text(label_obj, label); + lv_obj_set_style_text_font(label_obj, &CYD_SCREEN_FONT_SMALL, 0); + + lv_obj_t * value_obj = lv_label_create_ex(panel); + lv_obj_add_event_cb(value_obj, value, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subscribe_obj(DATA_PRINTER_DATA, value_obj, NULL); +} + +void stats_panel_init(lv_obj_t* panel) { + auto panel_width = CYD_SCREEN_PANEL_WIDTH_PX / 2 - CYD_SCREEN_GAP_PX * 3; + + lv_obj_t * left_panel = lv_create_empty_panel(panel); + lv_obj_set_size(left_panel, panel_width, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX * 2); + lv_layout_flex_column(left_panel); + lv_obj_set_flex_align(left_panel, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_START); + lv_obj_align(left_panel, LV_ALIGN_TOP_LEFT, CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); + + create_stat_text_block(left_panel, "Position:", label_pos); + create_stat_text_block(left_panel, "Filament Used:", label_filament_used_m); + create_stat_text_block(left_panel, "Layer:", label_total_layers); + create_stat_text_block(left_panel, "Pressure Advance:", label_pressure_advance); + create_stat_text_block(left_panel, "Feedrate:", label_feedrate); + + lv_obj_t * right_panel = lv_create_empty_panel(panel); + lv_obj_set_size(right_panel, panel_width, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX * 2); + lv_layout_flex_column(right_panel, LV_FLEX_ALIGN_CENTER); + lv_obj_align(right_panel, LV_ALIGN_TOP_RIGHT, -1 * CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); + + create_state_button(right_panel, set_fan_speed_text, open_fan_speed_panel); + create_state_button(right_panel, set_zoffset_text, open_zoffset_panel); + create_state_button(right_panel, set_speed_mult_text, open_speed_mult_panel); + create_state_button(right_panel, set_extrude_mult_text, open_extrude_mult_panel); +} \ No newline at end of file diff --git a/CYD-Klipper/src/ui/panels/temp_panel.cpp b/CYD-Klipper/src/ui/panels/temp_panel.cpp index f055869..98fbb47 100644 --- a/CYD-Klipper/src/ui/panels/temp_panel.cpp +++ b/CYD-Klipper/src/ui/panels/temp_panel.cpp @@ -2,6 +2,7 @@ #include "../../core/data_setup.h" #include "../../conf/global_config.h" #include +#include "../ui_utils.h" enum temp_target{ TARGET_HOTEND, @@ -79,15 +80,14 @@ static void keyboard_callback(lv_event_t * e){ } char gcode[64]; - const char* space = "%20"; switch (keyboard_target){ case TARGET_HOTEND: - sprintf(gcode, "M104%sS%d", space, temp); + sprintf(gcode, "M104 S%d", temp); send_gcode(true, gcode); break; case TARGET_BED: - sprintf(gcode, "M140%sS%d", space, temp); + sprintf(gcode, "M140 S%d", temp); send_gcode(true, gcode); break; case TARGET_HOTEND_CONFIG_1: @@ -127,7 +127,8 @@ static void keyboard_callback(lv_event_t * e){ static void show_keyboard(lv_event_t * e){ lv_obj_t * keyboard = lv_keyboard_create(root_panel); lv_obj_t * ta = lv_textarea_create(root_panel); - lv_obj_set_size(ta, TFT_HEIGHT - 40, 120); + // TODO: Hack, should be fixed before finishing porting + lv_obj_set_size(ta, CYD_SCREEN_PANEL_WIDTH_PX, 120); lv_obj_align(ta, LV_ALIGN_TOP_MID, 0, 0); lv_textarea_set_max_length(ta, 3); //lv_textarea_set_one_line(ta, true); @@ -154,8 +155,8 @@ static void cooldown_temp(lv_event_t * e){ return; } - send_gcode(true, "M104%20S0"); - send_gcode(true, "M140%20S0"); + send_gcode(true, "M104 S0"); + send_gcode(true, "M140 S0"); } static void btn_extrude(lv_event_t * e){ @@ -164,7 +165,7 @@ static void btn_extrude(lv_event_t * e){ } send_gcode(true, "M83"); - send_gcode(true, "G1%20E25%20F300"); + send_gcode(true, "G1 E25 F300"); } static void set_temp_via_preset(lv_event_t * e){ @@ -178,11 +179,10 @@ static void set_temp_via_preset(lv_event_t * e){ } char gcode[64]; - const char* space = "%20"; if (target <= TARGET_HOTEND_CONFIG_3) - sprintf(gcode, "M104%sS%d", space, value); + sprintf(gcode, "M104 S%d", value); else - sprintf(gcode, "M140%sS%d", space, value); + sprintf(gcode, "M140 S%d", value); send_gcode(true, gcode); } @@ -199,109 +199,107 @@ static void btn_retract(lv_event_t * e){ } send_gcode(true, "M83"); - send_gcode(true, "G1%20E-25%20F300"); + send_gcode(true, "G1 E-25 F300"); } -void temp_panel_init(lv_obj_t* panel){ +void temp_panel_init(lv_obj_t * panel){ + const auto element_width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2; root_panel = panel; edit_mode = false; - const int btn_row_y_one = 30; - const int btn_row_y_two = 100; - auto panel_width = TFT_HEIGHT - 40; - lv_obj_t * label = lv_label_create(panel); - lv_label_set_text(label, "???"); - lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 10); - lv_obj_add_event_cb(label, update_printer_data_hotend_temp, LV_EVENT_MSG_RECEIVED, NULL); - lv_msg_subscribe_obj(DATA_PRINTER_DATA, label, NULL); - - label = lv_label_create(panel); - lv_label_set_text(label, "???"); - lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 80); - lv_obj_add_event_cb(label, update_printer_data_bed_temp, LV_EVENT_MSG_RECEIVED, NULL); - lv_msg_subscribe_obj(DATA_PRINTER_DATA, label, NULL); - - lv_obj_t * btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_TOP_RIGHT, -10, btn_row_y_one); - lv_obj_add_event_cb(btn, show_keyboard_with_hotend, LV_EVENT_CLICKED, panel); - lv_obj_set_width(btn, panel_width / 4 - 10); - - label = lv_label_create(btn); - lv_label_set_text(label, "Set"); - lv_obj_center(label); - - btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_TOP_RIGHT, -10, btn_row_y_two); - lv_obj_add_event_cb(btn, show_keyboard_with_bed, LV_EVENT_CLICKED, panel); - lv_obj_set_width(btn, panel_width / 4 - 10); - label = lv_label_create(btn); - lv_label_set_text(label, "Set"); - lv_obj_center(label); + lv_obj_t * root_temp_panel = lv_create_empty_panel(panel); + lv_obj_set_size(root_temp_panel, CYD_SCREEN_PANEL_WIDTH_PX, LV_SIZE_CONTENT); + lv_obj_align(root_temp_panel, LV_ALIGN_TOP_RIGHT, 0, 0); + lv_obj_set_style_pad_all(root_temp_panel, CYD_SCREEN_GAP_PX, 0); + lv_layout_flex_column(root_temp_panel); - // Presets - for (int i = 0; i < 3; i++){ - int x_pos = 10 + (panel_width / 4) * i - (3 * i); + lv_obj_t * temp_rows[2] = {0}; + lv_obj_t * button_temp_rows[2] = {0}; - btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x_pos, btn_row_y_one); - lv_obj_add_event_cb(btn, set_temp_via_preset, LV_EVENT_CLICKED, reinterpret_cast(TARGET_HOTEND_CONFIG_1 + i)); - lv_obj_set_width(btn, panel_width / 4 - 10); + for (int tempIter = 0; tempIter < 2; tempIter++){ + temp_rows[tempIter] = lv_create_empty_panel(root_temp_panel); + lv_layout_flex_column(temp_rows[tempIter]); + lv_obj_set_size(temp_rows[tempIter], element_width, LV_SIZE_CONTENT); - label = lv_label_create(btn); + lv_obj_t * label = lv_label_create_ex(temp_rows[tempIter]); lv_label_set_text(label, "???"); - lv_obj_center(label); - lv_obj_add_event_cb(label, update_temp_preset_label, LV_EVENT_MSG_RECEIVED, reinterpret_cast(TARGET_HOTEND_CONFIG_1 + i)); - lv_msg_subscribe_obj(DATA_PRINTER_TEMP_PRESET, label, NULL); + lv_obj_add_event_cb(label, (tempIter == 0) ? update_printer_data_hotend_temp : update_printer_data_bed_temp, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subscribe_obj(DATA_PRINTER_DATA, label, NULL); + lv_obj_set_width(label, element_width); + + button_temp_rows[tempIter] = lv_create_empty_panel(temp_rows[tempIter]); + lv_layout_flex_row(button_temp_rows[tempIter], LV_FLEX_ALIGN_SPACE_EVENLY); + lv_obj_set_size(button_temp_rows[tempIter], element_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + for (int buttonIter = 0; buttonIter < 3; buttonIter++){ + lv_obj_t * btn = lv_btn_create(button_temp_rows[tempIter]); + lv_obj_add_event_cb(btn, set_temp_via_preset, LV_EVENT_CLICKED, reinterpret_cast(TARGET_HOTEND_CONFIG_1 + buttonIter + tempIter * 3)); + lv_obj_set_flex_grow(btn, 1); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, "???"); + lv_obj_center(label); + lv_obj_add_event_cb(label, update_temp_preset_label, LV_EVENT_MSG_RECEIVED, reinterpret_cast(TARGET_HOTEND_CONFIG_1 + buttonIter + tempIter * 3)); + lv_msg_subscribe_obj(DATA_PRINTER_TEMP_PRESET, label, NULL); + } - btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_TOP_LEFT, x_pos, btn_row_y_two); - lv_obj_add_event_cb(btn, set_temp_via_preset, LV_EVENT_CLICKED, reinterpret_cast(TARGET_BED_CONFIG_1 + i)); - lv_obj_set_width(btn, panel_width / 4 - 10); + lv_obj_t * btn = lv_btn_create(button_temp_rows[tempIter]); + lv_obj_add_event_cb(btn, (tempIter == 0) ? show_keyboard_with_hotend : show_keyboard_with_bed, LV_EVENT_CLICKED, panel); + lv_obj_set_flex_grow(btn, 1); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - label = lv_label_create(btn); - lv_label_set_text(label, "???"); + label = lv_label_create_ex(btn); + lv_label_set_text(label, "Set"); lv_obj_center(label); - lv_obj_add_event_cb(label, update_temp_preset_label, LV_EVENT_MSG_RECEIVED, reinterpret_cast(TARGET_BED_CONFIG_1 + i)); - lv_msg_subscribe_obj(DATA_PRINTER_TEMP_PRESET, label, NULL); } - btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_LEFT, 10, -50); - lv_obj_set_size(btn, panel_width / 2 - 15, 40); - lv_obj_add_event_cb(btn, cooldown_temp, LV_EVENT_CLICKED, panel); - - label = lv_label_create(btn); - lv_label_set_text(label, "Cooldown"); - lv_obj_center(label); - - btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -10, -50); - lv_obj_add_event_cb(btn, btn_toggleable_edit, LV_EVENT_CLICKED, NULL); - lv_obj_add_flag(btn, LV_OBJ_FLAG_CHECKABLE); - lv_obj_set_size(btn, panel_width / 2 - 15, 40); + lv_obj_t * bottom_panel = lv_create_empty_panel(panel); + lv_obj_set_size(bottom_panel, element_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(bottom_panel, LV_ALIGN_BOTTOM_MID, 0, -1 * CYD_SCREEN_GAP_PX); + lv_layout_flex_row(bottom_panel, LV_FLEX_ALIGN_SPACE_EVENLY); - label = lv_label_create(btn); - lv_label_set_text(label, "Edit Presets"); - lv_obj_center(label); + lv_obj_t * one_above_bottom_panel = lv_create_empty_panel(panel); + lv_obj_set_size(one_above_bottom_panel, element_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(one_above_bottom_panel, LV_ALIGN_BOTTOM_MID, 0, -1 * CYD_SCREEN_MIN_BUTTON_HEIGHT_PX - CYD_SCREEN_GAP_PX * 2); + lv_layout_flex_row(one_above_bottom_panel, LV_FLEX_ALIGN_SPACE_EVENLY); - btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_LEFT, 10, -5); + lv_obj_t * btn = lv_btn_create(bottom_panel); + lv_obj_set_flex_grow(btn, 1); lv_obj_add_event_cb(btn, btn_extrude, LV_EVENT_CLICKED, NULL); - lv_obj_set_size(btn, panel_width / 2 - 15, 40); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - label = lv_label_create(btn); + lv_obj_t * label = lv_label_create_ex(btn); lv_label_set_text(label, LV_SYMBOL_DOWN " Extrude"); lv_obj_center(label); - btn = lv_btn_create(panel); - lv_obj_align(btn, LV_ALIGN_BOTTOM_RIGHT, -10, -5); + btn = lv_btn_create(one_above_bottom_panel); + lv_obj_set_flex_grow(btn, 1); lv_obj_add_event_cb(btn, btn_retract, LV_EVENT_CLICKED, NULL); - lv_obj_set_size(btn, panel_width / 2 - 15, 40); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - label = lv_label_create(btn); + label = lv_label_create_ex(btn); lv_label_set_text(label, LV_SYMBOL_UP " Retract"); lv_obj_center(label); - lv_msg_send(DATA_PRINTER_DATA, &printer); + btn = lv_btn_create(bottom_panel); + lv_obj_set_flex_grow(btn, 1); + lv_obj_add_event_cb(btn, cooldown_temp, LV_EVENT_CLICKED, NULL); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, "Cooldown"); + lv_obj_center(label); + + btn = lv_btn_create(one_above_bottom_panel); + lv_obj_set_flex_grow(btn, 1); + lv_obj_add_event_cb(btn, btn_toggleable_edit, LV_EVENT_CLICKED, NULL); + lv_obj_set_height(btn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_flag(btn, LV_OBJ_FLAG_CHECKABLE); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, "Edit Presets"); + lv_obj_center(label); + lv_msg_send(DATA_PRINTER_TEMP_PRESET, &printer); } \ No newline at end of file diff --git a/CYD-Klipper/src/ui/ui_utils.cpp b/CYD-Klipper/src/ui/ui_utils.cpp new file mode 100644 index 0000000..e2cb7ec --- /dev/null +++ b/CYD-Klipper/src/ui/ui_utils.cpp @@ -0,0 +1,95 @@ +#include "lvgl.h" +#include "ui_utils.h" +#include "../core/data_setup.h" +#include "../core/lv_setup.h" + +lv_obj_t* lv_label_create_ex(lv_obj_t* parent) +{ + lv_obj_t* label = lv_label_create(parent); + lv_obj_add_style(label, get_default_label_style(), 0); + return label; +} + +lv_obj_t* lv_create_empty_panel(lv_obj_t* root) { + lv_obj_t* panel = lv_obj_create(root); + lv_obj_set_style_border_width(panel, 0, 0); + lv_obj_set_style_bg_opa(panel, LV_OPA_TRANSP, 0); + lv_obj_set_style_pad_all(panel, 0, 0); + return panel; +} + +void lv_layout_flex_column(lv_obj_t* obj, lv_flex_align_t allign, lv_coord_t pad_column, lv_coord_t pad_row){ + lv_obj_set_layout(obj, LV_LAYOUT_FLEX); + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_COLUMN); + lv_obj_set_flex_align(obj, allign, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_set_style_pad_column(obj, pad_column, 0); + lv_obj_set_style_pad_row(obj, pad_row, 0); +} + +void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign, lv_coord_t pad_column, lv_coord_t pad_row){ + lv_obj_set_layout(obj, LV_LAYOUT_FLEX); + lv_obj_set_flex_flow(obj, LV_FLEX_FLOW_ROW); + lv_obj_set_flex_align(obj, allign, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER); + lv_obj_set_style_pad_column(obj, pad_column, 0); + lv_obj_set_style_pad_row(obj, pad_row, 0); +} + +void destroy_event_user_data(lv_event_t * e){ + lv_obj_t * obj = (lv_obj_t *)lv_event_get_user_data(e); + lv_obj_del(obj); +} + +void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count){ + const auto full_panel_width = CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 3; + const auto full_panel_inner_width = full_panel_width - CYD_SCREEN_GAP_PX * 2 - 4; + const auto full_panel_height = CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX; + const auto full_panel_inner_height = full_panel_height - CYD_SCREEN_GAP_PX * 2 - 4; + auto column_width = full_panel_inner_width / column_count - CYD_SCREEN_GAP_PX; + auto column_height = full_panel_inner_height - CYD_SCREEN_GAP_PX - CYD_SCREEN_MIN_BUTTON_HEIGHT_PX; + + lv_obj_t * panel = lv_obj_create(root); + lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0); + lv_obj_set_size(panel, full_panel_width, full_panel_height); + lv_obj_align(panel, LV_ALIGN_CENTER, 0, 0); + + lv_obj_t * top_menu_row = lv_create_empty_panel(panel); + lv_obj_set_size(top_menu_row, full_panel_inner_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(top_menu_row, LV_ALIGN_TOP_LEFT, 0, 0); + + lv_obj_t * btn = lv_btn_create(top_menu_row); + lv_obj_set_size(btn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(btn, LV_ALIGN_RIGHT_MID, 0, 0); + lv_obj_add_event_cb(btn, destroy_event_user_data, LV_EVENT_CLICKED, panel); + + lv_obj_t * label = lv_label_create_ex(btn); + lv_label_set_text(label, LV_SYMBOL_CLOSE); + lv_obj_center(label); + + label = lv_label_create_ex(top_menu_row); + lv_label_set_text(label, "-"); + lv_obj_align(label, LV_ALIGN_LEFT_MID, 0, 0); + lv_obj_add_event_cb(label, title, LV_EVENT_MSG_RECEIVED, NULL); + lv_msg_subsribe_obj(DATA_PRINTER_DATA, label, NULL); + + lv_obj_t * rows = lv_create_empty_panel(panel); + lv_obj_set_size(rows, full_panel_inner_width, column_height); + lv_obj_align(rows, LV_ALIGN_BOTTOM_LEFT, 0, 0); + lv_layout_flex_row(rows, LV_FLEX_ALIGN_SPACE_BETWEEN, CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); + + for (int i = 0; i < column_count; i++){ + lv_obj_t * column = lv_create_empty_panel(rows); + lv_obj_clear_flag(column, LV_OBJ_FLAG_SCROLLABLE); + lv_obj_set_size(column, column_width, column_height); + lv_layout_flex_column(column, LV_FLEX_ALIGN_CENTER, CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); + + for (int j = 0; j < columns[i].length; j++){ + lv_obj_t * btn = lv_btn_create(column); + lv_obj_set_size(btn, column_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_add_event_cb(btn, columns[i].event, LV_EVENT_CLICKED, (void*)columns[i].data[j]); + + label = lv_label_create_ex(btn); + lv_label_set_text(label, columns[i].labels[j]); + lv_obj_center(label); + } + } +} \ No newline at end of file diff --git a/CYD-Klipper/src/ui/ui_utils.h b/CYD-Klipper/src/ui/ui_utils.h new file mode 100644 index 0000000..1b1c4d7 --- /dev/null +++ b/CYD-Klipper/src/ui/ui_utils.h @@ -0,0 +1,26 @@ +#pragma once + +#ifndef CYD_SCREEN_WIDTH_PX +#define CYD_SCREEN_WIDTH_PX LCD_HEIGHT +#endif + +#ifndef CYD_SCREEN_HEIGHT_PX +#define CYD_SCREEN_HEIGHT_PX LCD_WIDTH +#endif + +#define CYD_SCREEN_PANEL_WIDTH_PX \ + (CYD_SCREEN_WIDTH_PX - CYD_SCREEN_SIDEBAR_SIZE_PX) + +typedef struct { + lv_event_cb_t event; + const char** labels; + const void** data; + int length; +} lv_button_column_t; + +lv_obj_t* lv_label_create_ex(lv_obj_t* parent); +lv_obj_t* lv_create_empty_panel(lv_obj_t* root); +void lv_layout_flex_column(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_START, lv_coord_t pad_column = CYD_SCREEN_GAP_PX, lv_coord_t pad_row = CYD_SCREEN_GAP_PX); +void lv_layout_flex_row(lv_obj_t* obj, lv_flex_align_t allign = LV_FLEX_ALIGN_START, lv_coord_t pad_column = CYD_SCREEN_GAP_PX, lv_coord_t pad_row = CYD_SCREEN_GAP_PX); +void lv_create_fullscreen_button_matrix_popup(lv_obj_t * root, lv_event_cb_t title, lv_button_column_t* columns, int column_count); +void destroy_event_user_data(lv_event_t * e); \ No newline at end of file diff --git a/CYD-Klipper/src/ui/wifi_setup.cpp b/CYD-Klipper/src/ui/wifi_setup.cpp index c86c5fd..9197bc3 100644 --- a/CYD-Klipper/src/ui/wifi_setup.cpp +++ b/CYD-Klipper/src/ui/wifi_setup.cpp @@ -1,8 +1,9 @@ #include "lvgl.h" #include "wifi_setup.h" #include "../conf/global_config.h" - +#include "ui_utils.h" #include "WiFi.h" + void wifi_init_inner(); static void reset_btn_event_handler(lv_event_t * e) { @@ -47,18 +48,28 @@ static void ta_event_cb(lv_event_t * e) { void wifi_pass_entry(const char* ssid){ lv_obj_clean(lv_scr_act()); - lv_obj_t * label = lv_label_create(lv_scr_act()); + lv_obj_t * root = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_size(root, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_layout_flex_column(root); + + lv_obj_t * top_root = lv_create_empty_panel(root); + lv_obj_set_width(top_root, CYD_SCREEN_WIDTH_PX); + lv_layout_flex_column(top_root); + lv_obj_set_flex_grow(top_root, 1); + lv_obj_set_style_pad_all(top_root, CYD_SCREEN_GAP_PX, 0); + + lv_obj_t * label = lv_label_create_ex(top_root); lv_label_set_text(label, "Enter WiFi Password"); - lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 10 + 2); + lv_obj_set_width(label, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); - lv_obj_t * passEntry = lv_textarea_create(lv_scr_act()); + lv_obj_t * passEntry = lv_textarea_create(top_root); lv_textarea_set_one_line(passEntry, true); lv_textarea_set_text(passEntry, ""); - lv_obj_align(passEntry, LV_ALIGN_TOP_LEFT, 10, 40); + lv_obj_set_width(passEntry, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); lv_obj_add_event_cb(passEntry, ta_event_cb, LV_EVENT_ALL, NULL); - lv_obj_set_size(passEntry, TFT_HEIGHT - 20, 60); + lv_obj_set_flex_grow(passEntry, 1); - lv_obj_t * keyboard = lv_keyboard_create(lv_scr_act()); + lv_obj_t * keyboard = lv_keyboard_create(root); lv_keyboard_set_textarea(keyboard, passEntry); } @@ -74,7 +85,6 @@ static void wifi_btn_event_handler(lv_event_t * e){ } } - void wifi_init_inner(){ WiFi.disconnect(); lv_obj_clean(lv_scr_act()); @@ -82,22 +92,23 @@ void wifi_init_inner(){ if (global_config.wifiConfigured){ WiFi.begin(global_config.wifiSSID, global_config.wifiPassword); - lv_obj_t * label = lv_label_create(lv_scr_act()); + lv_obj_t * label = lv_label_create_ex(lv_scr_act()); lv_label_set_text(label, "Connecting to WiFi"); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); lv_obj_t * resetBtn = lv_btn_create(lv_scr_act()); - lv_obj_add_event_cb(resetBtn, reset_btn_event_handler, LV_EVENT_ALL, NULL); - lv_obj_align(resetBtn, LV_ALIGN_CENTER, 0, 40); + lv_obj_add_event_cb(resetBtn, reset_btn_event_handler, LV_EVENT_CLICKED, NULL); + lv_obj_set_height(resetBtn, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); + lv_obj_align(resetBtn, LV_ALIGN_CENTER, 0, CYD_SCREEN_GAP_PX + CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - label = lv_label_create(resetBtn); + label = lv_label_create_ex(resetBtn); lv_label_set_text(label, "Reset"); lv_obj_center(label); return; } - lv_obj_t * label = lv_label_create(lv_scr_act()); + lv_obj_t * label = lv_label_create_ex(lv_scr_act()); lv_label_set_text(label, "Scanning for networks..."); lv_obj_align(label, LV_ALIGN_CENTER, 0, 0); @@ -107,21 +118,29 @@ void wifi_init_inner(){ lv_obj_clean(lv_scr_act()); - lv_obj_t * refreshBtn = lv_btn_create(lv_scr_act()); + lv_obj_t * root = lv_create_empty_panel(lv_scr_act()); + lv_obj_set_size(root, CYD_SCREEN_WIDTH_PX, CYD_SCREEN_HEIGHT_PX); + lv_layout_flex_column(root); + lv_obj_set_style_pad_all(root, CYD_SCREEN_GAP_PX, 0); + + lv_obj_t * top_row = lv_create_empty_panel(root); + lv_obj_set_size(top_row, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2, LV_SIZE_CONTENT); + lv_layout_flex_row(top_row, LV_FLEX_ALIGN_SPACE_BETWEEN); + + label = lv_label_create_ex(top_row); + lv_label_set_text(label, "Select a network"); + + lv_obj_t * refreshBtn = lv_btn_create(top_row); lv_obj_add_event_cb(refreshBtn, reset_btn_event_handler, LV_EVENT_ALL, NULL); - lv_obj_align(refreshBtn, LV_ALIGN_TOP_RIGHT, -5, 5 - 1); + lv_obj_set_size(refreshBtn, CYD_SCREEN_MIN_BUTTON_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); - label = lv_label_create(refreshBtn); + label = lv_label_create_ex(refreshBtn); lv_label_set_text(label, LV_SYMBOL_REFRESH); lv_obj_center(label); - label = lv_label_create(lv_scr_act()); - lv_label_set_text(label, "Select a network"); - lv_obj_align(label, LV_ALIGN_TOP_LEFT, 10, 10 + 2); - - lv_obj_t * list = lv_list_create(lv_scr_act()); - lv_obj_align(list, LV_ALIGN_TOP_LEFT, 10, 40); - lv_obj_set_size(list, TFT_HEIGHT - 20, TFT_WIDTH - 40 - 5); + lv_obj_t * list = lv_list_create(root); + lv_obj_set_width(list, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2); + lv_obj_set_flex_grow(list, 1); int n = WiFi.scanNetworks(); diff --git a/README.md b/README.md index d8a2d77..36359ad 100644 --- a/README.md +++ b/README.md @@ -14,12 +14,14 @@ A ESP32-2432S028R is required to run this project. You can find out where to buy ### Features - View printer status -- View print progress +- View print progress and print statistics - Start a print -- Move the printer +- (When the printer is idle) move the printer +- (During a print) set fan speed, flow rate, speed and z offset - Manage temperature - Extrude/Retract filament - Execute predefined gcode macros +- Toggle Moonraker power devices ### Install @@ -34,11 +36,15 @@ There are no 'over the air' updates. Each update has to be applied manually. -|- :-:|:-: -![1](readme/PXL_20231113_142717308.jpg)|![2](readme/PXL_20231113_171701876.jpg) -![3](readme/PXL_20231113_171715809.jpg)|![4](readme/PXL_20231113_171724404.jpg) -![5](readme/PXL_20231113_171751745.jpg)|![6](readme/PXL_20231113_171809315.jpg) +![1](readme/1.jpg)|![2](readme/2.jpg) +![3](readme/3.jpg)|![4](readme/4.jpg) +![5](readme/5.jpg)|![6](readme/6.jpg) +![7](readme/7.jpg)|![8](readme/8.jpg) +![9](readme/9.jpg)|![10](readme/10.jpg) ### Credits - [xtouch](https://github.com/xperiments-in/xtouch) -- [ESP32-Cheap-Yellow-Display](https://github.com/witnessmenow/ESP32-Cheap-Yellow-Display) \ No newline at end of file +- [ESP32-Cheap-Yellow-Display](https://github.com/witnessmenow/ESP32-Cheap-Yellow-Display) +- [OperatorB](https://github.com/OperatorB) for the ESP32-3248S035C display driver +- [esp32-smartdisplay](https://github.com/rzeldent/esp32-smartdisplay) \ No newline at end of file diff --git a/_site/index.html b/_site/index.html index aeecc14..568c21a 100644 --- a/_site/index.html +++ b/_site/index.html @@ -8,26 +8,70 @@ font-family: 'Roboto', sans-serif; } + body { + background-color: #181a1b; + color: white; + } + .main { width: fit-content; margin: auto; + max-width: 750px; + } + + .main > section > :not(:first-child) { + margin-left: 20px; + } + + .main a { + color: #F00; + } + + .install .iconify { + color: green; + filter: drop-shadow(0 0 0.75rem lime); } + +
-

CYD-Klipper

-

An implementation of a Klipper status display on an ESP32 + screen.
Uses Moonraker to fetch data.

- GitHub release (with filter) - GitHub repo - Donate KoFi +

CYD-Klipper

+

An implementation of a Klipper status display on an ESP32 + screen.
Uses Moonraker to fetch data.
Source code is available on GitHub.

+ +
+

Changelog

+

+
+ + + +
+

Install on ESP32-2432S028 (2.8" Resistive)

+

Note: You may need to hold the 'BOOT' button on the device while pressing install.

+ +
-

Install

-

Note: You may need to hold the 'BOOT' button on the device while pressing install

+

Install on ESP32-3248S035 (3.5" Capacitive)

+

Note: You may need to hold the 'BOOT' button on the device while pressing install.

+ manifest="https://suchmememanyskill.github.io/CYD-Klipper/esp32-3248S035C.json">
\ No newline at end of file diff --git a/_site/manifest.json b/_site/manifest.json deleted file mode 100644 index d8029dc..0000000 --- a/_site/manifest.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "CYD-Klipper", - "new_install_prompt_erase": true, - "builds": [ - { - "chipFamily": "ESP32", - "parts": [ - { - "path": "output/bootloader.bin", - "offset": 4096 - }, - { - "path": "output/partitions.bin", - "offset": 32768 - }, - { - "path": "output/boot_app0.bin", - "offset": 57344 - }, - { - "path": "output/firmware.bin", - "offset": 65536 - } - ] - } - ] -} \ No newline at end of file diff --git a/_site/manifest_wipe.json b/_site/manifest_wipe.json deleted file mode 100644 index 8e471f8..0000000 --- a/_site/manifest_wipe.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "CYD-Klipper", - "new_install_prompt_erase": false, - "builds": [ - { - "path": "output/merged-firmware.bin", - "offset": 0 - } - ] -} \ No newline at end of file diff --git a/ci.py b/ci.py new file mode 100644 index 0000000..d339c0c --- /dev/null +++ b/ci.py @@ -0,0 +1,58 @@ +import subprocess, os, shutil, json + +CYD_PORTS = ["esp32-3248S035C", "esp32-2432S028R"] +BASE_DIR = os.getcwd() + +def get_manifest(base_path : str): + return { + "name": "CYD-Klipper", + "new_install_prompt_erase": True, + "builds": [ + { + "chipFamily": "ESP32", + "parts": [ + { + "path": f"{base_path}/bootloader.bin", + "offset": 4096 + }, + { + "path": f"{base_path}/partitions.bin", + "offset": 32768 + }, + { + "path": f"{base_path}/boot_app0.bin", + "offset": 57344 + }, + { + "path": f"{base_path}/firmware.bin", + "offset": 65536 + } + ] + } + ] + } + +if os.path.exists("out"): + shutil.rmtree("out") + +for port in CYD_PORTS: + port_path = f"out/{port}" + os.chdir(BASE_DIR) + os.makedirs(port_path, exist_ok=True) + os.chdir("CYD-Klipper") + subprocess.run(["pio", "run", "-e", port], check=True) + os.chdir(BASE_DIR) + for file in ["bootloader.bin", "partitions.bin", "firmware.bin"]: + shutil.copy(f"./CYD-Klipper/.pio/build/{port}/{file}", f"{port_path}/{file}") + + 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) + subprocess.run(["python3", "-m", "esptool", "--chip", "esp32", "merge_bin", "-o", "merged_firmware.bin", "--flash_mode", "dio", "--flash_freq", "40m", "--flash_size", "4MB", "0x1000", "bootloader.bin", "0x8000", "partitions.bin", "0xe000", "boot_app0.bin", "0x10000", "firmware.bin"], check=True) + + os.chdir(BASE_DIR) + + with open(f"./_site/{port}.json", "w") as f: + json.dump(get_manifest(port_path), f) + +os.chdir(BASE_DIR) +shutil.copytree("./out", "./_site/out") diff --git a/readme/1.jpg b/readme/1.jpg new file mode 100644 index 0000000..593ac57 Binary files /dev/null and b/readme/1.jpg differ diff --git a/readme/PXL_20231113_171809315.jpg b/readme/10.jpg similarity index 99% rename from readme/PXL_20231113_171809315.jpg rename to readme/10.jpg index ba615b4..fb11bfc 100644 Binary files a/readme/PXL_20231113_171809315.jpg and b/readme/10.jpg differ diff --git a/readme/2.jpg b/readme/2.jpg new file mode 100644 index 0000000..b526e39 Binary files /dev/null and b/readme/2.jpg differ diff --git a/readme/3.jpg b/readme/3.jpg new file mode 100644 index 0000000..9ec8457 Binary files /dev/null and b/readme/3.jpg differ diff --git a/readme/4.jpg b/readme/4.jpg new file mode 100644 index 0000000..e9a8226 Binary files /dev/null and b/readme/4.jpg differ diff --git a/readme/5.jpg b/readme/5.jpg new file mode 100644 index 0000000..cbfbd3c Binary files /dev/null and b/readme/5.jpg differ diff --git a/readme/6.jpg b/readme/6.jpg new file mode 100644 index 0000000..2da22b9 Binary files /dev/null and b/readme/6.jpg differ diff --git a/readme/7.jpg b/readme/7.jpg new file mode 100644 index 0000000..651cc2f Binary files /dev/null and b/readme/7.jpg differ diff --git a/readme/8.jpg b/readme/8.jpg new file mode 100644 index 0000000..93ffdeb Binary files /dev/null and b/readme/8.jpg differ diff --git a/readme/PXL_20231113_171751745.jpg b/readme/9.jpg similarity index 99% rename from readme/PXL_20231113_171751745.jpg rename to readme/9.jpg index 6428716..c9860a7 100644 Binary files a/readme/PXL_20231113_171751745.jpg and b/readme/9.jpg differ diff --git a/readme/PXL_20231113_142717308.jpg b/readme/PXL_20231113_142717308.jpg deleted file mode 100644 index b6b3aca..0000000 Binary files a/readme/PXL_20231113_142717308.jpg and /dev/null differ diff --git a/readme/PXL_20231113_171701876.jpg b/readme/PXL_20231113_171701876.jpg deleted file mode 100644 index 02b16ab..0000000 Binary files a/readme/PXL_20231113_171701876.jpg and /dev/null differ diff --git a/readme/PXL_20231113_171715809.jpg b/readme/PXL_20231113_171715809.jpg deleted file mode 100644 index 7a54176..0000000 Binary files a/readme/PXL_20231113_171715809.jpg and /dev/null differ diff --git a/readme/PXL_20231113_171724404.jpg b/readme/PXL_20231113_171724404.jpg deleted file mode 100644 index 4b5bc80..0000000 Binary files a/readme/PXL_20231113_171724404.jpg and /dev/null differ