19 Commits

Author SHA1 Message Date
Sims
1c7d5ffacd Merge pull request #51 from suchmememanyskill/dev
v1.4.0
2024-02-21 23:33:13 +01:00
suchmememanyskill
1bc770a1cf Undo o2 optimalisations 2024-02-21 23:20:01 +01:00
suchmememanyskill
b5ac6d045a Retry slicer print time fetch 2024-02-20 23:20:33 +01:00
suchmememanyskill
c9f8935310 Don't send gcode requests twice 2024-02-20 22:40:00 +01:00
suchmememanyskill
ff1c13602c Add API key flow 2024-02-19 21:56:35 +01:00
Flaviu Tamas
5d3d32b116 Fix frequent null-pointer errors (#49)
I was frequently seeing the following and a reboot:

Guru Meditation Error: Core  0 panic'ed (LoadProhibited). Exception was unhandled.

Core  0 register dump:
PC      : 0x4008ae2d  PS      : 0x00060330  A0      : 0x800d3fd9  A1      : 0x3ffe15f0
A2      : 0x3ffc40e8  A3      : 0x00000000  A4      : 0x000000ff  A5      : 0x0000ff00
A6      : 0x00ff0000  A7      : 0xff000000  A8      : 0x00000000  A9      : 0x3ffe15c0
A10     : 0x3ffc40e8  A11     : 0x3f40035d  A12     : 0x3ffe16a0  A13     : 0x000004b0
A14     : 0x7ff00000  A15     : 0x7ff2c000  SAR     : 0x0000001d  EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000  LBEG    : 0x4008ae2d  LEND    : 0x4008ae41  LCOUNT  : 0xffffffff

Backtrace: 0x4008ae2a:0x3ffe15f0 0x400d3fd6:0x3ffe1600 0x400d42d3:0x3ffe18f0

decoded:

0x4008acbc: strcmp at /builds/idf/crosstool-NG/.build/xtensa-esp32-elf/src/newlib/newlib/libc/machine/xtensa/strcmp.S:467
0x400d4145: fetch_printer_data() at /home/user/tmp/CYD-Klipper/CYD-Klipper/src/core/data_setup.cpp:180
0x400d42d3: data_loop_background(void*) at /home/user/tmp/CYD-Klipper/CYD-Klipper/src/core/data_setup.cpp:233 (discriminator 1)

Seems like the printer state was frequently ending up as null, so check
for that and return a reasonable response. After applying this patch,
things are stable for me.
2024-02-19 21:26:22 +01:00
suchmememanyskill
edec1724e6 Properly fix #45 2024-02-19 17:37:08 +01:00
suchmememanyskill
dd5e82d637 Reorder settings 2024-02-19 17:16:56 +01:00
suchmememanyskill
e5edabffa4 Add slicer time based estimates 2024-02-18 12:04:01 +01:00
suchmememanyskill
a1bb6a750f Improve Z Offset menu 2024-02-17 12:11:18 +01:00
suchmememanyskill
43cefaafd2 Make temp chart fit the lines 2024-02-16 23:39:35 +01:00
suchmememanyskill
dcf32d6685 Fix temp chart crashing 2024-02-16 23:09:32 +01:00
suchmememanyskill
12c4319173 Add graph to temp panel 2024-02-16 22:47:55 +01:00
suchmememanyskill
86be30034d Optimalisations 2024-02-16 22:15:15 +01:00
suchmememanyskill
4fc2316970 (Hack) Restart ESP when klipper calls start failing 2024-02-15 18:32:36 +01:00
suchmememanyskill
3dc241dbec Make stats panel accessible from move panel, improve Z offset menu 2024-02-15 18:29:13 +01:00
suchmememanyskill
cd58fcae4f Move touch calibration to lv_conf, implement invert colors in smartdisplay driver 2024-02-12 22:26:09 +01:00
suchmememanyskill
87a9257e19 Add ESP32-2432S022C using smartdisplay driver 2024-02-12 18:24:30 +01:00
suchmememanyskill
a436c6b5c7 Update readme 2024-02-11 10:33:22 +01:00
29 changed files with 926 additions and 220 deletions

View File

@@ -57,7 +57,7 @@ jobs:
url: ${{ steps.deployment.outputs.page_url }} url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
if: (github.event_name == 'release' && github.event.action == 'created') || (github.event_name != 'pull_request' && github.ref == 'refs/heads/master') if: github.event_name == 'release' && github.event.action == 'created'
steps: steps:
- name: Print GitHub event name - name: Print GitHub event name
run: | run: |

View File

@@ -12,6 +12,8 @@
"algorithm": "cpp", "algorithm": "cpp",
"cstddef": "cpp", "cstddef": "cpp",
"functional": "cpp", "functional": "cpp",
"*.tcc": "cpp" "*.tcc": "cpp",
} "cmath": "cpp"
},
"cmake.configureOnOpen": false
} }

View File

@@ -0,0 +1,126 @@
{
"build": {
"arduino": {
"ldscript": "esp32_out.ld"
},
"core": "esp32",
"extra_flags": [
"'-D ARDUINO_ESP32_DEV'",
"'-D ESP32_2432S022C'",
"'-D LCD_WIDTH=240'",
"'-D LCD_HEIGHT=320'",
"'-D LVGL_BUFFER_PIXELS=(LCD_WIDTH*LCD_HEIGHT/8)'",
"'-D LVGL_BUFFER_MALLOC_FLAGS=(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)'",
"'-D BCKL=0'",
"'-D LCD_ST7789_I80'",
"'-D ST7789_I80_BUS_CONFIG_CLK_SRC=LCD_CLK_SRC_PLL160M'",
"'-D ST7789_I80_BUS_CONFIG_DC=16'",
"'-D ST7789_I80_BUS_CONFIG_WR=4'",
"'-D ST7789_I80_BUS_CONFIG_DATA_GPIO_D8=15'",
"'-D ST7789_I80_BUS_CONFIG_DATA_GPIO_D9=13'",
"'-D ST7789_I80_BUS_CONFIG_DATA_GPIO_D10=12'",
"'-D ST7789_I80_BUS_CONFIG_DATA_GPIO_D11=14'",
"'-D ST7789_I80_BUS_CONFIG_DATA_GPIO_D12=27'",
"'-D ST7789_I80_BUS_CONFIG_DATA_GPIO_D13=25'",
"'-D ST7789_I80_BUS_CONFIG_DATA_GPIO_D14=33'",
"'-D ST7789_I80_BUS_CONFIG_DATA_GPIO_D15=32'",
"'-D ST7789_I80_BUS_CONFIG_BUS_WIDTH=8'",
"'-D ST7789_I80_BUS_CONFIG_MAX_TRANSFER_BYTES=(LVGL_BUFFER_PIXELS * sizeof(lv_color_t))'",
"'-D ST7789_I80_BUS_CONFIG_PSRAM_TRANS_ALIGN=64'",
"'-D ST7789_I80_BUS_CONFIG_SRAM_TRANS_ALIGN=4'",
"'-D ST7789_IO_I80_CONFIG_CS_GPIO_NUM=17'",
"'-D ST7789_IO_I80_CONFIG_PCLK_HZ=55000000'",
"'-D ST7789_IO_I80_CONFIG_TRANS_QUEUE_DEPTH=10'",
"'-D ST7789_IO_I80_CONFIG_LCD_CMD_BITS=8'",
"'-D ST7789_IO_I80_CONFIG_LCD_PARAM_BITS=8'",
"'-D ST7789_IO_I80_CONFIG_DC_LEVELS_DC_IDLE_LEVEL=0'",
"'-D ST7789_IO_I80_CONFIG_DC_LEVELS_DC_CMD_LEVEL=0'",
"'-D ST7789_IO_I80_CONFIG_DC_LEVELS_DC_DUMMY_LEVEL=0'",
"'-D ST7789_IO_I80_CONFIG_DC_LEVELS_DC_DATA_LEVEL=1'",
"'-D ST7789_IO_I80_CONFIG_FLAGS_CS_ACTIVE_HIGH=0'",
"'-D ST7789_IO_I80_CONFIG_FLAGS_REVERSE_COLOR_BITS=0'",
"'-D ST7789_IO_I80_CONFIG_FLAGS_SWAP_COLOR_BYTES=0'",
"'-D ST7789_IO_I80_CONFIG_FLAGS_PCLK_ACTIVE_NEG=0'",
"'-D ST7789_IO_I80_CONFIG_FLAGS_PCLK_IDLE_LOW=0'",
"'-D ST7789_DEV_CONFIG_RESET_GPIO_NUM=GPIO_NUM_NC'",
"'-D ST7789_DEV_CONFIG_COLOR_SPACE=ESP_LCD_COLOR_SPACE_BGR'",
"'-D ST7789_DEV_CONFIG_BITS_PER_PIXEL=16'",
"'-D ST7789_DEV_CONFIG_FLAGS_RESET_ACTIVE_HIGH=false'",
"'-D ST7789_DEV_CONFIG_VENDOR_CONFIG=NULL'",
"'-D ST7789_RD_GPIO=2'",
"'-D LCD_SWAP_XY=false'",
"'-D LCD_MIRROR_X=false'",
"'-D LCD_MIRROR_Y=false'",
"'-D BOARD_HAS_TOUCH'",
"'-D TOUCH_CST816S_I2C'",
"'-D CST816S_I2C_HOST=0'",
"'-D CST816S_I2C_CONFIG_SDA_IO_NUM=21'",
"'-D CST816S_I2C_CONFIG_SCL_IO_NUM=22'",
"'-D CST816S_I2C_CONFIG_SDA_PULLUP_EN=GPIO_PULLUP_ENABLE'",
"'-D CST816S_I2C_CONFIG_SCL_PULLUP_EN=GPIO_PULLUP_ENABLE'",
"'-D CST816S_I2C_CONFIG_MASTER_CLK_SPEED=400000'",
"'-D CST816S_I2C_CONFIG_CLK_FLAGS=0'",
"'-D CST816S_IO_I2C_CONFIG_DEV_ADDR=ESP_LCD_TOUCH_IO_I2C_CST816S_ADDRESS'",
"'-D CST816S_IO_I2C_CONFIG_CONTROL_PHASE_BYTES=1'",
"'-D CST816S_IO_I2C_CONFIG_DC_BIT_OFFSET=0'",
"'-D CST816S_IO_I2C_CONFIG_LCD_CMD_BITS=8'",
"'-D CST816S_IO_I2C_CONFIG_LCD_PARAM_BITS=0'",
"'-D CST816S_IO_I2C_CONFIG_FLAGS_DC_LOW_ON_DATA=false'",
"'-D CST816S_IO_I2C_CONFIG_FLAGS_DISABLE_CONTROL_PHASE=true'",
"'-D CST816S_TOUCH_CONFIG_X_MAX=LCD_WIDTH'",
"'-D CST816S_TOUCH_CONFIG_Y_MAX=LCD_HEIGHT'",
"'-D CST816S_TOUCH_CONFIG_RST_GPIO_NUM=GPIO_NUM_NC'",
"'-D CST816S_TOUCH_CONFIG_INT_GPIO_NUM=GPIO_NUM_NC'",
"'-D CST816S_TOUCH_CONFIG_LEVELS_RESET=0'",
"'-D CST816S_TOUCH_CONFIG_LEVELS_INTERRUPT=0'",
"'-D TOUCH_SWAP_XY=false'",
"'-D TOUCH_SWAP_X=false'",
"'-D TOUCH_SWAP_Y=false'",
"'-D BOARD_HAS_TF'",
"'-D TF_CS=5'",
"'-D TF_SPI_MOSI=23'",
"'-D TF_SPI_SCLK=18'",
"'-D TF_SPI_MISO=19'",
"'-D BOARD_HAS_SPEAK'",
"'-D SPEAK=26'",
"-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_SMARTDISPLAY=1",
"-DCYD_SCREEN_DISABLE_TOUCH_CALIBRATION=1",
"-DCYD_SCREEN_DISABLE_INVERT_COLORS=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-2432S022C",
"upload": {
"flash_size": "4MB",
"maximum_ram_size": 327680,
"maximum_size": 4194304,
"require_upload_port": true,
"speed": 460800
},
"url": "https://www.aliexpress.com/item/1005006284154750.html",
"vendor": "Sunton"
}

View File

@@ -0,0 +1,126 @@
{
"build": {
"arduino": {
"ldscript": "esp32_out.ld"
},
"core": "esp32",
"extra_flags": [
"'-D ARDUINO_ESP32_DEV'",
"'-D ESP32_2432S028Rv3'",
"'-D LCD_WIDTH=240'",
"'-D LCD_HEIGHT=320'",
"'-D LVGL_BUFFER_PIXELS=(LCD_WIDTH*LCD_HEIGHT/4)'",
"'-D LVGL_BUFFER_MALLOC_FLAGS=(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)'",
"'-D BCKL=21'",
"'-D LCD_ST7789_SPI'",
"'-D ST7789_SPI_HOST=SPI2_HOST'",
"'-D ST7789_SPI_DMA_CHANNEL=SPI_DMA_CH_AUTO'",
"'-D ST7789_SPI_BUS_MOSI_IO_NUM=13'",
"'-D ST7789_SPI_BUS_MISO_IO_NUM=GPIO_NUM_NC'",
"'-D ST7789_SPI_BUS_SCLK_IO_NUM=14'",
"'-D ST7789_SPI_BUS_QUADWP_IO_NUM=GPIO_NUM_NC'",
"'-D ST7789_SPI_BUS_QUADHD_IO_NUM=GPIO_NUM_NC'",
"'-D ST7789_SPI_BUS_MAX_TRANSFER_SZ=0'",
"'-D ST7789_SPI_BUS_FLAGS=0'",
"'-D ST7789_SPI_BUS_INTR_FLAGS=0'",
"'-D ST7789_SPI_CONFIG_CS_GPIO_NUM=15'",
"'-D ST7789_SPI_CONFIG_DC_GPIO_NUM=2'",
"'-D ST7789_SPI_CONFIG_SPI_MODE=SPI_MODE3'",
"'-D ST7789_SPI_CONFIG_PCLK_HZ=55000000'",
"'-D ST7789_SPI_CONFIG_TRANS_QUEUE_DEPTH=10'",
"'-D ST7789_SPI_CONFIG_LCD_CMD_BITS=8'",
"'-D ST7789_SPI_CONFIG_LCD_PARAM_BITS=8'",
"'-D ST7789_SPI_CONFIG_FLAGS_DC_AS_CMD_PHASE=false'",
"'-D ST7789_SPI_CONFIG_FLAGS_DC_LOW_ON_DATA=false'",
"'-D ST7789_SPI_CONFIG_FLAGS_OCTAL_MODE=false'",
"'-D ST7789_SPI_CONFIG_FLAGS_LSB_FIRST=false'",
"'-D ST7789_DEV_CONFIG_RESET_GPIO_NUM=GPIO_NUM_NC'",
"'-D ST7789_DEV_CONFIG_COLOR_SPACE=ESP_LCD_COLOR_SPACE_RGB'",
"'-D ST7789_DEV_CONFIG_BITS_PER_PIXEL=16'",
"'-D ST7789_DEV_CONFIG_FLAGS_RESET_ACTIVE_HIGH=false'",
"'-D ST7789_DEV_CONFIG_VENDOR_CONFIG=NULL'",
"'-D LCD_SWAP_XY=false'",
"'-D LCD_MIRROR_X=false'",
"'-D LCD_MIRROR_Y=false'",
"'-D BOARD_HAS_TOUCH'",
"'-D TOUCH_XPT2046_SPI'",
"'-D XPT2046_SPI_HOST=SPI3_HOST'",
"'-D XPT2046_SPI_DMA_CHANNEL=SPI_DMA_CH_AUTO'",
"'-D XPT2046_SPI_BUS_MOSI_IO_NUM=32'",
"'-D XPT2046_SPI_BUS_MISO_IO_NUM=39'",
"'-D XPT2046_SPI_BUS_SCLK_IO_NUM=25'",
"'-D XPT2046_SPI_BUS_QUADWP_IO_NUM=GPIO_NUM_NC'",
"'-D XPT2046_SPI_BUS_QUADHD_IO_NUM=GPIO_NUM_NC'",
"'-D XPT2046_SPI_CONFIG_CS_GPIO_NUM=33'",
"'-D XPT2046_SPI_CONFIG_DC_GPIO_NUM=GPIO_NUM_NC'",
"'-D XPT2046_SPI_CONFIG_SPI_MODE=SPI_MODE0'",
"'-D XPT2046_SPI_CONFIG_PCLK_HZ=2000000'",
"'-D XPT2046_SPI_CONFIG_TRANS_QUEUE_DEPTH=3'",
"'-D XPT2046_SPI_CONFIG_LCD_CMD_BITS=8'",
"'-D XPT2046_SPI_CONFIG_LCD_PARAM_BITS=8'",
"'-D XPT2046_SPI_CONFIG_FLAGS_DC_AS_CMD_PHASE=false'",
"'-D XPT2046_SPI_CONFIG_FLAGS_DC_LOW_ON_DATA=false'",
"'-D XPT2046_SPI_CONFIG_FLAGS_OCTAL_MODE=false'",
"'-D XPT2046_SPI_CONFIG_FLAGS_LSB_FIRST=false'",
"'-D XPT2046_TOUCH_CONFIG_X_MAX=LCD_WIDTH'",
"'-D XPT2046_TOUCH_CONFIG_Y_MAX=LCD_HEIGHT'",
"'-D XPT2046_TOUCH_CONFIG_RST_GPIO_NUM=GPIO_NUM_NC'",
"'-D XPT2046_TOUCH_CONFIG_INT_GPIO_NUM=36'",
"'-D XPT2046_TOUCH_CONFIG_LEVELS_RESET=0'",
"'-D XPT2046_TOUCH_CONFIG_LEVELS_INTERRUPT=0'",
"'-D TOUCH_SWAP_XY=true'",
"'-D TOUCH_SWAP_X=true'",
"'-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'",
"-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_SMARTDISPLAY=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-2432S028Rv3",
"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"
}

View File

@@ -16,9 +16,6 @@
"-DTFT_DC=2", "-DTFT_DC=2",
"-DTFT_RST=-1", "-DTFT_RST=-1",
"-DLOAD_GCLD=1", "-DLOAD_GCLD=1",
"-DLOAD_FONT2=1",
"-DLOAD_GFXFF=1",
"-DSMOOTH_FONT=1",
"-DSPI_FREQUENCY=55000000", "-DSPI_FREQUENCY=55000000",
"-DSPI_READ_FREQUENCY=20000000", "-DSPI_READ_FREQUENCY=20000000",
"-DSPI_TOUCH_FREQUENCY=2500000", "-DSPI_TOUCH_FREQUENCY=2500000",

View File

@@ -21,7 +21,7 @@
"'-D ST7796_SPI_CONFIG_CS_GPIO_NUM=15'", "'-D ST7796_SPI_CONFIG_CS_GPIO_NUM=15'",
"'-D ST7796_SPI_CONFIG_DC_GPIO_NUM=2'", "'-D ST7796_SPI_CONFIG_DC_GPIO_NUM=2'",
"'-D ST7796_SPI_CONFIG_SPI_MODE=SPI_MODE0'", "'-D ST7796_SPI_CONFIG_SPI_MODE=SPI_MODE0'",
"'-D ST7796_SPI_CONFIG_PCLK_HZ=24000000'", "'-D ST7796_SPI_CONFIG_PCLK_HZ=80000000'",
"'-D ST7796_SPI_CONFIG_TRANS_QUEUE_DEPTH=10'", "'-D ST7796_SPI_CONFIG_TRANS_QUEUE_DEPTH=10'",
"'-D ST7796_SPI_CONFIG_LCD_CMD_BITS=8'", "'-D ST7796_SPI_CONFIG_LCD_CMD_BITS=8'",
"'-D ST7796_SPI_CONFIG_LCD_PARAM_BITS=8'", "'-D ST7796_SPI_CONFIG_LCD_PARAM_BITS=8'",
@@ -74,7 +74,17 @@
"'-D BOARD_HAS_CDS'", "'-D BOARD_HAS_CDS'",
"'-D CDS=34'", "'-D CDS=34'",
"'-D BOARD_HAS_SPEAK'", "'-D BOARD_HAS_SPEAK'",
"'-D SPEAK=26'" "'-D SPEAK=26'",
"-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",
"-DCYD_SCREEN_DISABLE_TOUCH_CALIBRATION=1",
"-DCYD_SCREEN_DISABLE_INVERT_COLORS=1"
], ],
"f_cpu": "240000000L", "f_cpu": "240000000L",
"f_flash": "40000000L", "f_flash": "40000000L",

View File

@@ -16,9 +16,6 @@
"-DTFT_DC=2", "-DTFT_DC=2",
"-DTFT_RST=-1", "-DTFT_RST=-1",
"-DLOAD_GCLD=1", "-DLOAD_GCLD=1",
"-DLOAD_FONT2=1",
"-DLOAD_GFXFF=1",
"-DSMOOTH_FONT=1",
"-DSPI_FREQUENCY=80000000", "-DSPI_FREQUENCY=80000000",
"-DSPI_READ_FREQUENCY=20000000", "-DSPI_READ_FREQUENCY=20000000",
"-DSPI_TOUCH_FREQUENCY=2500000", "-DSPI_TOUCH_FREQUENCY=2500000",

View File

@@ -15,11 +15,17 @@ except:
version = "Unknown" version = "Unknown"
flag = "-D REPO_VERSION=\\\"" + version + "\\\"" flag = "-D REPO_VERSION=\\\"" + version + "\\\""
dev_flag = "-DREPO_DEVELOPMENT=1"
print(f"Version: {version}") print(f"Version: {version}")
print(f"Flag: {flag}") print(f"Flag: {flag}")
flags = [flag]
if ('(' in version):
flags.append(dev_flag)
Import("env") Import("env")
env.Append( env.Append(
BUILD_FLAGS=[flag] BUILD_FLAGS=flags
) )

View File

@@ -43,17 +43,8 @@ lib_deps =
bblanchon/ArduinoJson@^7.0.0 bblanchon/ArduinoJson@^7.0.0
plageoj/UrlEncode@^1.0.1 plageoj/UrlEncode@^1.0.1
# Terribly slow. Only use for development [env:esp32-3248S035C-smartdisplay]
# [env:esp32-3248S035C-smartdisplay] board = esp32-3248S035C-smartdisplay
# board = esp32-3248S035C-smartdisplay
# build_flags = [env:esp32-2432S028R-smartdisplay]
# -DLV_CONF_PATH="../../../../src/conf/lv_conf.h" board = esp32-2432S028R-smartdisplay
# -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

View File

@@ -5,6 +5,12 @@
#define CONFIG_VERSION 4 #define CONFIG_VERSION 4
enum {
REMAINING_TIME_CALC_PERCENTAGE = 0,
REMAINING_TIME_CALC_INTERPOLATED = 1,
REMAINING_TIME_CALC_SLICER = 2,
};
typedef struct _GLOBAL_CONFIG { typedef struct _GLOBAL_CONFIG {
unsigned char version; unsigned char version;
union { union {
@@ -21,6 +27,10 @@ typedef struct _GLOBAL_CONFIG {
bool rotateScreen : 1; bool rotateScreen : 1;
bool onDuringPrint : 1; bool onDuringPrint : 1;
bool autoOtaUpdate : 1; bool autoOtaUpdate : 1;
unsigned char remaining_time_calc_mode : 2;
// Internal
bool auth_configured : 1;
}; };
}; };
float screenCalXOffset; float screenCalXOffset;
@@ -40,6 +50,8 @@ typedef struct _GLOBAL_CONFIG {
unsigned short hotend_presets[3]; unsigned short hotend_presets[3];
unsigned short bed_presets[3]; unsigned short bed_presets[3];
char klipper_auth[33];
} GLOBAL_CONFIG; } GLOBAL_CONFIG;
typedef struct _COLOR_DEF { typedef struct _COLOR_DEF {

View File

@@ -242,8 +242,12 @@
* Others * Others
*-----------*/ *-----------*/
#ifndef REPO_DEVELOPMENT
#define REPO_DEVELOPMENT 0
#endif
/*1: Show CPU usage and FPS count*/ /*1: Show CPU usage and FPS count*/
#define LV_USE_PERF_MONITOR 0 #define LV_USE_PERF_MONITOR REPO_DEVELOPMENT
#if LV_USE_PERF_MONITOR #if LV_USE_PERF_MONITOR
#define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT #define LV_USE_PERF_MONITOR_POS LV_ALIGN_BOTTOM_RIGHT
#endif #endif
@@ -497,7 +501,7 @@
#define LV_USE_MSG 1 #define LV_USE_MSG 1
#define LV_USE_CHART 0 #define LV_USE_CHART 1
#define LV_USE_COLORWHEEL 0 #define LV_USE_COLORWHEEL 0

View File

@@ -50,6 +50,9 @@ void send_gcode(bool wait, const char *gcode)
HTTPClient client; HTTPClient client;
client.begin(buff); client.begin(buff);
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
if (!wait) if (!wait)
{ {
client.setTimeout(1000); client.setTimeout(1000);
@@ -65,6 +68,63 @@ void send_gcode(bool wait, const char *gcode)
} }
} }
int get_slicer_time_estimate_s()
{
if (printer.state == PRINTER_STATE_IDLE)
return 0;
delay(10);
char buff[256] = {};
sprintf(buff, "http://%s:%d/server/files/metadata?filename=%s", global_config.klipperHost, global_config.klipperPort, urlEncode(printer.print_filename).c_str());
HTTPClient client;
client.useHTTP10(true);
client.begin(buff);
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
int httpCode = client.GET();
if (httpCode != 200)
return 0;
JsonDocument doc;
deserializeJson(doc, client.getStream());
int time_estimate_s = doc["result"]["estimated_time"];
Serial.printf("Got slicer time estimate: %ds\n", time_estimate_s);
return time_estimate_s;
}
void move_printer(const char* axis, float amount, bool relative) {
if (!printer.homed_axis || printer.state == PRINTER_STATE_PRINTING)
return;
char gcode[64];
const char* extra = (amount > 0) ? "+" : "";
bool absolute_coords = printer.absolute_coords;
if (absolute_coords && relative) {
send_gcode(true, "G91");
}
else if (!absolute_coords && !relative) {
send_gcode(true, "G90");
}
sprintf(gcode, "G1 %s%s%.3f F6000", axis, extra, amount);
send_gcode(true, gcode);
if (absolute_coords && relative) {
send_gcode(true, "G90");
}
else if (!absolute_coords && !relative) {
send_gcode(true, "G91");
}
}
int last_slicer_time_query = -15000;
void fetch_printer_data() void fetch_printer_data()
{ {
freeze_request_thread(); freeze_request_thread();
@@ -73,6 +133,10 @@ void fetch_printer_data()
HTTPClient client; HTTPClient client;
client.useHTTP10(true); client.useHTTP10(true);
client.begin(buff); client.begin(buff);
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
int httpCode = client.GET(); int httpCode = client.GET();
delay(10); delay(10);
if (httpCode == 200) if (httpCode == 200)
@@ -122,6 +186,7 @@ void fetch_printer_data()
printer.extruder_target_temp = status["extruder"]["target"]; printer.extruder_target_temp = status["extruder"]["target"];
bool can_extrude = status["extruder"]["can_extrude"]; bool can_extrude = status["extruder"]["can_extrude"];
printer.pressure_advance = status["extruder"]["pressure_advance"]; printer.pressure_advance = status["extruder"]["pressure_advance"];
printer.smooth_time = status["extruder"]["smooth_time"];
printer.can_extrude = can_extrude == true; printer.can_extrude = can_extrude == true;
} }
@@ -175,7 +240,11 @@ void fetch_printer_data()
const char *state = status["print_stats"]["state"]; const char *state = status["print_stats"]["state"];
if (strcmp(state, "printing") == 0) if (state == nullptr)
{
printer_state = PRINTER_STATE_ERROR;
}
else if (strcmp(state, "printing") == 0)
{ {
printer_state = PRINTER_STATE_PRINTING; printer_state = PRINTER_STATE_PRINTING;
} }
@@ -194,7 +263,36 @@ void fetch_printer_data()
if (printer.state == PRINTER_STATE_PRINTING && printer.print_progress > 0) if (printer.state == PRINTER_STATE_PRINTING && printer.print_progress > 0)
{ {
printer.remaining_time_s = (printer.elapsed_time_s / printer.print_progress) - printer.elapsed_time_s; float remaining_time_s_percentage = (printer.elapsed_time_s / printer.print_progress) - printer.elapsed_time_s;
float remaining_time_s_slicer = 0;
if (printer.slicer_estimated_print_time_s > 0)
{
remaining_time_s_slicer = printer.slicer_estimated_print_time_s - printer.elapsed_time_s;
}
if (remaining_time_s_slicer <= 0 || global_config.remaining_time_calc_mode == REMAINING_TIME_CALC_PERCENTAGE)
{
printer.remaining_time_s = remaining_time_s_percentage;
}
else if (global_config.remaining_time_calc_mode == REMAINING_TIME_CALC_INTERPOLATED)
{
printer.remaining_time_s = remaining_time_s_percentage * printer.print_progress + remaining_time_s_slicer * (1 - printer.print_progress);
}
else if (global_config.remaining_time_calc_mode == REMAINING_TIME_CALC_SLICER)
{
printer.remaining_time_s = remaining_time_s_slicer;
}
}
if (printer.remaining_time_s < 0)
{
printer.remaining_time_s = 0;
}
if (printer.state == PRINTER_STATE_IDLE)
{
printer.slicer_estimated_print_time_s = 0;
} }
lv_msg_send(DATA_PRINTER_DATA, &printer); lv_msg_send(DATA_PRINTER_DATA, &printer);
@@ -206,6 +304,13 @@ void fetch_printer_data()
lv_msg_send(DATA_PRINTER_STATE, &printer); lv_msg_send(DATA_PRINTER_STATE, &printer);
} }
if (printer.state == PRINTER_STATE_PRINTING && millis() - last_slicer_time_query > 30000 && printer.slicer_estimated_print_time_s <= 0)
{
delay(10);
last_slicer_time_query = millis();
printer.slicer_estimated_print_time_s = get_slicer_time_estimate_s();
}
unfreeze_render_thread(); unfreeze_render_thread();
} }
else else

View File

@@ -23,8 +23,8 @@ typedef struct _Printer {
float elapsed_time_s; float elapsed_time_s;
float remaining_time_s; float remaining_time_s;
float filament_used_mm; float filament_used_mm;
char* print_filename; // 0 -> 1 char* print_filename;
float print_progress; float print_progress; // 0 -> 1
float fan_speed; // 0 -> 1 float fan_speed; // 0 -> 1
float gcode_offset[3]; float gcode_offset[3];
float speed_mult; float speed_mult;
@@ -32,7 +32,9 @@ typedef struct _Printer {
int total_layers; int total_layers;
int current_layer; int current_layer;
float pressure_advance; float pressure_advance;
float smooth_time;
int feedrate_mm_per_s; int feedrate_mm_per_s;
int slicer_estimated_print_time_s;
} Printer; } Printer;
extern Printer printer; extern Printer printer;
@@ -45,6 +47,7 @@ extern int klipper_request_consecutive_fail_count;
void data_loop(); void data_loop();
void data_setup(); void data_setup();
void send_gcode(bool wait, const char* gcode); void send_gcode(bool wait, const char* gcode);
void move_printer(const char* axis, float amount, bool relative);
void freeze_request_thread(); void freeze_request_thread();
void unfreeze_request_thread(); void unfreeze_request_thread();

View File

@@ -25,71 +25,6 @@ static lv_color_t buf[CYD_SCREEN_HEIGHT_PX * CYD_SCREEN_WIDTH_PX / 10];
TFT_eSPI tft = TFT_eSPI(); TFT_eSPI tft = TFT_eSPI();
TS_Point touchscreen_point()
{
TS_Point p = touchscreen.getPoint();
p.x = round((p.x * global_config.screenCalXMult) + global_config.screenCalXOffset);
p.y = round((p.y * global_config.screenCalYMult) + global_config.screenCalYOffset);
return p;
}
void touchscreen_calibrate(bool force)
{
if (global_config.screenCalibrated && !force)
{
return;
}
tft.fillScreen(TFT_BLACK);
tft.setCursor(20, 140);
tft.setTextColor(TFT_WHITE, TFT_BLACK);
tft.setTextSize(2);
tft.println("Calibrate Screen");
TS_Point p;
int16_t x1, y1, x2, y2;
while (touchscreen.touched())
;
tft.drawFastHLine(0, 10, 20, ILI9341_WHITE);
tft.drawFastVLine(10, 0, 20, ILI9341_WHITE);
while (!touchscreen.touched())
;
delay(50);
p = touchscreen.getPoint();
x1 = p.x;
y1 = p.y;
tft.drawFastHLine(0, 10, 20, ILI9341_BLACK);
tft.drawFastVLine(10, 0, 20, ILI9341_BLACK);
delay(500);
while (touchscreen.touched())
;
tft.drawFastHLine(300, 230, 20, ILI9341_WHITE);
tft.drawFastVLine(310, 220, 20, ILI9341_WHITE);
while (!touchscreen.touched())
;
delay(50);
p = touchscreen.getPoint();
x2 = p.x;
y2 = p.y;
tft.drawFastHLine(300, 230, 20, ILI9341_BLACK);
tft.drawFastVLine(310, 220, 20, ILI9341_BLACK);
int16_t xDist = 320 - 20;
int16_t yDist = 240 - 20;
global_config.screenCalXMult = (float)xDist / (float)(x2 - x1);
global_config.screenCalXOffset = 10.0 - ((float)x1 * global_config.screenCalXMult);
global_config.screenCalYMult = (float)yDist / (float)(y2 - y1);
global_config.screenCalYOffset = 10.0 - ((float)y1 * global_config.screenCalYMult);
global_config.screenCalibrated = true;
WriteGlobalConfig();
}
void screen_setBrightness(byte brightness) void screen_setBrightness(byte brightness)
{ {
// calculate duty, 4095 from 2 ^ 12 - 1 // calculate duty, 4095 from 2 ^ 12 - 1
@@ -116,7 +51,7 @@ void screen_lv_touchRead(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{ {
if (touchscreen.tirqTouched() && touchscreen.touched()) if (touchscreen.tirqTouched() && touchscreen.touched())
{ {
TS_Point p = touchscreen_point(); TS_Point p = touchscreen.getPoint();
data->state = LV_INDEV_STATE_PR; data->state = LV_INDEV_STATE_PR;
data->point.x = p.x; data->point.x = p.x;
data->point.y = p.y; data->point.y = p.y;
@@ -152,8 +87,6 @@ void screen_setup()
touchscreen_spi.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS); touchscreen_spi.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
touchscreen.begin(touchscreen_spi); touchscreen.begin(touchscreen_spi);
touchscreen_calibrate(false);
lv_disp_draw_buf_init(&draw_buf, buf, NULL, CYD_SCREEN_HEIGHT_PX * CYD_SCREEN_WIDTH_PX / 10); lv_disp_draw_buf_init(&draw_buf, buf, NULL, CYD_SCREEN_HEIGHT_PX * CYD_SCREEN_WIDTH_PX / 10);
/*Initialize the display*/ /*Initialize the display*/

View File

@@ -7,11 +7,8 @@
#include "lvgl.h" #include "lvgl.h"
#include "../lv_setup.h" #include "../lv_setup.h"
void touchscreen_calibrate(bool force) typedef void (*lv_disp_drv_t_flush_cb)(_lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p);
{ static lv_disp_drv_t_flush_cb original_screen_driver;
// TODO: Stubbed
return;
}
void screen_setBrightness(byte brightness) void screen_setBrightness(byte brightness)
{ {
@@ -19,13 +16,34 @@ void screen_setBrightness(byte brightness)
} }
void set_invert_display(){ void set_invert_display(){
// Stubbed lv_obj_invalidate(lv_scr_act());
}
void lv_screen_intercept(_lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p)
{
if (global_config.invertColors) {
uint32_t w = (area->x2 - area->x1 + 1);
uint32_t h = (area->y2 - area->y1 + 1);
for (int i = 0 ; i < w * h; i++){
color_p[i].full ^= 0xFFFF;
}
}
original_screen_driver(disp_drv, area, color_p);
} }
void screen_setup() void screen_setup()
{ {
smartdisplay_init(); smartdisplay_init();
#ifndef CYD_SCREEN_DISABLE_INVERT_COLORS
if (original_screen_driver == NULL){
original_screen_driver = lv_disp_get_default()->driver->flush_cb;
lv_disp_get_default()->driver->flush_cb = lv_screen_intercept;
}
#endif // CYD_SCREEN_DISABLE_INVERT_COLORS
lv_disp_set_rotation(lv_disp_get_default(), (global_config.rotateScreen) ? LV_DISP_ROT_270 : LV_DISP_ROT_90); lv_disp_set_rotation(lv_disp_get_default(), (global_config.rotateScreen) ? LV_DISP_ROT_270 : LV_DISP_ROT_90);
} }

View File

@@ -33,6 +33,10 @@ FILESYSTEM_FILE* get_files(int limit){
client.useHTTP10(true); client.useHTTP10(true);
client.setTimeout(5000); client.setTimeout(5000);
client.begin(buff); client.begin(buff);
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
int httpCode = client.GET(); int httpCode = client.GET();
auto timer_parse = millis(); auto timer_parse = millis();

View File

@@ -2,6 +2,7 @@
#include "screen_driver.h" #include "screen_driver.h"
#include "../conf/global_config.h" #include "../conf/global_config.h"
#include "lvgl.h" #include "lvgl.h"
#include "../ui/ui_utils.h"
#include <Esp.h> #include <Esp.h>
#ifndef CPU_FREQ_HIGH #ifndef CPU_FREQ_HIGH
@@ -13,8 +14,131 @@
typedef void (*lv_indev_drv_read_cb_t)(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data); typedef void (*lv_indev_drv_read_cb_t)(struct _lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
bool isScreenInSleep = false; bool is_screen_in_sleep = false;
lv_timer_t *screenSleepTimer; lv_timer_t *screen_sleep_timer;
lv_coord_t point[2] = {0};
static lv_indev_drv_read_cb_t original_touch_driver = NULL;
void lv_touch_intercept_calibration(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
original_touch_driver(indev_driver, data);
if (data->state == LV_INDEV_STATE_PR){
point[0] = data->point.x;
point[1] = data->point.y;
while (data->state == LV_INDEV_STATE_PR){
original_touch_driver(indev_driver, data);
delay(20);
}
}
data->state = LV_INDEV_STATE_REL;
}
void lv_touch_intercept(lv_indev_drv_t *indev_driver, lv_indev_data_t *data)
{
original_touch_driver(indev_driver, data);
if (data->state == LV_INDEV_STATE_PR) {
if (is_screen_asleep()) {
while (data->state == LV_INDEV_STATE_PR) {
original_touch_driver(indev_driver, data);
delay(20);
}
data->state = LV_INDEV_STATE_REL;
}
screen_timer_wake();
#ifndef CYD_SCREEN_DISABLE_TOUCH_CALIBRATION
data->point.x = round((data->point.x * global_config.screenCalXMult) + global_config.screenCalXOffset);
data->point.y = round((data->point.y * global_config.screenCalYMult) + global_config.screenCalYOffset);
#endif // CYD_SCREEN_DISABLE_TOUCH_CALIBRATION
}
}
void lv_do_calibration(){
if (global_config.screenCalibrated){
return;
}
lv_indev_t * display_driver = lv_indev_get_next(NULL);
display_driver->driver->read_cb = lv_touch_intercept_calibration;
lv_obj_clean(lv_scr_act());
lv_obj_clear_flag(lv_scr_act(), LV_OBJ_FLAG_SCROLLABLE);
lv_obj_t * label = lv_label_create(lv_scr_act());
lv_label_set_text(label, "Calibrate Screen");
lv_obj_align(label, LV_ALIGN_CENTER, 0, 0);
lv_obj_t * line = lv_line_create(lv_scr_act());
static lv_point_t line_points_x[] = { {0, 10}, {21, 10} };
static lv_point_t line_points_y[] = { {10, 0}, {10, 21} };
lv_line_set_points(line, line_points_x, 2);
lv_obj_align(line, LV_ALIGN_TOP_LEFT, 0, 0);
lv_obj_set_style_line_width(line, 1, 0);
lv_obj_t * line2 = lv_line_create(lv_scr_act());
lv_line_set_points(line2, line_points_y, 2);
lv_obj_align(line2, LV_ALIGN_TOP_LEFT, 0, 0);
lv_obj_set_style_line_width(line2, 1, 0);
while (true){
lv_timer_handler();
lv_task_handler();
if (point[0] != 0 && point[1] != 0){
break;
}
}
lv_coord_t x1 = point[0];
lv_coord_t y1 = point[1];
point[0] = 0;
point[1] = 0;
lv_obj_del(line);
lv_obj_del(line2);
line = lv_line_create(lv_scr_act());
lv_line_set_points(line, line_points_x, 2);
lv_obj_align(line, LV_ALIGN_BOTTOM_RIGHT, 1, -10);
lv_obj_set_style_line_width(line, 1, 0);
line = lv_line_create(lv_scr_act());
lv_line_set_points(line, line_points_y, 2);
lv_obj_align(line, LV_ALIGN_BOTTOM_RIGHT, -10, 1);
while (true){
lv_timer_handler();
lv_task_handler();
if (point[0] != 0 && point[1] != 0){
break;
}
}
lv_coord_t x2 = point[0];
lv_coord_t y2 = point[1];
int16_t xDist = CYD_SCREEN_WIDTH_PX - 20;
int16_t yDist = CYD_SCREEN_HEIGHT_PX - 20;
global_config.screenCalXMult = (float)xDist / (float)(x2 - x1);
global_config.screenCalXOffset = 10.0 - ((float)x1 * global_config.screenCalXMult);
global_config.screenCalYMult = (float)yDist / (float)(y2 - y1);
global_config.screenCalYOffset = 10.0 - ((float)y1 * global_config.screenCalYMult);
global_config.screenCalibrated = true;
WriteGlobalConfig();
lv_obj_clean(lv_scr_act());
}
void set_screen_brightness() void set_screen_brightness()
{ {
@@ -27,13 +151,13 @@ void set_screen_brightness()
void screen_timer_wake() void screen_timer_wake()
{ {
#ifndef CYD_SCREEN_DISABLE_TIMEOUT #ifndef CYD_SCREEN_DISABLE_TIMEOUT
lv_timer_reset(screenSleepTimer); lv_timer_reset(screen_sleep_timer);
if (!isScreenInSleep){ if (!is_screen_in_sleep){
return; return;
} }
isScreenInSleep = false; is_screen_in_sleep = false;
set_screen_brightness(); set_screen_brightness();
// Reset cpu freq // Reset cpu freq
@@ -46,7 +170,7 @@ void screen_timer_sleep(lv_timer_t *timer)
{ {
#ifndef CYD_SCREEN_DISABLE_TIMEOUT #ifndef CYD_SCREEN_DISABLE_TIMEOUT
screen_setBrightness(0); screen_setBrightness(0);
isScreenInSleep = true; is_screen_in_sleep = true;
// Screen is off, no need to make the cpu run fast, the user won't notice ;) // Screen is off, no need to make the cpu run fast, the user won't notice ;)
setCpuFrequencyMhz(CPU_FREQ_LOW); setCpuFrequencyMhz(CPU_FREQ_LOW);
@@ -56,23 +180,23 @@ void screen_timer_sleep(lv_timer_t *timer)
void screen_timer_setup() void screen_timer_setup()
{ {
screenSleepTimer = lv_timer_create(screen_timer_sleep, global_config.screenTimeout * 1000 * 60, NULL); screen_sleep_timer = lv_timer_create(screen_timer_sleep, global_config.screenTimeout * 1000 * 60, NULL);
lv_timer_pause(screenSleepTimer); lv_timer_pause(screen_sleep_timer);
} }
void screen_timer_start() void screen_timer_start()
{ {
lv_timer_resume(screenSleepTimer); lv_timer_resume(screen_sleep_timer);
} }
void screen_timer_stop() void screen_timer_stop()
{ {
lv_timer_pause(screenSleepTimer); lv_timer_pause(screen_sleep_timer);
} }
void screen_timer_period(unsigned int period) void screen_timer_period(unsigned int period)
{ {
lv_timer_set_period(screenSleepTimer, period); lv_timer_set_period(screen_sleep_timer, period);
} }
void set_screen_timer_period() void set_screen_timer_period()
@@ -100,41 +224,28 @@ void set_color_scheme()
lv_disp_set_theme(dispp, theme); 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() void lv_setup()
{ {
screen_timer_setup(); lv_indev_t * display_driver = lv_indev_get_next(NULL);
screen_timer_start();
if (original_touch_driver == NULL)
{
original_touch_driver = display_driver->driver->read_cb;
}
set_color_scheme(); set_color_scheme();
if (original_driver != NULL) #ifndef CYD_SCREEN_DISABLE_TOUCH_CALIBRATION
return; lv_do_calibration();
#endif // CYD_SCREEN_DISABLE_TOUCH_CALIBRATION
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; display_driver->driver->read_cb = lv_touch_intercept;
screen_timer_setup();
screen_timer_start();
} }
bool is_screen_asleep() bool is_screen_asleep()
{ {
return isScreenInSleep; return is_screen_in_sleep;
} }

View File

@@ -18,6 +18,10 @@ static void _macros_query_internal(){
HTTPClient client; HTTPClient client;
client.useHTTP10(true); client.useHTTP10(true);
client.begin(url.c_str()); client.begin(url.c_str());
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
int httpCode = client.GET(); int httpCode = client.GET();
if (httpCode == 200){ if (httpCode == 200){
JsonDocument doc; JsonDocument doc;
@@ -42,23 +46,32 @@ static void _macros_query_internal(){
} }
} }
void power_devices_clear(){
for (int i = 0; i < power_devices_count; i++){
free(power_devices[i]);
}
power_devices_count = 0;
}
void _power_devices_query_internal(){ void _power_devices_query_internal(){
String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/machine/device_power/devices"; String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/machine/device_power/devices";
HTTPClient client; HTTPClient client;
client.useHTTP10(true); client.useHTTP10(true);
client.setTimeout(500); client.setTimeout(500);
client.setConnectTimeout(1000);
client.begin(url.c_str()); client.begin(url.c_str());
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
int httpCode = client.GET(); int httpCode = client.GET();
if (httpCode == 200){ if (httpCode == 200){
JsonDocument doc; JsonDocument doc;
deserializeJson(doc, client.getStream()); deserializeJson(doc, client.getStream());
auto result = doc["result"]["devices"].as<JsonArray>(); auto result = doc["result"]["devices"].as<JsonArray>();
for (int i = 0; i < power_devices_count; i++){ power_devices_clear();
free(power_devices[i]);
}
power_devices_count = 0;
for (auto i : result){ for (auto i : result){
const char * device_name = i["device"]; const char * device_name = i["device"];
@@ -85,6 +98,10 @@ bool set_power_state(const char* device_name, bool state) {
HTTPClient client; HTTPClient client;
client.useHTTP10(true); client.useHTTP10(true);
client.begin(url.c_str()); client.begin(url.c_str());
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
if (client.POST("") != 200) if (client.POST("") != 200)
return false; return false;

View File

@@ -16,3 +16,4 @@ POWERQUERY power_devices_query();
void macros_query_setup(); void macros_query_setup();
bool set_power_state(const char* device_name, bool state); bool set_power_state(const char* device_name, bool state);
void _power_devices_query_internal(); void _power_devices_query_internal();
void power_devices_clear();

View File

@@ -1,7 +1,6 @@
#pragma once #pragma once
// Adapted from https://github.com/xperiments-in/xtouch/blob/main/src/devices/2.8/screen.h // Adapted from https://github.com/xperiments-in/xtouch/blob/main/src/devices/2.8/screen.h
void touchscreen_calibrate(bool force = false);
void screen_setBrightness(unsigned char brightness); void screen_setBrightness(unsigned char brightness);
void screen_setup(); void screen_setup();
void set_invert_display(); void set_invert_display();

View File

@@ -29,20 +29,35 @@ static const lv_btnmatrix_ctrl_t kb_ctrl[] = {
void ip_init_inner(); void ip_init_inner();
bool verify_ip(){ enum connection_status_t {
CONNECT_FAIL = 0,
CONNECT_OK = 1,
CONNECT_AUTH_REQUIRED = 2,
};
connection_status_t verify_ip(){
HTTPClient client; HTTPClient client;
String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/printer/info"; String url = "http://" + String(global_config.klipperHost) + ":" + String(global_config.klipperPort) + "/printer/info";
int httpCode; int httpCode;
try { try {
Serial.println(url);
client.setTimeout(500); client.setTimeout(500);
client.setConnectTimeout(1000);
client.begin(url.c_str()); client.begin(url.c_str());
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
httpCode = client.GET(); httpCode = client.GET();
return httpCode == 200; Serial.printf("%d %s\n", httpCode, url.c_str());
if (httpCode == 401)
return CONNECT_AUTH_REQUIRED;
return httpCode == 200 ? CONNECT_OK : CONNECT_FAIL;
} }
catch (...) { catch (...) {
Serial.println("Failed to connect"); Serial.println("Failed to connect");
return false; return CONNECT_FAIL;
} }
} }
@@ -64,12 +79,19 @@ static void ta_event_cb(lv_event_t * e) {
strcpy(global_config.klipperHost, lv_textarea_get_text(hostEntry)); strcpy(global_config.klipperHost, lv_textarea_get_text(hostEntry));
global_config.klipperPort = atoi(lv_textarea_get_text(portEntry)); global_config.klipperPort = atoi(lv_textarea_get_text(portEntry));
if (verify_ip()) connection_status_t status = verify_ip();
if (status == CONNECT_OK)
{ {
global_config.ipConfigured = true; global_config.ipConfigured = true;
WriteGlobalConfig(); WriteGlobalConfig();
connect_ok = true; connect_ok = true;
} }
else if (status == CONNECT_AUTH_REQUIRED)
{
label = NULL;
global_config.ipConfigured = true;
WriteGlobalConfig();
}
else else
{ {
lv_label_set_text(label, "Failed to connect"); lv_label_set_text(label, "Failed to connect");
@@ -148,6 +170,77 @@ void redraw_connect_screen(){
} }
} }
static bool auth_entry_done = false;
static void keyboard_event_auth_entry(lv_event_t * e) {
lv_event_code_t code = lv_event_get_code(e);
lv_obj_t * ta = lv_event_get_target(e);
lv_obj_t * kb = (lv_obj_t *)lv_event_get_user_data(e);
if (code == LV_EVENT_READY)
{
const char * txt = lv_textarea_get_text(ta);
int len = strlen(txt);
if (len > 0)
{
global_config.auth_configured = true;
strcpy(global_config.klipper_auth, txt);
WriteGlobalConfig();
auth_entry_done = true;
}
}
else if (code == LV_EVENT_CANCEL)
{
auth_entry_done = true;
}
}
void handle_auth_entry(){
auth_entry_done = false;
global_config.klipper_auth[32] = 0;
lv_obj_clean(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(top_root);
lv_label_set_text(label, "Enter API Key");
lv_obj_set_width(label, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2);
lv_obj_t * keyboard = lv_keyboard_create(root);
lv_obj_t * passEntry = lv_textarea_create(top_root);
lv_textarea_set_max_length(passEntry, 32);
lv_textarea_set_one_line(passEntry, true);
if (global_config.auth_configured)
lv_textarea_set_text(passEntry, global_config.klipper_auth);
else
lv_textarea_set_text(passEntry, "");
lv_obj_set_width(passEntry, CYD_SCREEN_WIDTH_PX - CYD_SCREEN_GAP_PX * 2);
lv_obj_add_event_cb(passEntry, keyboard_event_auth_entry, LV_EVENT_ALL, keyboard);
lv_obj_set_flex_grow(passEntry, 1);
lv_keyboard_set_textarea(keyboard, passEntry);
lv_keyboard_set_map(keyboard, LV_KEYBOARD_MODE_USER_1, kb_map, kb_ctrl);
lv_keyboard_set_mode(keyboard, LV_KEYBOARD_MODE_USER_1);
while (!auth_entry_done) {
lv_timer_handler();
lv_task_handler();
}
redraw_connect_screen();
}
void ip_init_inner(){ void ip_init_inner(){
if (global_config.ipConfigured) { if (global_config.ipConfigured) {
redraw_connect_screen(); redraw_connect_screen();
@@ -203,6 +296,7 @@ int retry_count = 0;
void ip_init(){ void ip_init(){
connect_ok = false; connect_ok = false;
retry_count = 0; retry_count = 0;
int prev_power_device_count = 0;
ip_init_inner(); ip_init_inner();
@@ -212,22 +306,33 @@ void ip_init(){
lv_task_handler(); lv_task_handler();
if (!connect_ok && global_config.ipConfigured && (millis() - last_data_update_ip) > data_update_interval_ip){ if (!connect_ok && global_config.ipConfigured && (millis() - last_data_update_ip) > data_update_interval_ip){
connect_ok = verify_ip(); connection_status_t status = verify_ip();
connect_ok = status == CONNECT_OK;
last_data_update_ip = millis(); last_data_update_ip = millis();
retry_count++; retry_count++;
if (label != NULL){
String retry_count_text = "Connecting to Klipper (Try " + String(retry_count + 1) + ")"; String retry_count_text = "Connecting to Klipper (Try " + String(retry_count + 1) + ")";
lv_label_set_text(label, retry_count_text.c_str()); lv_label_set_text(label, retry_count_text.c_str());
}
if (status != CONNECT_AUTH_REQUIRED)
_power_devices_query_internal(); _power_devices_query_internal();
if (power_devices_query().count >= 1) else
handle_auth_entry();
if (power_devices_query().count != prev_power_device_count) {
prev_power_device_count = power_devices_query().count;
redraw_connect_screen(); redraw_connect_screen();
} }
} }
}
} }
void ip_ok(){ void ip_ok(){
if (klipper_request_consecutive_fail_count > 5){ if (klipper_request_consecutive_fail_count > 5){
freeze_request_thread(); freeze_request_thread();
power_devices_clear();
ip_init(); ip_init();
unfreeze_request_thread(); unfreeze_request_thread();
klipper_request_consecutive_fail_count = 0; klipper_request_consecutive_fail_count = 0;

View File

@@ -2,8 +2,8 @@
#include "panels/panel.h" #include "panels/panel.h"
#include "../core/data_setup.h" #include "../core/data_setup.h"
#include "nav_buttons.h" #include "nav_buttons.h"
#include <HTTPClient.h>
#include "ui_utils.h" #include "ui_utils.h"
#include <stdio.h>
static lv_style_t nav_button_style; static lv_style_t nav_button_style;
@@ -137,6 +137,9 @@ void nav_buttons_setup(unsigned char active_panel){
case 4: case 4:
macros_panel_init(panel); macros_panel_init(panel);
break; break;
case 5:
stats_panel_init(panel);
break;
} }
lv_msg_send(DATA_PRINTER_DATA, &printer); lv_msg_send(DATA_PRINTER_DATA, &printer);

View File

@@ -104,6 +104,7 @@ void macros_panel_init(lv_obj_t* panel) {
} }
lv_obj_t * root_panel = lv_create_empty_panel(panel); lv_obj_t * root_panel = lv_create_empty_panel(panel);
lv_obj_set_scrollbar_mode(root_panel, LV_SCROLLBAR_MODE_OFF);
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_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_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); lv_layout_flex_column(root_panel);

View File

@@ -1,48 +1,28 @@
#include "lvgl.h" #include "lvgl.h"
#include "panel.h" #include "panel.h"
#include "../../core/data_setup.h" #include "../../core/data_setup.h"
#include "../nav_buttons.h"
#include "../ui_utils.h" #include "../ui_utils.h"
#include <stdio.h> #include <stdio.h>
static bool last_homing_state = false; static bool last_homing_state = false;
static void move_printer(const char* axis, float amount) {
if (!printer.homed_axis || printer.state == PRINTER_STATE_PRINTING)
return;
char gcode[64];
const char* extra = (amount > 0) ? "+" : "";
bool absolute_coords = printer.absolute_coords;
if (absolute_coords) {
send_gcode(true, "G91");
}
sprintf(gcode, "G1 %s%s%.1f F6000", axis, extra, amount);
send_gcode(true, gcode);
if (absolute_coords) {
send_gcode(true, "G90");
}
}
static void x_line_button_press(lv_event_t * e) { static void x_line_button_press(lv_event_t * e) {
float* data_pointer = (float*)lv_event_get_user_data(e); float* data_pointer = (float*)lv_event_get_user_data(e);
float data = *data_pointer; float data = *data_pointer;
move_printer("X", data); move_printer("X", data, true);
} }
static void y_line_button_press(lv_event_t * e) { static void y_line_button_press(lv_event_t * e) {
float* data_pointer = (float*)lv_event_get_user_data(e); float* data_pointer = (float*)lv_event_get_user_data(e);
float data = *data_pointer; float data = *data_pointer;
move_printer("Y", data); move_printer("Y", data, true);
} }
static void z_line_button_press(lv_event_t * e) { static void z_line_button_press(lv_event_t * e) {
float* data_pointer = (float*)lv_event_get_user_data(e); float* data_pointer = (float*)lv_event_get_user_data(e);
float data = *data_pointer; float data = *data_pointer;
move_printer("Z", data); move_printer("Z", data, true);
} }
char x_pos_buff[12]; char x_pos_buff[12];
@@ -103,6 +83,11 @@ static void disable_steppers_click(lv_event_t * e) {
send_gcode(true, "M18"); send_gcode(true, "M18");
} }
static void switch_to_stat_panel(lv_event_t * e) {
lv_obj_t * panel = lv_event_get_target(e);
nav_buttons_setup(5);
}
inline void root_panel_steppers_locked(lv_obj_t * root_panel){ inline void root_panel_steppers_locked(lv_obj_t * root_panel){
const auto width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2; const auto width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2;
@@ -121,7 +106,7 @@ inline void root_panel_steppers_locked(lv_obj_t * root_panel){
lv_obj_set_flex_grow(btn, 1); lv_obj_set_flex_grow(btn, 1);
lv_obj_t * label = lv_label_create(btn); lv_obj_t * label = lv_label_create(btn);
lv_label_set_text(label, LV_SYMBOL_HOME "Home Axis"); lv_label_set_text(label, LV_SYMBOL_HOME "Home");
lv_obj_center(label); lv_obj_center(label);
btn = lv_btn_create(home_button_row); btn = lv_btn_create(home_button_row);
@@ -130,7 +115,16 @@ inline void root_panel_steppers_locked(lv_obj_t * root_panel){
lv_obj_set_flex_grow(btn, 1); lv_obj_set_flex_grow(btn, 1);
label = lv_label_create(btn); label = lv_label_create(btn);
lv_label_set_text(label, LV_SYMBOL_EYE_CLOSE " Disable Step"); lv_label_set_text(label, LV_SYMBOL_EYE_CLOSE " Unlock");
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, switch_to_stat_panel, LV_EVENT_CLICKED, NULL);
lv_obj_set_flex_grow(btn, 1);
label = lv_label_create(btn);
lv_label_set_text(label, LV_SYMBOL_EDIT " Params");
lv_obj_center(label); lv_obj_center(label);
for (int row = 0; row < 3; row++) { for (int row = 0; row < 3; row++) {

View File

@@ -37,6 +37,10 @@ static void btn_print_file(lv_event_t * e){
HTTPClient client; HTTPClient client;
client.begin(buff); client.begin(buff);
if (global_config.auth_configured)
client.addHeader("X-Api-Key", global_config.klipper_auth);
int httpCode = client.POST(""); int httpCode = client.POST("");
Serial.printf("Print start: HTTP %d\n", httpCode); Serial.printf("Print start: HTTP %d\n", httpCode);
} }

View File

@@ -29,6 +29,7 @@ static void reset_calibration_click(lv_event_t * e){
static void reset_wifi_click(lv_event_t * e){ static void reset_wifi_click(lv_event_t * e){
global_config.wifiConfigured = false; global_config.wifiConfigured = false;
global_config.ipConfigured = false; global_config.ipConfigured = false;
global_config.auth_configured = false;
WriteGlobalConfig(); WriteGlobalConfig();
ESP.restart(); ESP.restart();
} }
@@ -99,6 +100,14 @@ static void auto_ota_update_switch(lv_event_t* e){
WriteGlobalConfig(); WriteGlobalConfig();
} }
const char* estimated_time_options = "Percentage\nInterpolated\nSlicer";
static void estimated_time_dropdown(lv_event_t * e){
lv_obj_t * dropdown = lv_event_get_target(e);
global_config.remaining_time_calc_mode = lv_dropdown_get_selected(dropdown);
WriteGlobalConfig();
}
const static lv_point_t line_points[] = { {0, 0}, {(short int)((CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2) * 0.85f), 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} };
void create_settings_widget(const char* label_text, lv_obj_t* object, lv_obj_t* root_panel, bool set_height = true){ void create_settings_widget(const char* label_text, lv_obj_t* object, lv_obj_t* root_panel, bool set_height = true){
@@ -122,13 +131,19 @@ void create_settings_widget(const char* label_text, lv_obj_t* object, lv_obj_t*
} }
void settings_panel_init(lv_obj_t* panel){ void settings_panel_init(lv_obj_t* panel){
lv_obj_t * toggle = NULL;
lv_obj_t * btn = NULL;
lv_obj_t * label = NULL;
lv_obj_t * dropdown = NULL;
lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0); lv_obj_set_style_pad_all(panel, CYD_SCREEN_GAP_PX, 0);
lv_layout_flex_column(panel); lv_layout_flex_column(panel);
lv_obj_set_scrollbar_mode(panel, LV_SCROLLBAR_MODE_OFF);
lv_obj_t * btn = lv_btn_create(panel); btn = lv_btn_create(panel);
lv_obj_add_event_cb(btn, reset_wifi_click, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(btn, reset_wifi_click, LV_EVENT_CLICKED, NULL);
lv_obj_t * label = lv_label_create(btn); label = lv_label_create(btn);
lv_label_set_text(label, "Restart"); lv_label_set_text(label, "Restart");
lv_obj_center(label); lv_obj_center(label);
@@ -145,7 +160,8 @@ void settings_panel_init(lv_obj_t* panel){
create_settings_widget("Calibrate Touch", btn, panel); create_settings_widget("Calibrate Touch", btn, panel);
#endif // CYD_SCREEN_DISABLE_TOUCH_CALIBRATION #endif // CYD_SCREEN_DISABLE_TOUCH_CALIBRATION
lv_obj_t * toggle = lv_switch_create(panel); #ifndef CYD_SCREEN_DISABLE_INVERT_COLORS
toggle = lv_switch_create(panel);
lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2); 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); lv_obj_add_event_cb(toggle, invert_color_switch, LV_EVENT_VALUE_CHANGED, NULL);
@@ -153,7 +169,7 @@ void settings_panel_init(lv_obj_t* panel){
lv_obj_add_state(toggle, LV_STATE_CHECKED); lv_obj_add_state(toggle, LV_STATE_CHECKED);
create_settings_widget("Invert Colors", toggle, panel); create_settings_widget("Invert Colors", toggle, panel);
#endif // CYD_SCREEN_DISABLE_INVERT_COLORS
toggle = lv_switch_create(panel); toggle = lv_switch_create(panel);
lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2); lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2);
@@ -164,7 +180,7 @@ void settings_panel_init(lv_obj_t* panel){
create_settings_widget("Light Mode", toggle, panel); create_settings_widget("Light Mode", toggle, panel);
lv_obj_t * dropdown = lv_dropdown_create(panel); dropdown = lv_dropdown_create(panel);
lv_dropdown_set_options(dropdown, "Blue\nGreen\nGrey\nYellow\nOrange\nRed\nPurple"); lv_dropdown_set_options(dropdown, "Blue\nGreen\nGrey\nYellow\nOrange\nRed\nPurple");
lv_dropdown_set_selected(dropdown, global_config.color_scheme); lv_dropdown_set_selected(dropdown, global_config.color_scheme);
lv_obj_add_event_cb(dropdown, theme_dropdown, LV_EVENT_VALUE_CHANGED, NULL); lv_obj_add_event_cb(dropdown, theme_dropdown, LV_EVENT_VALUE_CHANGED, NULL);
@@ -199,6 +215,13 @@ void settings_panel_init(lv_obj_t* panel){
create_settings_widget("Wake Timeout", dropdown, panel); create_settings_widget("Wake Timeout", dropdown, panel);
#endif #endif
dropdown = lv_dropdown_create(panel);
lv_dropdown_set_options(dropdown, estimated_time_options);
lv_obj_add_event_cb(dropdown, estimated_time_dropdown, LV_EVENT_VALUE_CHANGED, NULL);
lv_dropdown_set_selected(dropdown, global_config.remaining_time_calc_mode);
create_settings_widget("Estimated Time", dropdown, panel);
toggle = lv_switch_create(panel); toggle = lv_switch_create(panel);
lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2); 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); lv_obj_add_event_cb(toggle, rotate_screen_switch, LV_EVENT_VALUE_CHANGED, NULL);
@@ -219,6 +242,15 @@ void settings_panel_init(lv_obj_t* panel){
create_settings_widget("Screen On During Print", toggle, panel); create_settings_widget("Screen On During Print", toggle, panel);
#endif #endif
toggle = lv_switch_create(panel);
lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2);
lv_obj_add_event_cb(toggle, auto_ota_update_switch, LV_EVENT_VALUE_CHANGED, NULL);
if (global_config.autoOtaUpdate)
lv_obj_add_state(toggle, LV_STATE_CHECKED);
create_settings_widget("Auto Update", toggle, panel);
label = lv_label_create(panel); label = lv_label_create(panel);
lv_label_set_text(label, REPO_VERSION " "); lv_label_set_text(label, REPO_VERSION " ");
@@ -240,13 +272,4 @@ void settings_panel_init(lv_obj_t* panel){
create_settings_widget("Device", label, panel, false); create_settings_widget("Device", label, panel, false);
} }
toggle = lv_switch_create(panel);
lv_obj_set_width(toggle, CYD_SCREEN_MIN_BUTTON_WIDTH_PX * 2);
lv_obj_add_event_cb(toggle, auto_ota_update_switch, LV_EVENT_VALUE_CHANGED, NULL);
if (global_config.autoOtaUpdate)
lv_obj_add_state(toggle, LV_STATE_CHECKED);
create_settings_widget("Auto Update", toggle, panel);
} }

View File

@@ -36,19 +36,42 @@ static void set_zoffset_text(lv_event_t * e) {
lv_label_set_text(label, data); lv_label_set_text(label, data);
} }
static void set_zoffset_text_ex(lv_event_t * e) {
lv_obj_t * label = lv_event_get_target(e);
char data[64];
sprintf(data, "Z Offset: %.03f, Z: %.03f", printer.gcode_offset[2], printer.position[2]);
lv_label_set_text(label, data);
}
static void set_zoffset(lv_event_t * e){ static void set_zoffset(lv_event_t * e){
char* offset = (char*)lv_event_get_user_data(e); char* offset = (char*)lv_event_get_user_data(e);
char gcode[64]; char gcode[64];
sprintf(gcode, "SET_GCODE_OFFSET Z_ADJUST=%s", offset); sprintf(gcode, "SET_GCODE_OFFSET Z_ADJUST=%s MOVE=1", offset);
send_gcode(true, gcode); send_gcode(true, gcode);
} }
const char* zoffsets[] = { "-0.005", "-0.01", "-0.025", "-0.05" }; static void set_z(lv_event_t * e){
const char* zoffsets_2[] = { "+0.005", "+0.01", "+0.025", "+0.05" }; void* ptr = lv_event_get_user_data(e);
float value = *(float *)(&ptr);
if (value < 0) {
send_gcode(true, "SET_GCODE_OFFSET Z=0 MOVE=1");
return;
}
move_printer("Z", value, false);
}
const char* zoffsets[] = { "-0.01", "-0.025", "-0.05", "-0.2" };
const char* zoffsets_2[] = { "+0.01", "+0.025", "+0.05", "+0.2" };
const char* zabs[] = { "Z=0", "Z=0.1", "Z=1", "Clear" };
const float zabsvalues[] = { 0, 0.1f, 1.0f, -1.0f };
lv_button_column_t zoffset_columns[] = { lv_button_column_t zoffset_columns[] = {
{ set_zoffset, zoffsets, (const void**)zoffsets, 4}, { set_zoffset, zoffsets, (const void**)zoffsets, 4},
{ set_zoffset, zoffsets_2, (const void**)zoffsets_2, 4} { set_zoffset, zoffsets_2, (const void**)zoffsets_2, 4},
{ set_z, zabs, (const void**)zabsvalues, 4}
}; };
static void set_speed_mult_text(lv_event_t * e){ static void set_speed_mult_text(lv_event_t * e){
@@ -126,7 +149,7 @@ static void open_fan_speed_panel(lv_event_t * e){
} }
static void open_zoffset_panel(lv_event_t * e){ 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_create_fullscreen_button_matrix_popup(lv_scr_act(), set_zoffset_text_ex, zoffset_columns, (printer.state == PRINTER_STATE_IDLE) ? 3 : 2);
lv_msg_send(DATA_PRINTER_DATA, &printer); lv_msg_send(DATA_PRINTER_DATA, &printer);
} }
@@ -175,7 +198,7 @@ static void label_total_layers(lv_event_t * e){
static void label_pressure_advance(lv_event_t * e){ static void label_pressure_advance(lv_event_t * e){
lv_obj_t * label = lv_event_get_target(e); lv_obj_t * label = lv_event_get_target(e);
char pressure_buff[32]; char pressure_buff[32];
sprintf(pressure_buff, "%.3f", printer.pressure_advance); sprintf(pressure_buff, "%.3f (%.2fs)", printer.pressure_advance, printer.smooth_time);
lv_label_set_text(label, pressure_buff); lv_label_set_text(label, pressure_buff);
} }
@@ -211,8 +234,12 @@ void stats_panel_init(lv_obj_t* panel) {
lv_obj_align(left_panel, LV_ALIGN_TOP_LEFT, CYD_SCREEN_GAP_PX, CYD_SCREEN_GAP_PX); 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, "Position:", label_pos);
if (printer.state != PRINTER_STATE_IDLE){
create_stat_text_block(left_panel, "Filament Used:", label_filament_used_m); 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, "Layer:", label_total_layers);
}
create_stat_text_block(left_panel, "Pressure Advance:", label_pressure_advance); create_stat_text_block(left_panel, "Pressure Advance:", label_pressure_advance);
create_stat_text_block(left_panel, "Feedrate:", label_feedrate); create_stat_text_block(left_panel, "Feedrate:", label_feedrate);

View File

@@ -207,22 +207,100 @@ static void btn_retract(lv_event_t * e){
send_gcode(true, "G1 E-25 F300"); send_gcode(true, "G1 E-25 F300");
} }
static void set_chart_range(lv_event_t * e) {
lv_obj_t * chart_obj = lv_event_get_target(e);
lv_chart_t * chart = (lv_chart_t *)chart_obj;
int max_temp = 0;
lv_chart_series_t * prev = NULL;
do {
prev = lv_chart_get_series_next(chart_obj, prev);
if (prev != NULL)
for (int i = 0; i < chart->point_cnt; i++)
if (prev->y_points[i] > max_temp)
max_temp = prev->y_points[i];
} while (prev != NULL);
int range = ((max_temp + 49) / 50) * 50;
if (range < 100)
range = 100;
lv_chart_set_range(chart_obj, LV_CHART_AXIS_PRIMARY_Y, 0, range);
}
static void set_hotend_temp_chart(lv_event_t * e){
lv_obj_t * chart = lv_event_get_target(e);
lv_chart_series_t * series = (lv_chart_series_t *)lv_event_get_user_data(e);
lv_chart_set_next_value(chart, series, printer.extruder_temp);
}
static void set_hotend_target_temp_chart(lv_event_t * e){
lv_obj_t * chart = lv_event_get_target(e);
lv_chart_series_t * series = (lv_chart_series_t *)lv_event_get_user_data(e);
lv_chart_set_next_value(chart, series, printer.extruder_target_temp);
}
static void set_bed_temp_chart(lv_event_t * e){
lv_obj_t * chart = lv_event_get_target(e);
lv_chart_series_t * series = (lv_chart_series_t *)lv_event_get_user_data(e);
lv_chart_set_next_value(chart, series, printer.bed_temp);
}
static void set_bed_target_temp_chart(lv_event_t * e){
lv_obj_t * chart = lv_event_get_target(e);
lv_chart_series_t * series = (lv_chart_series_t *)lv_event_get_user_data(e);
lv_chart_set_next_value(chart, series, printer.bed_target_temp);
}
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; const auto element_width = CYD_SCREEN_PANEL_WIDTH_PX - CYD_SCREEN_GAP_PX * 2;
root_panel = panel; root_panel = panel;
edit_mode = false; edit_mode = false;
lv_obj_t * root_temp_panel = lv_create_empty_panel(panel); 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_set_size(root_temp_panel, CYD_SCREEN_PANEL_WIDTH_PX, CYD_SCREEN_HEIGHT_PX);
lv_obj_align(root_temp_panel, LV_ALIGN_TOP_RIGHT, 0, 0); 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_obj_set_style_pad_all(root_temp_panel, CYD_SCREEN_GAP_PX, 0);
lv_layout_flex_column(root_temp_panel); lv_layout_flex_column(root_temp_panel);
lv_obj_set_flex_align(root_temp_panel, LV_FLEX_ALIGN_START, LV_FLEX_ALIGN_END, LV_FLEX_ALIGN_CENTER);
lv_obj_set_scrollbar_mode(root_temp_panel, LV_SCROLLBAR_MODE_OFF);
lv_obj_t * chart = lv_chart_create(root_temp_panel);
lv_obj_set_size(chart, element_width - CYD_SCREEN_MIN_BUTTON_WIDTH_PX, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX * 3);
lv_chart_set_type(chart, LV_CHART_TYPE_LINE);
lv_chart_set_point_count(chart, 120);
lv_obj_set_style_size(chart, 0, LV_PART_INDICATOR);
lv_chart_set_axis_tick(chart, LV_CHART_AXIS_PRIMARY_Y, CYD_SCREEN_GAP_PX / 2, CYD_SCREEN_GAP_PX / 4, 4, 3, true, CYD_SCREEN_MIN_BUTTON_WIDTH_PX);
lv_chart_set_update_mode(chart, LV_CHART_UPDATE_MODE_SHIFT);
lv_chart_series_t * ser1 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_ORANGE), LV_CHART_AXIS_PRIMARY_Y);
lv_chart_set_all_value(chart, ser1, printer.extruder_target_temp);
lv_chart_series_t * ser2 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_RED), LV_CHART_AXIS_PRIMARY_Y);
lv_chart_set_all_value(chart, ser2, printer.extruder_temp);
lv_chart_series_t * ser3 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_TEAL), LV_CHART_AXIS_PRIMARY_Y);
lv_chart_set_all_value(chart, ser3, printer.bed_target_temp);
lv_chart_series_t * ser4 = lv_chart_add_series(chart, lv_palette_main(LV_PALETTE_BLUE), LV_CHART_AXIS_PRIMARY_Y);
lv_chart_set_all_value(chart, ser4, printer.bed_temp);
lv_obj_add_event_cb(chart, set_hotend_target_temp_chart, LV_EVENT_MSG_RECEIVED, ser1);
lv_obj_add_event_cb(chart, set_hotend_temp_chart, LV_EVENT_MSG_RECEIVED, ser2);
lv_obj_add_event_cb(chart, set_bed_target_temp_chart, LV_EVENT_MSG_RECEIVED, ser3);
lv_obj_add_event_cb(chart, set_bed_temp_chart, LV_EVENT_MSG_RECEIVED, ser4);
lv_obj_add_event_cb(chart, set_chart_range, LV_EVENT_MSG_RECEIVED, NULL);
lv_msg_subscribe_obj(DATA_PRINTER_DATA, chart, NULL);
lv_obj_t * single_screen_panel = lv_create_empty_panel(root_temp_panel);
lv_obj_set_size(single_screen_panel, element_width, CYD_SCREEN_HEIGHT_PX - CYD_SCREEN_GAP_PX * 2 - CYD_SCREEN_GAP_PX / 2);
lv_layout_flex_column(single_screen_panel);
lv_obj_t * temp_rows[2] = {0}; lv_obj_t * temp_rows[2] = {0};
lv_obj_t * button_temp_rows[2] = {0}; lv_obj_t * button_temp_rows[2] = {0};
for (int tempIter = 0; tempIter < 2; tempIter++){ for (int tempIter = 0; tempIter < 2; tempIter++){
temp_rows[tempIter] = lv_create_empty_panel(root_temp_panel); temp_rows[tempIter] = lv_create_empty_panel(single_screen_panel);
lv_layout_flex_column(temp_rows[tempIter]); lv_layout_flex_column(temp_rows[tempIter]);
lv_obj_set_size(temp_rows[tempIter], element_width, LV_SIZE_CONTENT); lv_obj_set_size(temp_rows[tempIter], element_width, LV_SIZE_CONTENT);
@@ -259,16 +337,17 @@ void temp_panel_init(lv_obj_t * panel){
lv_obj_center(label); lv_obj_center(label);
} }
lv_obj_t * bottom_panel = lv_create_empty_panel(panel); lv_obj_t * gap = lv_create_empty_panel(single_screen_panel);
lv_obj_set_size(bottom_panel, element_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); lv_obj_set_flex_grow(gap, 1);
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);
lv_obj_t * one_above_bottom_panel = lv_create_empty_panel(panel); lv_obj_t * one_above_bottom_panel = lv_create_empty_panel(single_screen_panel);
lv_obj_set_size(one_above_bottom_panel, element_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX); 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); lv_layout_flex_row(one_above_bottom_panel, LV_FLEX_ALIGN_SPACE_EVENLY);
lv_obj_t * bottom_panel = lv_create_empty_panel(single_screen_panel);
lv_obj_set_size(bottom_panel, element_width, CYD_SCREEN_MIN_BUTTON_HEIGHT_PX);
lv_layout_flex_row(bottom_panel, LV_FLEX_ALIGN_SPACE_EVENLY);
lv_obj_t * btn = lv_btn_create(bottom_panel); lv_obj_t * btn = lv_btn_create(bottom_panel);
lv_obj_set_flex_grow(btn, 1); lv_obj_set_flex_grow(btn, 1);
lv_obj_add_event_cb(btn, btn_extrude, LV_EVENT_CLICKED, NULL); lv_obj_add_event_cb(btn, btn_extrude, LV_EVENT_CLICKED, NULL);
@@ -306,5 +385,6 @@ void temp_panel_init(lv_obj_t * panel){
lv_label_set_text(label, "Edit Presets"); lv_label_set_text(label, "Edit Presets");
lv_obj_center(label); lv_obj_center(label);
lv_obj_scroll_to_y(root_temp_panel, 9999, LV_ANIM_OFF);
lv_msg_send(DATA_PRINTER_TEMP_PRESET, &printer); lv_msg_send(DATA_PRINTER_TEMP_PRESET, &printer);
} }

View File

@@ -22,6 +22,7 @@ A ESP32-2432S028R is required to run this project. You can find out where to buy
- Extrude/Retract filament - Extrude/Retract filament
- Execute predefined gcode macros - Execute predefined gcode macros
- Toggle Moonraker power devices - Toggle Moonraker power devices
- OTA updates
### Install ### Install
@@ -29,7 +30,13 @@ A ESP32-2432S028R is required to run this project. You can find out where to buy
On initial install, all data should be wiped. On updates, data should be able to be kept without issues. On initial install, all data should be wiped. On updates, data should be able to be kept without issues.
There are no 'over the air' updates. Each update has to be applied manually. When there is an update available, a button in the settings will appear that can be pressed to update. If automatic updates are preferred, there is a toggle in the settings to automatically update. This will right after connecting to wifi update the screen.
### Donate
If you found this project helpful, please consider a donation [to my Ko-Fi](https://ko-fi.com/suchmememanyskill). It would help out a lot in the development of this project, due to the need to buy the screens.
Thank you!
### Screenshots ### Screenshots
(Quite literally shots of the screen. I'm sorry) (Quite literally shots of the screen. I'm sorry)