Bump to bugfix brack as of 20180526
This commit is contained in:
+432
-432
@@ -28,483 +28,483 @@
|
||||
#ifndef CONDITIONALS_LCD_H // Get the LCD defines which are needed first
|
||||
#define CONDITIONALS_LCD_H
|
||||
|
||||
#define LCD_HAS_DIRECTIONAL_BUTTONS (BUTTON_EXISTS(UP) || BUTTON_EXISTS(DWN) || BUTTON_EXISTS(LFT) || BUTTON_EXISTS(RT))
|
||||
#define LCD_HAS_DIRECTIONAL_BUTTONS (BUTTON_EXISTS(UP) || BUTTON_EXISTS(DWN) || BUTTON_EXISTS(LFT) || BUTTON_EXISTS(RT))
|
||||
|
||||
#if ENABLED(CARTESIO_UI)
|
||||
#if ENABLED(CARTESIO_UI)
|
||||
|
||||
#define DOGLCD
|
||||
#define ULTIPANEL
|
||||
#define DEFAULT_LCD_CONTRAST 90
|
||||
#define LCD_CONTRAST_MIN 60
|
||||
#define LCD_CONTRAST_MAX 140
|
||||
#define DOGLCD
|
||||
#define ULTIPANEL
|
||||
#define DEFAULT_LCD_CONTRAST 90
|
||||
#define LCD_CONTRAST_MIN 60
|
||||
#define LCD_CONTRAST_MAX 140
|
||||
|
||||
#elif ENABLED(MAKRPANEL)
|
||||
#elif ENABLED(MAKRPANEL)
|
||||
|
||||
#define U8GLIB_ST7565_64128N
|
||||
|
||||
#elif ENABLED(ZONESTAR_LCD)
|
||||
|
||||
#define REPRAPWORLD_KEYPAD
|
||||
#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0
|
||||
#define ADC_KEYPAD
|
||||
#define ADC_KEY_NUM 8
|
||||
#define ULTIPANEL
|
||||
|
||||
// this helps to implement ADC_KEYPAD menus
|
||||
#define ENCODER_PULSES_PER_STEP 1
|
||||
#define ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
#define ENCODER_FEEDRATE_DEADZONE 2
|
||||
#define REVERSE_MENU_DIRECTION
|
||||
|
||||
#elif ENABLED(ANET_FULL_GRAPHICS_LCD)
|
||||
|
||||
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
|
||||
#elif ENABLED(BQ_LCD_SMART_CONTROLLER)
|
||||
|
||||
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
|
||||
#elif ENABLED(miniVIKI) || ENABLED(VIKI2) || ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
|
||||
|
||||
#define ULTRA_LCD //general LCD support, also 16x2
|
||||
#define DOGLCD // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
|
||||
#define ULTIMAKERCONTROLLER //as available from the Ultimaker online store.
|
||||
|
||||
#if ENABLED(miniVIKI)
|
||||
#define LCD_CONTRAST_MIN 75
|
||||
#define LCD_CONTRAST_MAX 115
|
||||
#define DEFAULT_LCD_CONTRAST 95
|
||||
#define U8GLIB_ST7565_64128N
|
||||
|
||||
#elif ENABLED(ZONESTAR_LCD)
|
||||
|
||||
#define REPRAPWORLD_KEYPAD
|
||||
#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0
|
||||
#define ADC_KEYPAD
|
||||
#define ADC_KEY_NUM 8
|
||||
#define ULTIPANEL
|
||||
|
||||
// this helps to implement ADC_KEYPAD menus
|
||||
#define ENCODER_PULSES_PER_STEP 1
|
||||
#define ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
#define ENCODER_FEEDRATE_DEADZONE 2
|
||||
#define REVERSE_MENU_DIRECTION
|
||||
|
||||
#elif ENABLED(ANET_FULL_GRAPHICS_LCD)
|
||||
|
||||
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
|
||||
#elif ENABLED(BQ_LCD_SMART_CONTROLLER)
|
||||
|
||||
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
|
||||
#elif ENABLED(miniVIKI) || ENABLED(VIKI2) || ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
|
||||
|
||||
#define ULTRA_LCD //general LCD support, also 16x2
|
||||
#define DOGLCD // Support for SPI LCD 128x64 (Controller ST7565R graphic Display Family)
|
||||
#define ULTIMAKERCONTROLLER //as available from the Ultimaker online store.
|
||||
|
||||
#if ENABLED(miniVIKI)
|
||||
#define LCD_CONTRAST_MIN 75
|
||||
#define LCD_CONTRAST_MAX 115
|
||||
#define DEFAULT_LCD_CONTRAST 95
|
||||
#define U8GLIB_ST7565_64128N
|
||||
#elif ENABLED(VIKI2)
|
||||
#define LCD_CONTRAST_MIN 0
|
||||
#define LCD_CONTRAST_MAX 255
|
||||
#define DEFAULT_LCD_CONTRAST 140
|
||||
#define U8GLIB_ST7565_64128N
|
||||
#elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
|
||||
#define LCD_CONTRAST_MIN 90
|
||||
#define LCD_CONTRAST_MAX 130
|
||||
#define DEFAULT_LCD_CONTRAST 110
|
||||
#define U8GLIB_LM6059_AF
|
||||
#define SD_DETECT_INVERTED
|
||||
#endif
|
||||
|
||||
#elif ENABLED(OLED_PANEL_TINYBOY2)
|
||||
|
||||
#define U8GLIB_SSD1306
|
||||
#define ULTIPANEL
|
||||
#define REVERSE_ENCODER_DIRECTION
|
||||
#define REVERSE_MENU_DIRECTION
|
||||
|
||||
#elif ENABLED(RA_CONTROL_PANEL)
|
||||
|
||||
#define LCD_I2C_TYPE_PCA8574
|
||||
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
|
||||
#define ULTIPANEL
|
||||
|
||||
#elif ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
|
||||
|
||||
#define DOGLCD
|
||||
#define U8GLIB_ST7920
|
||||
#define ULTIPANEL
|
||||
|
||||
#elif ENABLED(CR10_STOCKDISPLAY)
|
||||
|
||||
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
#ifndef ST7920_DELAY_1
|
||||
#define ST7920_DELAY_1 DELAY_2_NOP
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_2
|
||||
#define ST7920_DELAY_2 DELAY_2_NOP
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_3
|
||||
#define ST7920_DELAY_3 DELAY_2_NOP
|
||||
#endif
|
||||
|
||||
#elif ENABLED(MKS_12864OLED)
|
||||
|
||||
#define REPRAP_DISCOUNT_SMART_CONTROLLER
|
||||
#define U8GLIB_SH1106
|
||||
|
||||
#elif ENABLED(MKS_12864OLED_SSD1306)
|
||||
|
||||
#define REPRAP_DISCOUNT_SMART_CONTROLLER
|
||||
#define U8GLIB_SSD1306
|
||||
|
||||
#elif ENABLED(MKS_MINI_12864)
|
||||
|
||||
#define MINIPANEL
|
||||
|
||||
#elif ENABLED(VIKI2)
|
||||
#define LCD_CONTRAST_MIN 0
|
||||
#define LCD_CONTRAST_MAX 255
|
||||
#define DEFAULT_LCD_CONTRAST 140
|
||||
#define U8GLIB_ST7565_64128N
|
||||
#elif ENABLED(ELB_FULL_GRAPHIC_CONTROLLER)
|
||||
#define LCD_CONTRAST_MIN 90
|
||||
#define LCD_CONTRAST_MAX 130
|
||||
#define DEFAULT_LCD_CONTRAST 110
|
||||
#define U8GLIB_LM6059_AF
|
||||
#define SD_DETECT_INVERTED
|
||||
#endif
|
||||
|
||||
#if ENABLED(MAKRPANEL) || ENABLED(MINIPANEL)
|
||||
#define DOGLCD
|
||||
#define ULTIPANEL
|
||||
#define DEFAULT_LCD_CONTRAST 17
|
||||
#elif ENABLED(OLED_PANEL_TINYBOY2)
|
||||
|
||||
#define U8GLIB_SSD1306
|
||||
#define ULTIPANEL
|
||||
#define REVERSE_ENCODER_DIRECTION
|
||||
#define REVERSE_MENU_DIRECTION
|
||||
|
||||
#elif ENABLED(RA_CONTROL_PANEL)
|
||||
|
||||
#define LCD_I2C_TYPE_PCA8574
|
||||
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
|
||||
#define ULTIPANEL
|
||||
|
||||
#elif ENABLED(REPRAPWORLD_GRAPHICAL_LCD)
|
||||
|
||||
#define DOGLCD
|
||||
#define U8GLIB_ST7920
|
||||
#define ULTIPANEL
|
||||
|
||||
#elif ENABLED(CR10_STOCKDISPLAY)
|
||||
|
||||
#define REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER
|
||||
#ifndef ST7920_DELAY_1
|
||||
#define ST7920_DELAY_1 DELAY_NS(125)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_2
|
||||
#define ST7920_DELAY_2 DELAY_NS(125)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_3
|
||||
#define ST7920_DELAY_3 DELAY_NS(125)
|
||||
#endif
|
||||
|
||||
#if ENABLED(ULTI_CONTROLLER)
|
||||
#define U8GLIB_SSD1309
|
||||
#define REVERSE_ENCODER_DIRECTION
|
||||
#define LCD_RESET_PIN LCD_PINS_D6 // This controller need a reset pin
|
||||
#define LCD_CONTRAST_MIN 0
|
||||
#define LCD_CONTRAST_MAX 254
|
||||
#define DEFAULT_LCD_CONTRAST 127
|
||||
#define ENCODER_PULSES_PER_STEP 2
|
||||
#define ENCODER_STEPS_PER_MENU_ITEM 2
|
||||
#elif ENABLED(MKS_12864OLED)
|
||||
|
||||
#define REPRAP_DISCOUNT_SMART_CONTROLLER
|
||||
#define U8GLIB_SH1106
|
||||
|
||||
#elif ENABLED(MKS_12864OLED_SSD1306)
|
||||
|
||||
#define REPRAP_DISCOUNT_SMART_CONTROLLER
|
||||
#define U8GLIB_SSD1306
|
||||
|
||||
#elif ENABLED(MKS_MINI_12864)
|
||||
|
||||
#define MINIPANEL
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(MAKRPANEL) || ENABLED(MINIPANEL)
|
||||
#define DOGLCD
|
||||
#define ULTIPANEL
|
||||
#define DEFAULT_LCD_CONTRAST 17
|
||||
#endif
|
||||
|
||||
#if ENABLED(ULTI_CONTROLLER)
|
||||
#define U8GLIB_SSD1309
|
||||
#define REVERSE_ENCODER_DIRECTION
|
||||
#define LCD_RESET_PIN LCD_PINS_D6 // This controller need a reset pin
|
||||
#define LCD_CONTRAST_MIN 0
|
||||
#define LCD_CONTRAST_MAX 254
|
||||
#define DEFAULT_LCD_CONTRAST 127
|
||||
#define ENCODER_PULSES_PER_STEP 2
|
||||
#define ENCODER_STEPS_PER_MENU_ITEM 2
|
||||
#endif
|
||||
|
||||
// Generic support for SSD1306 / SSD1309 / SH1106 OLED based LCDs.
|
||||
#if ENABLED(U8GLIB_SSD1306) || ENABLED(U8GLIB_SSD1309) || ENABLED(U8GLIB_SH1106)
|
||||
#define ULTRA_LCD //general LCD support, also 16x2
|
||||
#define DOGLCD // Support for I2C LCD 128x64 (Controller SSD1306 / SSD1309 / SH1106 graphic Display Family)
|
||||
#endif
|
||||
|
||||
#if ENABLED(PANEL_ONE) || ENABLED(U8GLIB_SH1106)
|
||||
|
||||
#define ULTIMAKERCONTROLLER
|
||||
|
||||
#elif ENABLED(MAKEBOARD_MINI_2_LINE_DISPLAY_1602)
|
||||
|
||||
#define REPRAP_DISCOUNT_SMART_CONTROLLER
|
||||
#define LCD_WIDTH 16
|
||||
#define LCD_HEIGHT 2
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) || ENABLED(LCD_FOR_MELZI) || ENABLED(SILVER_GATE_GLCD_CONTROLLER)
|
||||
#define DOGLCD
|
||||
#define U8GLIB_ST7920
|
||||
#define REPRAP_DISCOUNT_SMART_CONTROLLER
|
||||
#endif
|
||||
|
||||
#if ENABLED(ULTIMAKERCONTROLLER) \
|
||||
|| ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) \
|
||||
|| ENABLED(G3D_PANEL) \
|
||||
|| ENABLED(RIGIDBOT_PANEL) \
|
||||
|| ENABLED(ULTI_CONTROLLER)
|
||||
#define ULTIPANEL
|
||||
#endif
|
||||
|
||||
#if ENABLED(REPRAPWORLD_KEYPAD)
|
||||
#define NEWPANEL
|
||||
#if ENABLED(ULTIPANEL) && !defined(REPRAPWORLD_KEYPAD_MOVE_STEP)
|
||||
#define REPRAPWORLD_KEYPAD_MOVE_STEP 1.0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* I2C PANELS
|
||||
*/
|
||||
|
||||
#if ENABLED(LCD_SAINSMART_I2C_1602) || ENABLED(LCD_SAINSMART_I2C_2004)
|
||||
|
||||
#define LCD_I2C_TYPE_PCF8575
|
||||
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
|
||||
#define ULTRA_LCD
|
||||
|
||||
#if ENABLED(LCD_SAINSMART_I2C_2004)
|
||||
#define LCD_WIDTH 20
|
||||
#define LCD_HEIGHT 4
|
||||
#endif
|
||||
|
||||
// Generic support for SSD1306 / SSD1309 / SH1106 OLED based LCDs.
|
||||
#if ENABLED(U8GLIB_SSD1306) || ENABLED(U8GLIB_SSD1309) || ENABLED(U8GLIB_SH1106)
|
||||
#define ULTRA_LCD //general LCD support, also 16x2
|
||||
#define DOGLCD // Support for I2C LCD 128x64 (Controller SSD1306 / SSD1309 / SH1106 graphic Display Family)
|
||||
#elif ENABLED(LCD_I2C_PANELOLU2)
|
||||
|
||||
// PANELOLU2 LCD with status LEDs, separate encoder and click inputs
|
||||
|
||||
#define LCD_I2C_TYPE_MCP23017
|
||||
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
|
||||
#define LCD_USE_I2C_BUZZER // Enable buzzer on LCD (optional)
|
||||
#define ULTIPANEL
|
||||
|
||||
#elif ENABLED(LCD_I2C_VIKI)
|
||||
|
||||
/**
|
||||
* Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
|
||||
*
|
||||
* This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
|
||||
* Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
|
||||
* Note: The pause/stop/resume LCD button pin should be connected to the Arduino
|
||||
* BTN_ENC pin (or set BTN_ENC to -1 if not used)
|
||||
*/
|
||||
#define LCD_I2C_TYPE_MCP23017
|
||||
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
|
||||
#define LCD_USE_I2C_BUZZER // Enable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
|
||||
#define ULTIPANEL
|
||||
|
||||
#define ENCODER_FEEDRATE_DEADZONE 4
|
||||
|
||||
#define STD_ENCODER_PULSES_PER_STEP 1
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 2
|
||||
|
||||
#elif ENABLED(G3D_PANEL)
|
||||
|
||||
#define STD_ENCODER_PULSES_PER_STEP 2
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
|
||||
#elif ENABLED(miniVIKI) || ENABLED(VIKI2) \
|
||||
|| ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \
|
||||
|| ENABLED(OLED_PANEL_TINYBOY2) \
|
||||
|| ENABLED(BQ_LCD_SMART_CONTROLLER) \
|
||||
|| ENABLED(LCD_I2C_PANELOLU2) \
|
||||
|| ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
|
||||
#define STD_ENCODER_PULSES_PER_STEP 4
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
#endif
|
||||
|
||||
#ifndef STD_ENCODER_PULSES_PER_STEP
|
||||
#define STD_ENCODER_PULSES_PER_STEP 5
|
||||
#endif
|
||||
#ifndef STD_ENCODER_STEPS_PER_MENU_ITEM
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
#endif
|
||||
#ifndef ENCODER_PULSES_PER_STEP
|
||||
#define ENCODER_PULSES_PER_STEP STD_ENCODER_PULSES_PER_STEP
|
||||
#endif
|
||||
#ifndef ENCODER_STEPS_PER_MENU_ITEM
|
||||
#define ENCODER_STEPS_PER_MENU_ITEM STD_ENCODER_STEPS_PER_MENU_ITEM
|
||||
#endif
|
||||
#ifndef ENCODER_FEEDRATE_DEADZONE
|
||||
#define ENCODER_FEEDRATE_DEADZONE 6
|
||||
#endif
|
||||
|
||||
// Shift register panels
|
||||
// ---------------------
|
||||
// 2 wire Non-latching LCD SR from:
|
||||
// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
|
||||
|
||||
#if ENABLED(SAV_3DLCD)
|
||||
#define SR_LCD_2W_NL // Non latching 2 wire shift register
|
||||
#define ULTIPANEL
|
||||
#endif
|
||||
|
||||
#if ENABLED(DOGLCD) // Change number of lines to match the DOG graphic display
|
||||
#ifndef LCD_WIDTH
|
||||
#ifdef LCD_WIDTH_OVERRIDE
|
||||
#define LCD_WIDTH LCD_WIDTH_OVERRIDE
|
||||
#else
|
||||
#define LCD_WIDTH 22
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LCD_HEIGHT
|
||||
#define LCD_HEIGHT 5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(PANEL_ONE) || ENABLED(U8GLIB_SH1106)
|
||||
#if ENABLED(NO_LCD_MENUS)
|
||||
#undef ULTIPANEL
|
||||
#endif
|
||||
|
||||
#define ULTIMAKERCONTROLLER
|
||||
|
||||
#elif ENABLED(MAKEBOARD_MINI_2_LINE_DISPLAY_1602)
|
||||
|
||||
#define REPRAP_DISCOUNT_SMART_CONTROLLER
|
||||
#if ENABLED(ULTIPANEL)
|
||||
#define NEWPANEL // Disable this if you actually have no click-encoder panel
|
||||
#define ULTRA_LCD
|
||||
#ifndef LCD_WIDTH
|
||||
#define LCD_WIDTH 20
|
||||
#endif
|
||||
#ifndef LCD_HEIGHT
|
||||
#define LCD_HEIGHT 4
|
||||
#endif
|
||||
#elif ENABLED(ULTRA_LCD) // no panel but just LCD
|
||||
#ifndef LCD_WIDTH
|
||||
#define LCD_WIDTH 16
|
||||
#endif
|
||||
#ifndef LCD_HEIGHT
|
||||
#define LCD_HEIGHT 2
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(REPRAP_DISCOUNT_FULL_GRAPHIC_SMART_CONTROLLER) || ENABLED(LCD_FOR_MELZI) || ENABLED(SILVER_GATE_GLCD_CONTROLLER)
|
||||
#define DOGLCD
|
||||
#define U8GLIB_ST7920
|
||||
#define REPRAP_DISCOUNT_SMART_CONTROLLER
|
||||
#endif
|
||||
#if ENABLED(DOGLCD)
|
||||
/* Custom characters defined in font dogm_font_data_Marlin_symbols.h / Marlin_symbols.fon */
|
||||
// \x00 intentionally skipped to avoid problems in strings
|
||||
#define LCD_STR_REFRESH "\x01"
|
||||
#define LCD_STR_FOLDER "\x02"
|
||||
#define LCD_STR_ARROW_RIGHT "\x03"
|
||||
#define LCD_STR_UPLEVEL "\x04"
|
||||
#define LCD_STR_CLOCK "\x05"
|
||||
#define LCD_STR_FEEDRATE "\x06"
|
||||
#define LCD_STR_BEDTEMP "\x07"
|
||||
#define LCD_STR_THERMOMETER "\x08"
|
||||
#define LCD_STR_DEGREE "\x09"
|
||||
|
||||
#if ENABLED(ULTIMAKERCONTROLLER) \
|
||||
|| ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER) \
|
||||
|| ENABLED(G3D_PANEL) \
|
||||
|| ENABLED(RIGIDBOT_PANEL) \
|
||||
|| ENABLED(ULTI_CONTROLLER)
|
||||
#define ULTIPANEL
|
||||
#endif
|
||||
#define LCD_STR_SPECIAL_MAX '\x09'
|
||||
// Maximum here is 0x1F because 0x20 is ' ' (space) and the normal charsets begin.
|
||||
// Better stay below 0x10 because DISPLAY_CHARSET_HD44780_WESTERN begins here.
|
||||
|
||||
#if ENABLED(REPRAPWORLD_KEYPAD)
|
||||
#define NEWPANEL
|
||||
#if ENABLED(ULTIPANEL) && !defined(REPRAPWORLD_KEYPAD_MOVE_STEP)
|
||||
#define REPRAPWORLD_KEYPAD_MOVE_STEP 1.0
|
||||
// Symbol characters
|
||||
#define LCD_STR_FILAM_DIA "\xf8"
|
||||
#define LCD_STR_FILAM_MUL "\xa4"
|
||||
#else
|
||||
// Custom characters defined in the first 8 characters of the LCD
|
||||
#define LCD_BEDTEMP_CHAR 0x00 // Print only as a char. This will have 'unexpected' results when used in a string!
|
||||
#define LCD_DEGREE_CHAR 0x01
|
||||
#define LCD_STR_THERMOMETER "\x02" // Still used with string concatenation
|
||||
#define LCD_UPLEVEL_CHAR 0x03
|
||||
#define LCD_STR_REFRESH "\x04"
|
||||
#define LCD_STR_FOLDER "\x05"
|
||||
#define LCD_FEEDRATE_CHAR 0x06
|
||||
#define LCD_CLOCK_CHAR 0x07
|
||||
#define LCD_STR_ARROW_RIGHT ">" /* from the default character set */
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Default LCD contrast for dogm-like LCD displays
|
||||
*/
|
||||
#if ENABLED(DOGLCD)
|
||||
|
||||
#define HAS_LCD_CONTRAST ( \
|
||||
ENABLED(MAKRPANEL) \
|
||||
|| ENABLED(CARTESIO_UI) \
|
||||
|| ENABLED(VIKI2) \
|
||||
|| ENABLED(miniVIKI) \
|
||||
|| ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \
|
||||
)
|
||||
|
||||
#if HAS_LCD_CONTRAST
|
||||
#ifndef LCD_CONTRAST_MIN
|
||||
#define LCD_CONTRAST_MIN 0
|
||||
#endif
|
||||
#ifndef LCD_CONTRAST_MAX
|
||||
#define LCD_CONTRAST_MAX 63
|
||||
#endif
|
||||
#ifndef DEFAULT_LCD_CONTRAST
|
||||
#define DEFAULT_LCD_CONTRAST 32
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* I2C PANELS
|
||||
*/
|
||||
// Boot screens
|
||||
#if DISABLED(ULTRA_LCD)
|
||||
#undef SHOW_BOOTSCREEN
|
||||
#elif !defined(BOOTSCREEN_TIMEOUT)
|
||||
#define BOOTSCREEN_TIMEOUT 2500
|
||||
#endif
|
||||
|
||||
#if ENABLED(LCD_SAINSMART_I2C_1602) || ENABLED(LCD_SAINSMART_I2C_2004)
|
||||
#define HAS_DEBUG_MENU (ENABLED(ULTIPANEL) && ENABLED(LCD_PROGRESS_BAR_TEST))
|
||||
|
||||
#define LCD_I2C_TYPE_PCF8575
|
||||
#define LCD_I2C_ADDRESS 0x27 // I2C Address of the port expander
|
||||
#define ULTRA_LCD
|
||||
// MK2 Multiplexer forces SINGLENOZZLE and kills DISABLE_INACTIVE_EXTRUDER
|
||||
#if ENABLED(MK2_MULTIPLEXER)
|
||||
#define SINGLENOZZLE
|
||||
#undef DISABLE_INACTIVE_EXTRUDER
|
||||
#endif
|
||||
|
||||
#if ENABLED(LCD_SAINSMART_I2C_2004)
|
||||
#define LCD_WIDTH 20
|
||||
#define LCD_HEIGHT 4
|
||||
#endif
|
||||
/**
|
||||
* Extruders have some combination of stepper motors and hotends
|
||||
* so we separate these concepts into the defines:
|
||||
*
|
||||
* EXTRUDERS - Number of Selectable Tools
|
||||
* HOTENDS - Number of hotends, whether connected or separate
|
||||
* E_STEPPERS - Number of actual E stepper motors
|
||||
* E_MANUAL - Number of E steppers for LCD move options
|
||||
*
|
||||
*/
|
||||
#if ENABLED(SINGLENOZZLE) || ENABLED(MIXING_EXTRUDER) // One hotend, one thermistor, no XY offset
|
||||
#define HOTENDS 1
|
||||
#undef TEMP_SENSOR_1_AS_REDUNDANT
|
||||
#undef HOTEND_OFFSET_X
|
||||
#undef HOTEND_OFFSET_Y
|
||||
#else // Two hotends
|
||||
#define HOTENDS EXTRUDERS
|
||||
#endif
|
||||
|
||||
#elif ENABLED(LCD_I2C_PANELOLU2)
|
||||
|
||||
// PANELOLU2 LCD with status LEDs, separate encoder and click inputs
|
||||
|
||||
#define LCD_I2C_TYPE_MCP23017
|
||||
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
|
||||
#define LCD_USE_I2C_BUZZER // Enable buzzer on LCD (optional)
|
||||
#define ULTIPANEL
|
||||
|
||||
#elif ENABLED(LCD_I2C_VIKI)
|
||||
|
||||
/**
|
||||
* Panucatt VIKI LCD with status LEDs, integrated click & L/R/U/P buttons, separate encoder inputs
|
||||
*
|
||||
* This uses the LiquidTWI2 library v1.2.3 or later ( https://github.com/lincomatic/LiquidTWI2 )
|
||||
* Make sure the LiquidTWI2 directory is placed in the Arduino or Sketchbook libraries subdirectory.
|
||||
* Note: The pause/stop/resume LCD button pin should be connected to the Arduino
|
||||
* BTN_ENC pin (or set BTN_ENC to -1 if not used)
|
||||
*/
|
||||
#define LCD_I2C_TYPE_MCP23017
|
||||
#define LCD_I2C_ADDRESS 0x20 // I2C Address of the port expander
|
||||
#define LCD_USE_I2C_BUZZER // Enable buzzer on LCD (requires LiquidTWI2 v1.2.3 or later)
|
||||
#define ULTIPANEL
|
||||
|
||||
#define ENCODER_FEEDRATE_DEADZONE 4
|
||||
|
||||
#define STD_ENCODER_PULSES_PER_STEP 1
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 2
|
||||
|
||||
#elif ENABLED(G3D_PANEL)
|
||||
|
||||
#define STD_ENCODER_PULSES_PER_STEP 2
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
|
||||
#elif ENABLED(miniVIKI) || ENABLED(VIKI2) \
|
||||
|| ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \
|
||||
|| ENABLED(OLED_PANEL_TINYBOY2) \
|
||||
|| ENABLED(BQ_LCD_SMART_CONTROLLER) \
|
||||
|| ENABLED(LCD_I2C_PANELOLU2) \
|
||||
|| ENABLED(REPRAP_DISCOUNT_SMART_CONTROLLER)
|
||||
#define STD_ENCODER_PULSES_PER_STEP 4
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
#endif
|
||||
|
||||
#ifndef STD_ENCODER_PULSES_PER_STEP
|
||||
#define STD_ENCODER_PULSES_PER_STEP 5
|
||||
#endif
|
||||
#ifndef STD_ENCODER_STEPS_PER_MENU_ITEM
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
#endif
|
||||
#ifndef ENCODER_PULSES_PER_STEP
|
||||
#define ENCODER_PULSES_PER_STEP STD_ENCODER_PULSES_PER_STEP
|
||||
#endif
|
||||
#ifndef ENCODER_STEPS_PER_MENU_ITEM
|
||||
#define ENCODER_STEPS_PER_MENU_ITEM STD_ENCODER_STEPS_PER_MENU_ITEM
|
||||
#endif
|
||||
#ifndef ENCODER_FEEDRATE_DEADZONE
|
||||
#define ENCODER_FEEDRATE_DEADZONE 6
|
||||
#endif
|
||||
|
||||
// Shift register panels
|
||||
// ---------------------
|
||||
// 2 wire Non-latching LCD SR from:
|
||||
// https://bitbucket.org/fmalpartida/new-liquidcrystal/wiki/schematics#!shiftregister-connection
|
||||
|
||||
#if ENABLED(SAV_3DLCD)
|
||||
#define SR_LCD_2W_NL // Non latching 2 wire shift register
|
||||
#define ULTIPANEL
|
||||
#endif
|
||||
|
||||
#if ENABLED(DOGLCD) // Change number of lines to match the DOG graphic display
|
||||
#ifndef LCD_WIDTH
|
||||
#ifdef LCD_WIDTH_OVERRIDE
|
||||
#define LCD_WIDTH LCD_WIDTH_OVERRIDE
|
||||
#else
|
||||
#define LCD_WIDTH 22
|
||||
#endif
|
||||
#endif
|
||||
#ifndef LCD_HEIGHT
|
||||
#define LCD_HEIGHT 5
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(ULTIPANEL)
|
||||
#define NEWPANEL // Disable this if you actually have no click-encoder panel
|
||||
#define ULTRA_LCD
|
||||
#ifndef LCD_WIDTH
|
||||
#define LCD_WIDTH 20
|
||||
#endif
|
||||
#ifndef LCD_HEIGHT
|
||||
#define LCD_HEIGHT 4
|
||||
#endif
|
||||
#elif ENABLED(ULTRA_LCD) // no panel but just LCD
|
||||
#ifndef LCD_WIDTH
|
||||
#define LCD_WIDTH 16
|
||||
#endif
|
||||
#ifndef LCD_HEIGHT
|
||||
#define LCD_HEIGHT 2
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(DOGLCD)
|
||||
/* Custom characters defined in font dogm_font_data_Marlin_symbols.h / Marlin_symbols.fon */
|
||||
// \x00 intentionally skipped to avoid problems in strings
|
||||
#define LCD_STR_REFRESH "\x01"
|
||||
#define LCD_STR_FOLDER "\x02"
|
||||
#define LCD_STR_ARROW_RIGHT "\x03"
|
||||
#define LCD_STR_UPLEVEL "\x04"
|
||||
#define LCD_STR_CLOCK "\x05"
|
||||
#define LCD_STR_FEEDRATE "\x06"
|
||||
#define LCD_STR_BEDTEMP "\x07"
|
||||
#define LCD_STR_THERMOMETER "\x08"
|
||||
#define LCD_STR_DEGREE "\x09"
|
||||
|
||||
#define LCD_STR_SPECIAL_MAX '\x09'
|
||||
// Maximum here is 0x1F because 0x20 is ' ' (space) and the normal charsets begin.
|
||||
// Better stay below 0x10 because DISPLAY_CHARSET_HD44780_WESTERN begins here.
|
||||
|
||||
// Symbol characters
|
||||
#define LCD_STR_FILAM_DIA "\xf8"
|
||||
#define LCD_STR_FILAM_MUL "\xa4"
|
||||
#if ENABLED(SWITCHING_EXTRUDER) // One stepper for every two EXTRUDERS
|
||||
#if EXTRUDERS > 4
|
||||
#define E_STEPPERS 3
|
||||
#define E_MANUAL 3
|
||||
#elif EXTRUDERS > 2
|
||||
#define E_STEPPERS 2
|
||||
#define E_MANUAL 2
|
||||
#else
|
||||
// Custom characters defined in the first 8 characters of the LCD
|
||||
#define LCD_BEDTEMP_CHAR 0x00 // Print only as a char. This will have 'unexpected' results when used in a string!
|
||||
#define LCD_DEGREE_CHAR 0x01
|
||||
#define LCD_STR_THERMOMETER "\x02" // Still used with string concatenation
|
||||
#define LCD_UPLEVEL_CHAR 0x03
|
||||
#define LCD_STR_REFRESH "\x04"
|
||||
#define LCD_STR_FOLDER "\x05"
|
||||
#define LCD_FEEDRATE_CHAR 0x06
|
||||
#define LCD_CLOCK_CHAR 0x07
|
||||
#define LCD_STR_ARROW_RIGHT ">" /* from the default character set */
|
||||
#define E_STEPPERS 1
|
||||
#endif
|
||||
#define E_MANUAL EXTRUDERS
|
||||
#elif ENABLED(MIXING_EXTRUDER)
|
||||
#define E_STEPPERS MIXING_STEPPERS
|
||||
#define E_MANUAL 1
|
||||
#else
|
||||
#define E_STEPPERS EXTRUDERS
|
||||
#define E_MANUAL EXTRUDERS
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Default LCD contrast for dogm-like LCD displays
|
||||
*/
|
||||
#if ENABLED(DOGLCD)
|
||||
#define DO_SWITCH_EXTRUDER (ENABLED(SWITCHING_EXTRUDER) && (DISABLED(SWITCHING_NOZZLE) || SWITCHING_EXTRUDER_SERVO_NR != SWITCHING_NOZZLE_SERVO_NR))
|
||||
|
||||
#define HAS_LCD_CONTRAST ( \
|
||||
ENABLED(MAKRPANEL) \
|
||||
|| ENABLED(CARTESIO_UI) \
|
||||
|| ENABLED(VIKI2) \
|
||||
|| ENABLED(miniVIKI) \
|
||||
|| ENABLED(ELB_FULL_GRAPHIC_CONTROLLER) \
|
||||
)
|
||||
/**
|
||||
* DISTINCT_E_FACTORS affects how some E factors are accessed
|
||||
*/
|
||||
#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
|
||||
#define XYZE_N (XYZ + E_STEPPERS)
|
||||
#define E_AXIS_N (E_AXIS + extruder)
|
||||
#else
|
||||
#undef DISTINCT_E_FACTORS
|
||||
#define XYZE_N XYZE
|
||||
#define E_AXIS_N E_AXIS
|
||||
#endif
|
||||
|
||||
#if HAS_LCD_CONTRAST
|
||||
#ifndef LCD_CONTRAST_MIN
|
||||
#define LCD_CONTRAST_MIN 0
|
||||
#endif
|
||||
#ifndef LCD_CONTRAST_MAX
|
||||
#define LCD_CONTRAST_MAX 63
|
||||
#endif
|
||||
#ifndef DEFAULT_LCD_CONTRAST
|
||||
#define DEFAULT_LCD_CONTRAST 32
|
||||
#endif
|
||||
#endif
|
||||
/**
|
||||
* The BLTouch Probe emulates a servo probe
|
||||
* and uses "special" angles for its state.
|
||||
*/
|
||||
#if ENABLED(BLTOUCH)
|
||||
#ifndef Z_PROBE_SERVO_NR
|
||||
#define Z_PROBE_SERVO_NR 0
|
||||
#endif
|
||||
|
||||
#if ENABLED(NO_LCD_MENUS)
|
||||
#undef ULTIPANEL
|
||||
#undef NEWPANEL
|
||||
#ifndef NUM_SERVOS
|
||||
#define NUM_SERVOS (Z_PROBE_SERVO_NR + 1)
|
||||
#endif
|
||||
|
||||
// Boot screens
|
||||
#if DISABLED(ULTRA_LCD)
|
||||
#undef SHOW_BOOTSCREEN
|
||||
#elif !defined(BOOTSCREEN_TIMEOUT)
|
||||
#define BOOTSCREEN_TIMEOUT 2500
|
||||
#undef DEACTIVATE_SERVOS_AFTER_MOVE
|
||||
#if NUM_SERVOS == 1
|
||||
#undef SERVO_DELAY
|
||||
#define SERVO_DELAY { 50 }
|
||||
#endif
|
||||
|
||||
#define HAS_DEBUG_MENU (ENABLED(ULTIPANEL) && ENABLED(LCD_PROGRESS_BAR_TEST))
|
||||
|
||||
// MK2 Multiplexer forces SINGLENOZZLE and kills DISABLE_INACTIVE_EXTRUDER
|
||||
#if ENABLED(MK2_MULTIPLEXER)
|
||||
#define SINGLENOZZLE
|
||||
#undef DISABLE_INACTIVE_EXTRUDER
|
||||
#ifndef BLTOUCH_DELAY
|
||||
#define BLTOUCH_DELAY 375
|
||||
#endif
|
||||
#undef Z_SERVO_ANGLES
|
||||
#define Z_SERVO_ANGLES { BLTOUCH_DEPLOY, BLTOUCH_STOW }
|
||||
|
||||
/**
|
||||
* Extruders have some combination of stepper motors and hotends
|
||||
* so we separate these concepts into the defines:
|
||||
*
|
||||
* EXTRUDERS - Number of Selectable Tools
|
||||
* HOTENDS - Number of hotends, whether connected or separate
|
||||
* E_STEPPERS - Number of actual E stepper motors
|
||||
* E_MANUAL - Number of E steppers for LCD move options
|
||||
*
|
||||
*/
|
||||
#if ENABLED(SINGLENOZZLE) || ENABLED(MIXING_EXTRUDER) // One hotend, one thermistor, no XY offset
|
||||
#define HOTENDS 1
|
||||
#undef TEMP_SENSOR_1_AS_REDUNDANT
|
||||
#undef HOTEND_OFFSET_X
|
||||
#undef HOTEND_OFFSET_Y
|
||||
#else // Two hotends
|
||||
#define HOTENDS EXTRUDERS
|
||||
#if ENABLED(SWITCHING_NOZZLE) && !defined(HOTEND_OFFSET_Z)
|
||||
#define HOTEND_OFFSET_Z { 0 }
|
||||
#endif
|
||||
#endif
|
||||
#define BLTOUCH_DEPLOY 10
|
||||
#define BLTOUCH_STOW 90
|
||||
#define BLTOUCH_SELFTEST 120
|
||||
#define BLTOUCH_RESET 160
|
||||
#define _TEST_BLTOUCH(P) (READ(P##_PIN) != P##_ENDSTOP_INVERTING)
|
||||
|
||||
#if ENABLED(SWITCHING_EXTRUDER) // One stepper for every two EXTRUDERS
|
||||
#if EXTRUDERS > 4
|
||||
#define E_STEPPERS 3
|
||||
#define E_MANUAL 3
|
||||
#elif EXTRUDERS > 2
|
||||
#define E_STEPPERS 2
|
||||
#define E_MANUAL 2
|
||||
#else
|
||||
#define E_STEPPERS 1
|
||||
#endif
|
||||
#define E_MANUAL EXTRUDERS
|
||||
#elif ENABLED(MIXING_EXTRUDER)
|
||||
#define E_STEPPERS MIXING_STEPPERS
|
||||
#define E_MANUAL 1
|
||||
// Always disable probe pin inverting for BLTouch
|
||||
#undef Z_MIN_PROBE_ENDSTOP_INVERTING
|
||||
#define Z_MIN_PROBE_ENDSTOP_INVERTING false
|
||||
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
#undef Z_MIN_ENDSTOP_INVERTING
|
||||
#define Z_MIN_ENDSTOP_INVERTING Z_MIN_PROBE_ENDSTOP_INVERTING
|
||||
#define TEST_BLTOUCH() _TEST_BLTOUCH(Z_MIN)
|
||||
#else
|
||||
#define E_STEPPERS EXTRUDERS
|
||||
#define E_MANUAL EXTRUDERS
|
||||
#define TEST_BLTOUCH() _TEST_BLTOUCH(Z_MIN_PROBE)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* DISTINCT_E_FACTORS affects how some E factors are accessed
|
||||
*/
|
||||
#if ENABLED(DISTINCT_E_FACTORS) && E_STEPPERS > 1
|
||||
#define XYZE_N (XYZ + E_STEPPERS)
|
||||
#define E_AXIS_N (E_AXIS + extruder)
|
||||
#else
|
||||
#undef DISTINCT_E_FACTORS
|
||||
#define XYZE_N XYZE
|
||||
#define E_AXIS_N E_AXIS
|
||||
#endif
|
||||
/**
|
||||
* Set a flag for a servo probe
|
||||
*/
|
||||
#define HAS_Z_SERVO_PROBE (defined(Z_PROBE_SERVO_NR) && Z_PROBE_SERVO_NR >= 0)
|
||||
|
||||
/**
|
||||
* The BLTouch Probe emulates a servo probe
|
||||
* and uses "special" angles for its state.
|
||||
*/
|
||||
#if ENABLED(BLTOUCH)
|
||||
#ifndef Z_PROBE_SERVO_NR
|
||||
#define Z_PROBE_SERVO_NR 0
|
||||
#endif
|
||||
#ifndef NUM_SERVOS
|
||||
#define NUM_SERVOS (Z_PROBE_SERVO_NR + 1)
|
||||
#endif
|
||||
#undef DEACTIVATE_SERVOS_AFTER_MOVE
|
||||
#if NUM_SERVOS == 1
|
||||
#undef SERVO_DELAY
|
||||
#define SERVO_DELAY { 50 }
|
||||
#endif
|
||||
#ifndef BLTOUCH_DELAY
|
||||
#define BLTOUCH_DELAY 375
|
||||
#endif
|
||||
#undef Z_SERVO_ANGLES
|
||||
#define Z_SERVO_ANGLES { BLTOUCH_DEPLOY, BLTOUCH_STOW }
|
||||
/**
|
||||
* Set flags for enabled probes
|
||||
*/
|
||||
#define HAS_BED_PROBE (ENABLED(FIX_MOUNTED_PROBE) || ENABLED(Z_PROBE_ALLEN_KEY) || HAS_Z_SERVO_PROBE || ENABLED(Z_PROBE_SLED) || ENABLED(SOLENOID_PROBE))
|
||||
#define PROBE_SELECTED (HAS_BED_PROBE || ENABLED(PROBE_MANUALLY))
|
||||
|
||||
#define BLTOUCH_DEPLOY 10
|
||||
#define BLTOUCH_STOW 90
|
||||
#define BLTOUCH_SELFTEST 120
|
||||
#define BLTOUCH_RESET 160
|
||||
#define _TEST_BLTOUCH(P) (READ(P##_PIN) != P##_ENDSTOP_INVERTING)
|
||||
#if !HAS_BED_PROBE
|
||||
// Clear probe pin settings when no probe is selected
|
||||
#undef Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
|
||||
#undef Z_MIN_PROBE_ENDSTOP
|
||||
#elif ENABLED(Z_PROBE_ALLEN_KEY)
|
||||
// Extra test for Allen Key Probe
|
||||
#define PROBE_IS_TRIGGERED_WHEN_STOWED_TEST
|
||||
#endif
|
||||
|
||||
// Always disable probe pin inverting for BLTouch
|
||||
#undef Z_MIN_PROBE_ENDSTOP_INVERTING
|
||||
#define Z_MIN_PROBE_ENDSTOP_INVERTING false
|
||||
#define HOMING_Z_WITH_PROBE (HAS_BED_PROBE && Z_HOME_DIR < 0 && ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN))
|
||||
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
#undef Z_MIN_ENDSTOP_INVERTING
|
||||
#define Z_MIN_ENDSTOP_INVERTING Z_MIN_PROBE_ENDSTOP_INVERTING
|
||||
#define TEST_BLTOUCH() _TEST_BLTOUCH(Z_MIN)
|
||||
#else
|
||||
#define TEST_BLTOUCH() _TEST_BLTOUCH(Z_MIN_PROBE)
|
||||
#endif
|
||||
#endif
|
||||
#define HAS_SOFTWARE_ENDSTOPS (ENABLED(MIN_SOFTWARE_ENDSTOPS) || ENABLED(MAX_SOFTWARE_ENDSTOPS))
|
||||
#define HAS_RESUME_CONTINUE (ENABLED(NEWPANEL) || ENABLED(EMERGENCY_PARSER))
|
||||
#define HAS_COLOR_LEDS (ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED) || ENABLED(PCA9632) || ENABLED(NEOPIXEL_LED))
|
||||
|
||||
/**
|
||||
* Set a flag for a servo probe
|
||||
*/
|
||||
#define HAS_Z_SERVO_PROBE (defined(Z_PROBE_SERVO_NR) && Z_PROBE_SERVO_NR >= 0)
|
||||
|
||||
/**
|
||||
* Set flags for enabled probes
|
||||
*/
|
||||
#define HAS_BED_PROBE (ENABLED(FIX_MOUNTED_PROBE) || ENABLED(Z_PROBE_ALLEN_KEY) || HAS_Z_SERVO_PROBE || ENABLED(Z_PROBE_SLED) || ENABLED(SOLENOID_PROBE))
|
||||
#define PROBE_SELECTED (HAS_BED_PROBE || ENABLED(PROBE_MANUALLY))
|
||||
|
||||
#if !HAS_BED_PROBE
|
||||
// Clear probe pin settings when no probe is selected
|
||||
#undef Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN
|
||||
#undef Z_MIN_PROBE_ENDSTOP
|
||||
#elif ENABLED(Z_PROBE_ALLEN_KEY)
|
||||
// Extra test for Allen Key Probe
|
||||
#define PROBE_IS_TRIGGERED_WHEN_STOWED_TEST
|
||||
#endif
|
||||
|
||||
#define HOMING_Z_WITH_PROBE (HAS_BED_PROBE && Z_HOME_DIR < 0 && ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN))
|
||||
|
||||
#define HAS_SOFTWARE_ENDSTOPS (ENABLED(MIN_SOFTWARE_ENDSTOPS) || ENABLED(MAX_SOFTWARE_ENDSTOPS))
|
||||
#define HAS_RESUME_CONTINUE (ENABLED(NEWPANEL) || ENABLED(EMERGENCY_PARSER))
|
||||
#define HAS_COLOR_LEDS (ENABLED(BLINKM) || ENABLED(RGB_LED) || ENABLED(RGBW_LED) || ENABLED(PCA9632) || ENABLED(NEOPIXEL_LED))
|
||||
#define USE_MARLINSERIAL !(defined(__AVR__) && defined(USBCON))
|
||||
|
||||
#endif // CONDITIONALS_LCD_H
|
||||
|
||||
+1192
-1175
File diff suppressed because it is too large
Load Diff
@@ -30,7 +30,7 @@
|
||||
/*
|
||||
* Enables a filament sensor plugged into the laser pin. Disables the laser
|
||||
*/
|
||||
#define FilamentSensor
|
||||
//#define FilamentSensor
|
||||
/**
|
||||
* Configuration.h
|
||||
*
|
||||
|
||||
@@ -134,9 +134,6 @@
|
||||
// External references
|
||||
|
||||
extern Planner planner;
|
||||
#if ENABLED(ULTRA_LCD)
|
||||
extern char lcd_status_message[];
|
||||
#endif
|
||||
|
||||
// Private functions
|
||||
|
||||
@@ -158,7 +155,7 @@
|
||||
|
||||
static int8_t g26_prime_flag;
|
||||
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
|
||||
/**
|
||||
* If the LCD is clicked, cancel, wait for release, return true
|
||||
@@ -183,9 +180,9 @@
|
||||
|
||||
void G26_line_to_destination(const float &feed_rate) {
|
||||
const float save_feedrate = feedrate_mm_s;
|
||||
feedrate_mm_s = feed_rate; // use specified feed rate
|
||||
feedrate_mm_s = feed_rate;
|
||||
prepare_move_to_destination(); // will ultimately call ubl.line_to_destination_cartesian or ubl.prepare_linear_move_to for UBL_SEGMENTED
|
||||
feedrate_mm_s = save_feedrate; // restore global feed rate
|
||||
feedrate_mm_s = save_feedrate;
|
||||
}
|
||||
|
||||
void move_to(const float &rx, const float &ry, const float &z, const float &e_delta) {
|
||||
@@ -242,7 +239,7 @@
|
||||
*/
|
||||
inline bool prime_nozzle() {
|
||||
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
float Total_Prime = 0.0;
|
||||
|
||||
if (g26_prime_flag == -1) { // The user wants to control how much filament gets purged
|
||||
@@ -264,7 +261,7 @@
|
||||
#endif
|
||||
G26_line_to_destination(planner.max_feedrate_mm_s[E_AXIS] / 15.0);
|
||||
set_destination_from_current();
|
||||
stepper.synchronize(); // Without this synchronize, the purge is more consistent,
|
||||
planner.synchronize(); // Without this synchronize, the purge is more consistent,
|
||||
// but because the planner has a buffer, we won't be able
|
||||
// to stop as quickly. So we put up with the less smooth
|
||||
// action to give the user a more responsive 'Stop'.
|
||||
@@ -274,8 +271,6 @@
|
||||
|
||||
wait_for_release();
|
||||
|
||||
strcpy_P(lcd_status_message, PSTR("Done Priming")); // Hack to get the message up. May be obsolete.
|
||||
|
||||
lcd_setstatusPGM(PSTR("Done Priming"), 99);
|
||||
lcd_quick_feedback(true);
|
||||
lcd_external_control = false;
|
||||
@@ -363,7 +358,7 @@
|
||||
|
||||
// If the end point of the line is closer to the nozzle, flip the direction,
|
||||
// moving from the end to the start. On very small lines the optimization isn't worth it.
|
||||
if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < FABS(line_length))
|
||||
if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length))
|
||||
return print_line_from_here_to_there(ex, ey, ez, sx, sy, sz);
|
||||
|
||||
// Decide whether to retract & bump
|
||||
@@ -389,7 +384,7 @@
|
||||
for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
|
||||
for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
|
||||
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
if (user_canceled()) return true; // Check if the user wants to stop the Mesh Validation
|
||||
#endif
|
||||
|
||||
@@ -480,14 +475,14 @@
|
||||
if (g26_bed_temp > 25) {
|
||||
lcd_setstatusPGM(PSTR("G26 Heating Bed."), 99);
|
||||
lcd_quick_feedback(true);
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
lcd_external_control = true;
|
||||
#endif
|
||||
#endif
|
||||
thermalManager.setTargetBed(g26_bed_temp);
|
||||
while (abs(thermalManager.degBed() - g26_bed_temp) > 3) {
|
||||
while (ABS(thermalManager.degBed() - g26_bed_temp) > 3) {
|
||||
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
if (is_lcd_clicked()) return exit_from_g26();
|
||||
#endif
|
||||
|
||||
@@ -508,9 +503,9 @@
|
||||
|
||||
// Start heating the nozzle and wait for it to reach temperature.
|
||||
thermalManager.setTargetHotend(g26_hotend_temp, 0);
|
||||
while (abs(thermalManager.degHotend(0) - g26_hotend_temp) > 3) {
|
||||
while (ABS(thermalManager.degHotend(0) - g26_hotend_temp) > 3) {
|
||||
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
if (is_lcd_clicked()) return exit_from_g26();
|
||||
#endif
|
||||
|
||||
@@ -623,7 +618,7 @@
|
||||
|
||||
if (parser.seen('P')) {
|
||||
if (!parser.has_value()) {
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
g26_prime_flag = -1;
|
||||
#else
|
||||
SERIAL_PROTOCOLLNPGM("?Prime length must be specified when not using an LCD.");
|
||||
@@ -668,7 +663,7 @@
|
||||
}
|
||||
|
||||
int16_t g26_repeats;
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
g26_repeats = parser.intval('R', GRID_MAX_POINTS + 1);
|
||||
#else
|
||||
if (!parser.seen('R')) {
|
||||
@@ -727,27 +722,31 @@
|
||||
move_to(destination, 0.0);
|
||||
move_to(destination, g26_ooze_amount);
|
||||
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
lcd_external_control = true;
|
||||
#endif
|
||||
|
||||
//debug_current_and_destination(PSTR("Starting G26 Mesh Validation Pattern."));
|
||||
|
||||
/**
|
||||
* Pre-generate radius offset values at 30 degree intervals to reduce CPU load.
|
||||
*/
|
||||
#define A_INT 30
|
||||
#define _ANGS (360 / A_INT)
|
||||
#define A_CNT (_ANGS / 2)
|
||||
#define _IND(A) ((A + _ANGS * 8) % _ANGS)
|
||||
#define _COS(A) (trig_table[_IND(A) % A_CNT] * (_IND(A) >= A_CNT ? -1 : 1))
|
||||
#define _SIN(A) (-_COS((A + A_CNT / 2) % _ANGS))
|
||||
#if A_CNT & 1
|
||||
#error "A_CNT must be a positive value. Please change A_INT."
|
||||
#endif
|
||||
float trig_table[A_CNT];
|
||||
for (uint8_t i = 0; i < A_CNT; i++)
|
||||
trig_table[i] = INTERSECTION_CIRCLE_RADIUS * cos(RADIANS(i * A_INT));
|
||||
#if DISABLED(ARC_SUPPORT)
|
||||
|
||||
/**
|
||||
* Pre-generate radius offset values at 30 degree intervals to reduce CPU load.
|
||||
*/
|
||||
#define A_INT 30
|
||||
#define _ANGS (360 / A_INT)
|
||||
#define A_CNT (_ANGS / 2)
|
||||
#define _IND(A) ((A + _ANGS * 8) % _ANGS)
|
||||
#define _COS(A) (trig_table[_IND(A) % A_CNT] * (_IND(A) >= A_CNT ? -1 : 1))
|
||||
#define _SIN(A) (-_COS((A + A_CNT / 2) % _ANGS))
|
||||
#if A_CNT & 1
|
||||
#error "A_CNT must be a positive value. Please change A_INT."
|
||||
#endif
|
||||
float trig_table[A_CNT];
|
||||
for (uint8_t i = 0; i < A_CNT; i++)
|
||||
trig_table[i] = INTERSECTION_CIRCLE_RADIUS * cos(RADIANS(i * A_INT));
|
||||
|
||||
#endif // !ARC_SUPPORT
|
||||
|
||||
mesh_index_pair location;
|
||||
do {
|
||||
@@ -766,52 +765,127 @@
|
||||
// which is always drawn counter-clockwise.
|
||||
const uint8_t xi = location.x_index, yi = location.y_index;
|
||||
const bool f = yi == 0, r = xi >= GRID_MAX_POINTS_X - 1, b = yi >= GRID_MAX_POINTS_Y - 1;
|
||||
int8_t start_ind = -2, end_ind = 9; // Assume a full circle (from 5:00 to 5:00)
|
||||
if (xi == 0) { // Left edge? Just right half.
|
||||
start_ind = f ? 0 : -3; // 03:00 to 12:00 for front-left
|
||||
end_ind = b ? 0 : 2; // 06:00 to 03:00 for back-left
|
||||
}
|
||||
else if (r) { // Right edge? Just left half.
|
||||
start_ind = b ? 6 : 3; // 12:00 to 09:00 for front-right
|
||||
end_ind = f ? 5 : 8; // 09:00 to 06:00 for back-right
|
||||
}
|
||||
else if (f) { // Front edge? Just back half.
|
||||
start_ind = 0; // 03:00
|
||||
end_ind = 5; // 09:00
|
||||
}
|
||||
else if (b) { // Back edge? Just front half.
|
||||
start_ind = 6; // 09:00
|
||||
end_ind = 11; // 03:00
|
||||
}
|
||||
|
||||
for (int8_t ind = start_ind; ind <= end_ind; ind++) {
|
||||
#if ENABLED(ARC_SUPPORT)
|
||||
|
||||
#if ENABLED(NEWPANEL)
|
||||
if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
|
||||
#define ARC_LENGTH(quarters) (INTERSECTION_CIRCLE_RADIUS * M_PI * (quarters) / 2)
|
||||
float sx = circle_x + INTERSECTION_CIRCLE_RADIUS, // default to full circle
|
||||
ex = circle_x + INTERSECTION_CIRCLE_RADIUS,
|
||||
sy = circle_y, ey = circle_y,
|
||||
arc_length = ARC_LENGTH(4);
|
||||
|
||||
// Figure out where to start and end the arc - we always print counterclockwise
|
||||
if (xi == 0) { // left edge
|
||||
sx = f ? circle_x + INTERSECTION_CIRCLE_RADIUS : circle_x;
|
||||
ex = b ? circle_x + INTERSECTION_CIRCLE_RADIUS : circle_x;
|
||||
sy = f ? circle_y : circle_y - INTERSECTION_CIRCLE_RADIUS;
|
||||
ey = b ? circle_y : circle_y + INTERSECTION_CIRCLE_RADIUS;
|
||||
arc_length = (f || b) ? ARC_LENGTH(1) : ARC_LENGTH(2);
|
||||
}
|
||||
else if (r) { // right edge
|
||||
sx = b ? circle_x - INTERSECTION_CIRCLE_RADIUS : circle_x;
|
||||
ex = f ? circle_x - INTERSECTION_CIRCLE_RADIUS : circle_x;
|
||||
sy = b ? circle_y : circle_y + INTERSECTION_CIRCLE_RADIUS;
|
||||
ey = f ? circle_y : circle_y - INTERSECTION_CIRCLE_RADIUS;
|
||||
arc_length = (f || b) ? ARC_LENGTH(1) : ARC_LENGTH(2);
|
||||
}
|
||||
else if (f) {
|
||||
sx = circle_x + INTERSECTION_CIRCLE_RADIUS;
|
||||
ex = circle_x - INTERSECTION_CIRCLE_RADIUS;
|
||||
sy = ey = circle_y;
|
||||
arc_length = ARC_LENGTH(2);
|
||||
}
|
||||
else if (b) {
|
||||
sx = circle_x - INTERSECTION_CIRCLE_RADIUS;
|
||||
ex = circle_x + INTERSECTION_CIRCLE_RADIUS;
|
||||
sy = ey = circle_y;
|
||||
arc_length = ARC_LENGTH(2);
|
||||
}
|
||||
const float arc_offset[2] = {
|
||||
circle_x - sx,
|
||||
circle_y - sy
|
||||
};
|
||||
|
||||
const float dx_s = current_position[X_AXIS] - sx, // find our distance from the start of the actual circle
|
||||
dy_s = current_position[Y_AXIS] - sy,
|
||||
dist_start = HYPOT2(dx_s, dy_s);
|
||||
const float endpoint[XYZE] = {
|
||||
ex, ey,
|
||||
g26_layer_height,
|
||||
current_position[E_AXIS] + (arc_length * g26_e_axis_feedrate * g26_extrusion_multiplier)
|
||||
};
|
||||
|
||||
if (dist_start > 2.0) {
|
||||
retract_filament(destination);
|
||||
//todo: parameterize the bump height with a define
|
||||
move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + 0.500, 0.0); // Z bump to minimize scraping
|
||||
move_to(sx, sy, g26_layer_height + 0.500, 0.0); // Get to the starting point with no extrusion while bumped
|
||||
}
|
||||
|
||||
move_to(sx, sy, g26_layer_height, 0.0); // Get to the starting point with no extrusion / un-Z bump
|
||||
|
||||
recover_filament(destination);
|
||||
const float save_feedrate = feedrate_mm_s;
|
||||
feedrate_mm_s = PLANNER_XY_FEEDRATE() / 10.0;
|
||||
plan_arc(endpoint, arc_offset, false); // Draw a counter-clockwise arc
|
||||
feedrate_mm_s = save_feedrate;
|
||||
set_destination_from_current();
|
||||
#if ENABLED(ULTIPANEL)
|
||||
if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
|
||||
#endif
|
||||
|
||||
float rx = circle_x + _COS(ind), // For speed, these are now a lookup table entry
|
||||
ry = circle_y + _SIN(ind),
|
||||
xe = circle_x + _COS(ind + 1),
|
||||
ye = circle_y + _SIN(ind + 1);
|
||||
#else // !ARC_SUPPORT
|
||||
|
||||
#if IS_KINEMATIC
|
||||
// Check to make sure this segment is entirely on the bed, skip if not.
|
||||
if (!position_is_reachable(rx, ry) || !position_is_reachable(xe, ye)) continue;
|
||||
#else // not, we need to skip
|
||||
rx = constrain(rx, X_MIN_POS + 1, X_MAX_POS - 1); // This keeps us from bumping the endstops
|
||||
ry = constrain(ry, Y_MIN_POS + 1, Y_MAX_POS - 1);
|
||||
xe = constrain(xe, X_MIN_POS + 1, X_MAX_POS - 1);
|
||||
ye = constrain(ye, Y_MIN_POS + 1, Y_MAX_POS - 1);
|
||||
#endif
|
||||
int8_t start_ind = -2, end_ind = 9; // Assume a full circle (from 5:00 to 5:00)
|
||||
if (xi == 0) { // Left edge? Just right half.
|
||||
start_ind = f ? 0 : -3; // 03:00 to 12:00 for front-left
|
||||
end_ind = b ? 0 : 2; // 06:00 to 03:00 for back-left
|
||||
}
|
||||
else if (r) { // Right edge? Just left half.
|
||||
start_ind = b ? 6 : 3; // 12:00 to 09:00 for front-right
|
||||
end_ind = f ? 5 : 8; // 09:00 to 06:00 for back-right
|
||||
}
|
||||
else if (f) { // Front edge? Just back half.
|
||||
start_ind = 0; // 03:00
|
||||
end_ind = 5; // 09:00
|
||||
}
|
||||
else if (b) { // Back edge? Just front half.
|
||||
start_ind = 6; // 09:00
|
||||
end_ind = 11; // 03:00
|
||||
}
|
||||
|
||||
print_line_from_here_to_there(rx, ry, g26_layer_height, xe, ye, g26_layer_height);
|
||||
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
|
||||
}
|
||||
if (look_for_lines_to_connect())
|
||||
goto LEAVE;
|
||||
for (int8_t ind = start_ind; ind <= end_ind; ind++) {
|
||||
|
||||
#if ENABLED(ULTIPANEL)
|
||||
if (user_canceled()) goto LEAVE; // Check if the user wants to stop the Mesh Validation
|
||||
#endif
|
||||
|
||||
float rx = circle_x + _COS(ind), // For speed, these are now a lookup table entry
|
||||
ry = circle_y + _SIN(ind),
|
||||
xe = circle_x + _COS(ind + 1),
|
||||
ye = circle_y + _SIN(ind + 1);
|
||||
|
||||
#if IS_KINEMATIC
|
||||
// Check to make sure this segment is entirely on the bed, skip if not.
|
||||
if (!position_is_reachable(rx, ry) || !position_is_reachable(xe, ye)) continue;
|
||||
#else // not, we need to skip
|
||||
rx = constrain(rx, X_MIN_POS + 1, X_MAX_POS - 1); // This keeps us from bumping the endstops
|
||||
ry = constrain(ry, Y_MIN_POS + 1, Y_MAX_POS - 1);
|
||||
xe = constrain(xe, X_MIN_POS + 1, X_MAX_POS - 1);
|
||||
ye = constrain(ye, Y_MIN_POS + 1, Y_MAX_POS - 1);
|
||||
#endif
|
||||
|
||||
print_line_from_here_to_there(rx, ry, g26_layer_height, xe, ye, g26_layer_height);
|
||||
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
|
||||
}
|
||||
|
||||
#endif // !ARC_SUPPORT
|
||||
|
||||
if (look_for_lines_to_connect()) goto LEAVE;
|
||||
}
|
||||
|
||||
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
|
||||
|
||||
} while (--g26_repeats && location.x_index >= 0 && location.y_index >= 0);
|
||||
|
||||
LEAVE:
|
||||
@@ -831,7 +905,7 @@
|
||||
move_to(destination, 0); // Move back to the starting position
|
||||
//debug_current_and_destination(PSTR("done doing X/Y move."));
|
||||
|
||||
#if ENABLED(NEWPANEL)
|
||||
#if ENABLED(ULTIPANEL)
|
||||
lcd_external_control = false; // Give back control of the LCD Panel!
|
||||
#endif
|
||||
|
||||
|
||||
+305
@@ -0,0 +1,305 @@
|
||||
/* **************************************************************************
|
||||
|
||||
Marlin 3D Printer Firmware
|
||||
Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
|
||||
Copyright (c) 2016 Bob Cousins bobcousins42@googlemail.com
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
* Description: HAL for __AVR__
|
||||
*/
|
||||
|
||||
#ifndef _HAL_AVR_H_
|
||||
#define _HAL_AVR_H_
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Includes
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#include "fastio.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <Arduino.h>
|
||||
#include <util/delay.h>
|
||||
#include <avr/eeprom.h>
|
||||
#include <avr/pgmspace.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/io.h>
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Defines
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//#define analogInputToDigitalPin(IO) IO
|
||||
|
||||
// Bracket code that shouldn't be interrupted
|
||||
#ifndef CRITICAL_SECTION_START
|
||||
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
|
||||
#define CRITICAL_SECTION_END SREG = _sreg;
|
||||
#endif
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Types
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
typedef uint16_t hal_timer_t;
|
||||
#define HAL_TIMER_TYPE_MAX 0xFFFF
|
||||
|
||||
typedef int8_t pin_t;
|
||||
|
||||
#define HAL_SERVO_LIB Servo
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public Variables
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//extern uint8_t MCUSR;
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Public functions
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//void cli(void);
|
||||
|
||||
//void _delay_ms(const int delay);
|
||||
|
||||
inline void HAL_clear_reset_source(void) { MCUSR = 0; }
|
||||
inline uint8_t HAL_get_reset_source(void) { return MCUSR; }
|
||||
|
||||
// eeprom
|
||||
//void eeprom_write_byte(unsigned char *pos, unsigned char value);
|
||||
//unsigned char eeprom_read_byte(unsigned char *pos);
|
||||
|
||||
// timers
|
||||
#define HAL_TIMER_RATE ((F_CPU) / 8) // i.e., 2MHz or 2.5MHz
|
||||
|
||||
#define STEP_TIMER_NUM 1
|
||||
#define TEMP_TIMER_NUM 0
|
||||
#define PULSE_TIMER_NUM TEMP_TIMER_NUM
|
||||
|
||||
#define HAL_STEPPER_TIMER_RATE HAL_TIMER_RATE
|
||||
#define HAL_TICKS_PER_US ((HAL_STEPPER_TIMER_RATE) / 1000000) // Cannot be of type double
|
||||
#define STEPPER_TIMER_PRESCALE 8
|
||||
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
|
||||
|
||||
#define TEMP_TIMER_FREQUENCY ((F_CPU) / 64.0 / 256.0)
|
||||
|
||||
#define TIMER_OCR_1 OCR1A
|
||||
#define TIMER_COUNTER_1 TCNT1
|
||||
|
||||
#define TIMER_OCR_0 OCR0A
|
||||
#define TIMER_COUNTER_0 TCNT0
|
||||
|
||||
#define PULSE_TIMER_PRESCALE 8
|
||||
|
||||
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
|
||||
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
|
||||
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
|
||||
|
||||
#define ENABLE_TEMPERATURE_INTERRUPT() SBI(TIMSK0, OCIE0B)
|
||||
#define DISABLE_TEMPERATURE_INTERRUPT() CBI(TIMSK0, OCIE0B)
|
||||
#define TEMPERATURE_ISR_ENABLED() TEST(TIMSK0, OCIE0B)
|
||||
|
||||
#define HAL_timer_start(timer_num, frequency)
|
||||
|
||||
#define _CAT(a, ...) a ## __VA_ARGS__
|
||||
#define HAL_timer_set_compare(timer, compare) (_CAT(TIMER_OCR_, timer) = compare)
|
||||
#define HAL_timer_restrain(timer, interval_ticks) NOLESS(_CAT(TIMER_OCR_, timer), _CAT(TIMER_COUNTER_, timer) + interval_ticks)
|
||||
|
||||
#define HAL_timer_get_compare(timer) _CAT(TIMER_OCR_, timer)
|
||||
#define HAL_timer_get_count(timer) _CAT(TIMER_COUNTER_, timer)
|
||||
|
||||
/**
|
||||
* On AVR there is no hardware prioritization and preemption of
|
||||
* interrupts, so this emulates it. The UART has first priority
|
||||
* (otherwise, characters will be lost due to UART overflow).
|
||||
* Then: Stepper, Endstops, Temperature, and -finally- all others.
|
||||
*/
|
||||
#define HAL_timer_isr_prologue(TIMER_NUM)
|
||||
#define HAL_timer_isr_epilogue(TIMER_NUM)
|
||||
|
||||
/* 18 cycles maximum latency */
|
||||
#define HAL_STEP_TIMER_ISR \
|
||||
extern "C" void TIMER1_COMPA_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
|
||||
extern "C" void TIMER1_COMPA_vect_bottom (void) asm ("TIMER1_COMPA_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
|
||||
void TIMER1_COMPA_vect (void) { \
|
||||
__asm__ __volatile__ ( \
|
||||
A("push r16") /* 2 Save R16 */ \
|
||||
A("in r16, __SREG__") /* 1 Get SREG */ \
|
||||
A("push r16") /* 2 Save SREG into stack */ \
|
||||
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
|
||||
A("push r16") /* 2 Save TIMSK0 into the stack */ \
|
||||
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
|
||||
A("sts %[timsk0], r16") /* 2 And set the new value */ \
|
||||
A("lds r16, %[timsk1]") /* 2 Load into R0 the stepper timer Interrupt mask register [TIMSK1] */ \
|
||||
A("andi r16,~%[msk1]") /* 1 Disable the stepper ISR */ \
|
||||
A("sts %[timsk1], r16") /* 2 And set the new value */ \
|
||||
A("sei") /* 1 Enable global interrupts - stepper and temperature ISRs are disabled, so no risk of reentry or being preempted by the temperature ISR */ \
|
||||
A("push r16") /* 2 Save TIMSK1 into stack */ \
|
||||
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
|
||||
A("push r16") /* 2 Save RAMPZ into stack */ \
|
||||
A("in r16, 0x3C") /* 1 Get EIND register */ \
|
||||
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
|
||||
A("push r1") \
|
||||
A("push r18") \
|
||||
A("push r19") \
|
||||
A("push r20") \
|
||||
A("push r21") \
|
||||
A("push r22") \
|
||||
A("push r23") \
|
||||
A("push r24") \
|
||||
A("push r25") \
|
||||
A("push r26") \
|
||||
A("push r27") \
|
||||
A("push r30") \
|
||||
A("push r31") \
|
||||
A("clr r1") /* C runtime expects this register to be 0 */ \
|
||||
A("call TIMER1_COMPA_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
|
||||
A("pop r31") \
|
||||
A("pop r30") \
|
||||
A("pop r27") \
|
||||
A("pop r26") \
|
||||
A("pop r25") \
|
||||
A("pop r24") \
|
||||
A("pop r23") \
|
||||
A("pop r22") \
|
||||
A("pop r21") \
|
||||
A("pop r20") \
|
||||
A("pop r19") \
|
||||
A("pop r18") \
|
||||
A("pop r1") \
|
||||
A("pop r0") \
|
||||
A("out 0x3C, r16") /* 1 Restore EIND register */ \
|
||||
A("pop r16") /* 2 Get the original RAMPZ register value */ \
|
||||
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
|
||||
A("pop r16") /* 2 Get the original TIMSK1 value but with stepper ISR disabled */ \
|
||||
A("ori r16,%[msk1]") /* 1 Reenable the stepper ISR */ \
|
||||
A("cli") /* 1 Disable global interrupts - Reenabling Stepper ISR can reenter amd temperature can reenter, and we want that, if it happens, after this ISR has ended */ \
|
||||
A("sts %[timsk1], r16") /* 2 And restore the old value - This reenables the stepper ISR */ \
|
||||
A("pop r16") /* 2 Get the temperature timer Interrupt mask register [TIMSK0] */ \
|
||||
A("sts %[timsk0], r16") /* 2 And restore the old value - This reenables the temperature ISR */ \
|
||||
A("pop r16") /* 2 Get the old SREG value */ \
|
||||
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
|
||||
A("pop r16") /* 2 Restore R16 value */ \
|
||||
A("reti") /* 4 Return from interrupt */ \
|
||||
: \
|
||||
: [timsk0] "i" ((uint16_t)&TIMSK0), \
|
||||
[timsk1] "i" ((uint16_t)&TIMSK1), \
|
||||
[msk0] "M" ((uint8_t)(1<<OCIE0B)),\
|
||||
[msk1] "M" ((uint8_t)(1<<OCIE1A)) \
|
||||
: \
|
||||
); \
|
||||
} \
|
||||
void TIMER1_COMPA_vect_bottom(void)
|
||||
|
||||
/* 14 cycles maximum latency */
|
||||
#define HAL_TEMP_TIMER_ISR \
|
||||
extern "C" void TIMER0_COMPB_vect (void) __attribute__ ((signal, naked, used, externally_visible)); \
|
||||
extern "C" void TIMER0_COMPB_vect_bottom(void) asm ("TIMER0_COMPB_vect_bottom") __attribute__ ((used, externally_visible, noinline)); \
|
||||
void TIMER0_COMPB_vect (void) { \
|
||||
__asm__ __volatile__ ( \
|
||||
A("push r16") /* 2 Save R16 */ \
|
||||
A("in r16, __SREG__") /* 1 Get SREG */ \
|
||||
A("push r16") /* 2 Save SREG into stack */ \
|
||||
A("lds r16, %[timsk0]") /* 2 Load into R0 the Temperature timer Interrupt mask register */ \
|
||||
A("andi r16,~%[msk0]") /* 1 Disable the temperature ISR */ \
|
||||
A("sts %[timsk0], r16") /* 2 And set the new value */ \
|
||||
A("sei") /* 1 Enable global interrupts - It is safe, as the temperature ISR is disabled, so we cannot reenter it */ \
|
||||
A("push r16") /* 2 Save TIMSK0 into stack */ \
|
||||
A("in r16, 0x3B") /* 1 Get RAMPZ register */ \
|
||||
A("push r16") /* 2 Save RAMPZ into stack */ \
|
||||
A("in r16, 0x3C") /* 1 Get EIND register */ \
|
||||
A("push r0") /* C runtime can modify all the following registers without restoring them */ \
|
||||
A("push r1") \
|
||||
A("push r18") \
|
||||
A("push r19") \
|
||||
A("push r20") \
|
||||
A("push r21") \
|
||||
A("push r22") \
|
||||
A("push r23") \
|
||||
A("push r24") \
|
||||
A("push r25") \
|
||||
A("push r26") \
|
||||
A("push r27") \
|
||||
A("push r30") \
|
||||
A("push r31") \
|
||||
A("clr r1") /* C runtime expects this register to be 0 */ \
|
||||
A("call TIMER0_COMPB_vect_bottom") /* Call the bottom handler - No inlining allowed, otherwise registers used are not saved */ \
|
||||
A("pop r31") \
|
||||
A("pop r30") \
|
||||
A("pop r27") \
|
||||
A("pop r26") \
|
||||
A("pop r25") \
|
||||
A("pop r24") \
|
||||
A("pop r23") \
|
||||
A("pop r22") \
|
||||
A("pop r21") \
|
||||
A("pop r20") \
|
||||
A("pop r19") \
|
||||
A("pop r18") \
|
||||
A("pop r1") \
|
||||
A("pop r0") \
|
||||
A("out 0x3C, r16") /* 1 Restore EIND register */ \
|
||||
A("pop r16") /* 2 Get the original RAMPZ register value */ \
|
||||
A("out 0x3B, r16") /* 1 Restore RAMPZ register to its original value */ \
|
||||
A("pop r16") /* 2 Get the original TIMSK0 value but with temperature ISR disabled */ \
|
||||
A("ori r16,%[msk0]") /* 1 Enable temperature ISR */ \
|
||||
A("cli") /* 1 Disable global interrupts - We must do this, as we will reenable the temperature ISR, and we don´t want to reenter this handler until the current one is done */ \
|
||||
A("sts %[timsk0], r16") /* 2 And restore the old value */ \
|
||||
A("pop r16") /* 2 Get the old SREG */ \
|
||||
A("out __SREG__, r16") /* 1 And restore the SREG value */ \
|
||||
A("pop r16") /* 2 Restore R16 */ \
|
||||
A("reti") /* 4 Return from interrupt */ \
|
||||
: \
|
||||
: [timsk0] "i"((uint16_t)&TIMSK0), \
|
||||
[msk0] "M" ((uint8_t)(1<<OCIE0B)) \
|
||||
: \
|
||||
); \
|
||||
} \
|
||||
void TIMER0_COMPB_vect_bottom(void)
|
||||
|
||||
// ADC
|
||||
#ifdef DIDR2
|
||||
#define HAL_ANALOG_SELECT(pin) do{ if (pin < 8) SBI(DIDR0, pin); else SBI(DIDR2, pin & 0x07); }while(0)
|
||||
#else
|
||||
#define HAL_ANALOG_SELECT(pin) do{ SBI(DIDR0, pin); }while(0)
|
||||
#endif
|
||||
|
||||
inline void HAL_adc_init(void) {
|
||||
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
|
||||
DIDR0 = 0;
|
||||
#ifdef DIDR2
|
||||
DIDR2 = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
|
||||
#ifdef MUX5
|
||||
#define HAL_START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
|
||||
#else
|
||||
#define HAL_START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
|
||||
#endif
|
||||
|
||||
#define HAL_READ_ADC ADC
|
||||
|
||||
#define GET_PIN_MAP_PIN(index) index
|
||||
#define GET_PIN_MAP_INDEX(pin) pin
|
||||
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
|
||||
|
||||
#define HAL_SENSITIVE_PINS 0, 1
|
||||
|
||||
#endif // _HAL_AVR_H_
|
||||
@@ -99,7 +99,7 @@
|
||||
|
||||
//the encoder likely lost its place when the error occured, so we'll reset and use the printer's
|
||||
//idea of where it the axis is to re-initialise
|
||||
float position = stepper.get_axis_position_mm(encoderAxis);
|
||||
float position = planner.get_axis_position_mm(encoderAxis);
|
||||
int32_t positionInTicks = position * get_ticks_unit();
|
||||
|
||||
//shift position from previous to current position
|
||||
@@ -134,7 +134,7 @@
|
||||
|
||||
#ifdef I2CPE_EC_THRESH_PROPORTIONAL
|
||||
const millis_t deltaTime = positionTime - lastPositionTime;
|
||||
const uint32_t distance = abs(position - lastPosition),
|
||||
const uint32_t distance = ABS(position - lastPosition),
|
||||
speed = distance / deltaTime;
|
||||
const float threshold = constrain((speed / 50), 1, 50) * ecThreshold;
|
||||
#else
|
||||
@@ -150,7 +150,7 @@
|
||||
|
||||
LOOP_L_N(i, I2CPE_ERR_ARRAY_SIZE) {
|
||||
sum += err[i];
|
||||
if (i) diffSum += abs(err[i-1] - err[i]);
|
||||
if (i) diffSum += ABS(err[i-1] - err[i]);
|
||||
}
|
||||
|
||||
const int32_t error = int32_t(sum / (I2CPE_ERR_ARRAY_SIZE + 1)); //calculate average for error
|
||||
@@ -163,7 +163,7 @@
|
||||
//SERIAL_ECHOLN(error);
|
||||
|
||||
#ifdef I2CPE_ERR_THRESH_ABORT
|
||||
if (labs(error) > I2CPE_ERR_THRESH_ABORT * planner.axis_steps_per_mm[encoderAxis]) {
|
||||
if (ABS(error) > I2CPE_ERR_THRESH_ABORT * planner.axis_steps_per_mm[encoderAxis]) {
|
||||
//kill("Significant Error");
|
||||
SERIAL_ECHOPGM("Axis error greater than set threshold, aborting!");
|
||||
SERIAL_ECHOLN(error);
|
||||
@@ -175,8 +175,8 @@
|
||||
if (errIdx == 0) {
|
||||
// In order to correct for "error" but avoid correcting for noise and non-skips
|
||||
// it must be > threshold and have a difference average of < 10 and be < 2000 steps
|
||||
if (labs(error) > threshold * planner.axis_steps_per_mm[encoderAxis] &&
|
||||
diffSum < 10 * (I2CPE_ERR_ARRAY_SIZE - 1) && labs(error) < 2000) { // Check for persistent error (skip)
|
||||
if (ABS(error) > threshold * planner.axis_steps_per_mm[encoderAxis] &&
|
||||
diffSum < 10 * (I2CPE_ERR_ARRAY_SIZE - 1) && ABS(error) < 2000) { // Check for persistent error (skip)
|
||||
errPrst[errPrstIdx++] = error; // Error must persist for I2CPE_ERR_PRST_ARRAY_SIZE error cycles. This also serves to improve the average accuracy
|
||||
if (errPrstIdx >= I2CPE_ERR_PRST_ARRAY_SIZE) {
|
||||
float sumP = 0;
|
||||
@@ -193,14 +193,14 @@
|
||||
errPrstIdx = 0;
|
||||
}
|
||||
#else
|
||||
if (labs(error) > threshold * planner.axis_steps_per_mm[encoderAxis]) {
|
||||
if (ABS(error) > threshold * planner.axis_steps_per_mm[encoderAxis]) {
|
||||
//SERIAL_ECHOLN(error);
|
||||
//SERIAL_ECHOLN(position);
|
||||
thermalManager.babystepsTodo[encoderAxis] = -LROUND(error / 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (labs(error) > I2CPE_ERR_CNT_THRESH * planner.axis_steps_per_mm[encoderAxis]) {
|
||||
if (ABS(error) > I2CPE_ERR_CNT_THRESH * planner.axis_steps_per_mm[encoderAxis]) {
|
||||
const millis_t ms = millis();
|
||||
if (ELAPSED(ms, nextErrorCountTime)) {
|
||||
SERIAL_ECHOPAIR("Large error on ", axis_codes[encoderAxis]);
|
||||
@@ -254,11 +254,11 @@
|
||||
float I2CPositionEncoder::get_axis_error_mm(const bool report) {
|
||||
float target, actual, error;
|
||||
|
||||
target = stepper.get_axis_position_mm(encoderAxis);
|
||||
target = planner.get_axis_position_mm(encoderAxis);
|
||||
actual = mm_from_count(position);
|
||||
error = actual - target;
|
||||
|
||||
if (labs(error) > 10000) error = 0; // ?
|
||||
if (ABS(error) > 10000) error = 0; // ?
|
||||
|
||||
if (report) {
|
||||
SERIAL_ECHO(axis_codes[encoderAxis]);
|
||||
@@ -293,7 +293,7 @@
|
||||
error = (encoderCountInStepperTicksScaled - target);
|
||||
|
||||
//suppress discontinuities (might be caused by bad I2C readings...?)
|
||||
bool suppressOutput = (labs(error - errorPrev) > 100);
|
||||
const bool suppressOutput = (ABS(error - errorPrev) > 100);
|
||||
|
||||
if (report) {
|
||||
SERIAL_ECHO(axis_codes[encoderAxis]);
|
||||
@@ -349,18 +349,18 @@
|
||||
ec = false;
|
||||
|
||||
LOOP_NA(i) {
|
||||
startCoord[i] = stepper.get_axis_position_mm((AxisEnum)i);
|
||||
endCoord[i] = stepper.get_axis_position_mm((AxisEnum)i);
|
||||
startCoord[i] = planner.get_axis_position_mm((AxisEnum)i);
|
||||
endCoord[i] = planner.get_axis_position_mm((AxisEnum)i);
|
||||
}
|
||||
|
||||
startCoord[encoderAxis] = startPosition;
|
||||
endCoord[encoderAxis] = endPosition;
|
||||
|
||||
stepper.synchronize();
|
||||
planner.synchronize();
|
||||
|
||||
planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
|
||||
stepper.get_axis_position_mm(E_AXIS), feedrate, 0);
|
||||
stepper.synchronize();
|
||||
planner.get_axis_position_mm(E_AXIS), feedrate, 0);
|
||||
planner.synchronize();
|
||||
|
||||
// if the module isn't currently trusted, wait until it is (or until it should be if things are working)
|
||||
if (!trusted) {
|
||||
@@ -371,8 +371,8 @@
|
||||
|
||||
if (trusted) { // if trusted, commence test
|
||||
planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
|
||||
stepper.get_axis_position_mm(E_AXIS), feedrate, 0);
|
||||
stepper.synchronize();
|
||||
planner.get_axis_position_mm(E_AXIS), feedrate, 0);
|
||||
planner.synchronize();
|
||||
}
|
||||
|
||||
return trusted;
|
||||
@@ -408,19 +408,19 @@
|
||||
travelDistance = endDistance - startDistance;
|
||||
|
||||
LOOP_NA(i) {
|
||||
startCoord[i] = stepper.get_axis_position_mm((AxisEnum)i);
|
||||
endCoord[i] = stepper.get_axis_position_mm((AxisEnum)i);
|
||||
startCoord[i] = planner.get_axis_position_mm((AxisEnum)i);
|
||||
endCoord[i] = planner.get_axis_position_mm((AxisEnum)i);
|
||||
}
|
||||
|
||||
startCoord[encoderAxis] = startDistance;
|
||||
endCoord[encoderAxis] = endDistance;
|
||||
|
||||
stepper.synchronize();
|
||||
planner.synchronize();
|
||||
|
||||
LOOP_L_N(i, iter) {
|
||||
planner.buffer_line(startCoord[X_AXIS], startCoord[Y_AXIS], startCoord[Z_AXIS],
|
||||
stepper.get_axis_position_mm(E_AXIS), feedrate, 0);
|
||||
stepper.synchronize();
|
||||
planner.get_axis_position_mm(E_AXIS), feedrate, 0);
|
||||
planner.synchronize();
|
||||
|
||||
delay(250);
|
||||
startCount = get_position();
|
||||
@@ -428,14 +428,14 @@
|
||||
//do_blocking_move_to(endCoord[X_AXIS],endCoord[Y_AXIS],endCoord[Z_AXIS]);
|
||||
|
||||
planner.buffer_line(endCoord[X_AXIS], endCoord[Y_AXIS], endCoord[Z_AXIS],
|
||||
stepper.get_axis_position_mm(E_AXIS), feedrate, 0);
|
||||
stepper.synchronize();
|
||||
planner.get_axis_position_mm(E_AXIS), feedrate, 0);
|
||||
planner.synchronize();
|
||||
|
||||
//Read encoder distance
|
||||
delay(250);
|
||||
stopCount = get_position();
|
||||
|
||||
travelledDistance = mm_from_count(abs(stopCount - startCount));
|
||||
travelledDistance = mm_from_count(ABS(stopCount - startCount));
|
||||
|
||||
SERIAL_ECHOPAIR("Attempted to travel: ", travelDistance);
|
||||
SERIAL_ECHOLNPGM("mm.");
|
||||
|
||||
+5
-5
@@ -448,10 +448,6 @@ void report_current_position();
|
||||
filament_change_load_length[EXTRUDERS];
|
||||
#endif
|
||||
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
extern int lpq_len;
|
||||
#endif
|
||||
|
||||
#if HAS_POWER_SWITCH
|
||||
extern bool powersupply_on;
|
||||
#define PSU_PIN_ON() do{ OUT_WRITE(PS_ON_PIN, PS_ON_AWAKE); powersupply_on = true; }while(0)
|
||||
@@ -477,6 +473,10 @@ void do_blocking_move_to_x(const float &rx, const float &fr_mm_s=0.0);
|
||||
void do_blocking_move_to_z(const float &rz, const float &fr_mm_s=0.0);
|
||||
void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm_s=0.0);
|
||||
|
||||
#if ENABLED(ARC_SUPPORT)
|
||||
void plan_arc(const float(&cart)[XYZE], const float(&offset)[2], const bool clockwise);
|
||||
#endif
|
||||
|
||||
#define HAS_AXIS_UNHOMED_ERR ( \
|
||||
ENABLED(Z_PROBE_ALLEN_KEY) \
|
||||
|| ENABLED(Z_PROBE_SLED) \
|
||||
@@ -522,7 +522,7 @@ void do_blocking_move_to_xy(const float &rx, const float &ry, const float &fr_mm
|
||||
// Note: This won't work on SCARA since the probe offset rotates with the arm.
|
||||
inline bool position_is_reachable_by_probe(const float &rx, const float &ry) {
|
||||
return position_is_reachable(rx - (X_PROBE_OFFSET_FROM_EXTRUDER), ry - (Y_PROBE_OFFSET_FROM_EXTRUDER))
|
||||
&& position_is_reachable(rx, ry, FABS(MIN_PROBE_EDGE));
|
||||
&& position_is_reachable(rx, ry, ABS(MIN_PROBE_EDGE));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
+11
-7
@@ -23,21 +23,25 @@
|
||||
#ifndef MARLIN_CONFIG_H
|
||||
#define MARLIN_CONFIG_H
|
||||
|
||||
#include "fastio.h"
|
||||
#include "macros.h"
|
||||
#include "boards.h"
|
||||
#include "macros.h"
|
||||
#include "Version.h"
|
||||
#include "Configuration.h"
|
||||
#include "Conditionals_LCD.h"
|
||||
#include "Configuration_adv.h"
|
||||
#include "pins.h"
|
||||
#if defined(__AVR__) && !defined(USBCON)
|
||||
|
||||
#if USE_MARLINSERIAL
|
||||
#define HardwareSerial_h // trick to disable the standard HWserial
|
||||
#endif
|
||||
#include "Arduino.h"
|
||||
|
||||
#include "types.h"
|
||||
#include "HAL.h"
|
||||
#include "pins.h"
|
||||
#include "Conditionals_post.h"
|
||||
#include "SanityCheck.h"
|
||||
|
||||
#include <avr/pgmspace.h>
|
||||
#include "enum.h"
|
||||
#include "language.h"
|
||||
#include "utility.h"
|
||||
#include "serial.h"
|
||||
|
||||
#endif // MARLIN_CONFIG_H
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
#if !(defined(__AVR__) && defined(USBCON)) && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
|
||||
#if USE_MARLINSERIAL && (defined(UBRRH) || defined(UBRR0H) || defined(UBRR1H) || defined(UBRR2H) || defined(UBRR3H))
|
||||
|
||||
#include "MarlinSerial.h"
|
||||
#include "Marlin.h"
|
||||
@@ -561,9 +561,9 @@
|
||||
// Preinstantiate
|
||||
MarlinSerial customizedSerial;
|
||||
|
||||
#endif // !(__AVR__ && USBCON) && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
|
||||
#endif // USE_MARLINSERIAL && (UBRRH || UBRR0H || UBRR1H || UBRR2H || UBRR3H)
|
||||
|
||||
// For AT90USB targets use the UART for BT interfacing
|
||||
#if defined(__AVR__) && defined(USBCON) && ENABLED(BLUETOOTH)
|
||||
#if !USE_MARLINSERIAL && ENABLED(BLUETOOTH)
|
||||
HardwareSerial bluetoothSerial;
|
||||
#endif
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
#define TX_BUFFER_SIZE 32
|
||||
#endif
|
||||
|
||||
#if !(defined(__AVR__) && defined(USBCON))
|
||||
#if USE_MARLINSERIAL
|
||||
|
||||
#if RX_BUFFER_SIZE > 256
|
||||
typedef uint16_t ring_buffer_pos_t;
|
||||
@@ -159,10 +159,10 @@
|
||||
|
||||
extern MarlinSerial customizedSerial;
|
||||
|
||||
#endif // !(__AVR__ && USBCON)
|
||||
#endif // USE_MARLINSERIAL
|
||||
|
||||
// Use the UART for Bluetooth in AT90USB configurations
|
||||
#if defined(__AVR__) && defined(USBCON) && ENABLED(BLUETOOTH)
|
||||
#if !USE_MARLINSERIAL && ENABLED(BLUETOOTH)
|
||||
extern HardwareSerial bluetoothSerial;
|
||||
#endif
|
||||
|
||||
|
||||
+268
-221
File diff suppressed because it is too large
Load Diff
@@ -60,11 +60,12 @@
|
||||
#include "planner.h"
|
||||
#include "stepper.h"
|
||||
#include "Marlin.h"
|
||||
#include "delay.h"
|
||||
|
||||
static uint8_t LEDs[8] = { 0 };
|
||||
|
||||
// Delay for 0.1875µs (16MHz AVR) or 0.15µs (20MHz AVR)
|
||||
#define SIG_DELAY() DELAY_3_NOP
|
||||
#define SIG_DELAY() DELAY_NS(188)
|
||||
|
||||
void Max7219_PutByte(uint8_t data) {
|
||||
CRITICAL_SECTION_START
|
||||
@@ -341,8 +342,8 @@ void Max7219_idle_tasks() {
|
||||
NOMORE(current_depth, 16); // if the BLOCK_BUFFER_SIZE is greater than 16, two lines
|
||||
// of LEDs is enough to see if the buffer is draining
|
||||
|
||||
const uint8_t st = min(current_depth, last_depth),
|
||||
en = max(current_depth, last_depth);
|
||||
const uint8_t st = MIN(current_depth, last_depth),
|
||||
en = MAX(current_depth, last_depth);
|
||||
if (current_depth < last_depth)
|
||||
for (uint8_t i = st; i <= en; i++) // clear the highest order LEDs
|
||||
Max7219_LED_Off(MAX7219_DEBUG_STEPPER_QUEUE + (i & 1), i / 2);
|
||||
|
||||
@@ -307,7 +307,7 @@
|
||||
/**
|
||||
* Serial
|
||||
*/
|
||||
#if !(defined(__AVR__) && defined(USBCON))
|
||||
#if USE_MARLINSERIAL
|
||||
#if ENABLED(SERIAL_XON_XOFF) && RX_BUFFER_SIZE < 1024
|
||||
#error "SERIAL_XON_XOFF requires RX_BUFFER_SIZE >= 1024 for reliable transfers without drops."
|
||||
#elif RX_BUFFER_SIZE && (RX_BUFFER_SIZE < 2 || !IS_POWER_OF_2(RX_BUFFER_SIZE))
|
||||
@@ -1274,7 +1274,7 @@ static_assert(X_MAX_LENGTH >= X_BED_SIZE && Y_MAX_LENGTH >= Y_BED_SIZE,
|
||||
/**
|
||||
* emergency-command parser
|
||||
*/
|
||||
#if ENABLED(EMERGENCY_PARSER) && defined(__AVR__) && defined(USBCON)
|
||||
#if ENABLED(EMERGENCY_PARSER) && !USE_MARLINSERIAL
|
||||
#error "EMERGENCY_PARSER does not work on boards with AT90USB processors (USBCON)."
|
||||
#endif
|
||||
|
||||
|
||||
+9
-14
@@ -368,7 +368,7 @@ int8_t SdBaseFile::lsPrintNext(uint8_t flags, uint8_t indent) {
|
||||
// print size if requested
|
||||
if (!DIR_IS_SUBDIR(&dir) && (flags & LS_SIZE)) {
|
||||
SERIAL_CHAR(' ');
|
||||
SERIAL_PROTOCOL(dir.fileSize);
|
||||
SERIAL_ECHO(dir.fileSize);
|
||||
}
|
||||
SERIAL_EOL();
|
||||
return DIR_IS_FILE(&dir) ? 1 : 2;
|
||||
@@ -601,7 +601,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t ofla
|
||||
// search for file
|
||||
|
||||
while (dirFile->curPosition_ < dirFile->fileSize_) {
|
||||
index = 0XF & (dirFile->curPosition_ >> 5);
|
||||
index = 0xF & (dirFile->curPosition_ >> 5);
|
||||
p = dirFile->readDirCache();
|
||||
if (!p) return false;
|
||||
|
||||
@@ -705,7 +705,7 @@ bool SdBaseFile::open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag) {
|
||||
return false;
|
||||
}
|
||||
// open cached entry
|
||||
return openCachedEntry(index & 0XF, oflag);
|
||||
return openCachedEntry(index & 0xF, oflag);
|
||||
}
|
||||
|
||||
// open a cached directory entry. Assumes vol_ is initialized
|
||||
@@ -775,7 +775,7 @@ bool SdBaseFile::openNext(SdBaseFile* dirFile, uint8_t oflag) {
|
||||
vol_ = dirFile->vol_;
|
||||
|
||||
while (1) {
|
||||
index = 0XF & (dirFile->curPosition_ >> 5);
|
||||
index = 0xF & (dirFile->curPosition_ >> 5);
|
||||
|
||||
// read entry into cache
|
||||
p = dirFile->readDirCache();
|
||||
@@ -902,11 +902,10 @@ int SdBaseFile::peek() {
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
// print uint8_t with width 2
|
||||
static void print2u(uint8_t v) {
|
||||
static void print2u(const uint8_t v) {
|
||||
if (v < 10) SERIAL_CHAR('0');
|
||||
SERIAL_PRINT(v, DEC);
|
||||
SERIAL_ECHO_F(v, DEC);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -927,7 +926,7 @@ static void print2u(uint8_t v) {
|
||||
* \param[in] fatDate The date field from a directory entry.
|
||||
*/
|
||||
void SdBaseFile::printFatDate(uint16_t fatDate) {
|
||||
SERIAL_PROTOCOL(FAT_YEAR(fatDate));
|
||||
SERIAL_ECHO(FAT_YEAR(fatDate));
|
||||
SERIAL_CHAR('-');
|
||||
print2u(FAT_MONTH(fatDate));
|
||||
SERIAL_CHAR('-');
|
||||
@@ -959,7 +958,7 @@ void SdBaseFile::printFatTime(uint16_t fatTime) {
|
||||
bool SdBaseFile::printName() {
|
||||
char name[FILENAME_LENGTH];
|
||||
if (!getFilename(name)) return false;
|
||||
SERIAL_PROTOCOL(name);
|
||||
SERIAL_ECHO(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1104,7 +1103,7 @@ dir_t* SdBaseFile::readDirCache() {
|
||||
if (!isDir()) return 0;
|
||||
|
||||
// index of entry in cache
|
||||
i = (curPosition_ >> 5) & 0XF;
|
||||
i = (curPosition_ >> 5) & 0xF;
|
||||
|
||||
// use read to locate and cache block
|
||||
if (read() < 0) return 0;
|
||||
@@ -1726,8 +1725,4 @@ int16_t SdBaseFile::write(const void* buf, uint16_t nbyte) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if ALLOW_DEPRECATED_FUNCTIONS
|
||||
void (*SdBaseFile::oldDateTime_)(uint16_t &date, uint16_t &time) = 0;
|
||||
#endif
|
||||
|
||||
#endif // SDSUPPORT
|
||||
|
||||
+2
-113
@@ -37,6 +37,8 @@
|
||||
#include "SdFatConfig.h"
|
||||
#include "SdVolume.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* \struct filepos_t
|
||||
* \brief internal type for istream
|
||||
@@ -383,119 +385,6 @@ class SdBaseFile {
|
||||
bool open(SdBaseFile* dirFile, const uint8_t dname[11], uint8_t oflag);
|
||||
bool openCachedEntry(uint8_t cacheIndex, uint8_t oflags);
|
||||
dir_t* readDirCache();
|
||||
|
||||
// Deprecated functions
|
||||
#if ALLOW_DEPRECATED_FUNCTIONS
|
||||
public:
|
||||
|
||||
/**
|
||||
* \deprecated Use:
|
||||
* bool contiguousRange(uint32_t* bgnBlock, uint32_t* endBlock);
|
||||
* \param[out] bgnBlock the first block address for the file.
|
||||
* \param[out] endBlock the last block address for the file.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool contiguousRange(uint32_t& bgnBlock, uint32_t& endBlock) {
|
||||
return contiguousRange(&bgnBlock, &endBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* \deprecated Use:
|
||||
* bool createContiguous(SdBaseFile* dirFile, const char* path, uint32_t size)
|
||||
* \param[in] dirFile The directory where the file will be created.
|
||||
* \param[in] path A path with a valid DOS 8.3 file name.
|
||||
* \param[in] size The desired file size.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool createContiguous(SdBaseFile& dirFile, const char* path, uint32_t size) {
|
||||
return createContiguous(&dirFile, path, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* \deprecated Use:
|
||||
* static void dateTimeCallback(
|
||||
* void (*dateTime)(uint16_t* date, uint16_t* time));
|
||||
* \param[in] dateTime The user's call back function.
|
||||
*/
|
||||
static void dateTimeCallback(
|
||||
void (*dateTime)(uint16_t &date, uint16_t &time)) {
|
||||
oldDateTime_ = dateTime;
|
||||
dateTime_ = dateTime ? oldToNew : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \deprecated Use:
|
||||
* bool open(SdBaseFile* dirFile, const char* path, uint8_t oflag);
|
||||
* \param[in] dirFile An open SdFat instance for the directory containing the
|
||||
* file to be opened.
|
||||
* \param[in] path A path with a valid 8.3 DOS name for the file.
|
||||
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
||||
* OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool open(SdBaseFile& dirFile, const char* path, uint8_t oflag) {
|
||||
return open(&dirFile, path, oflag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \deprecated Do not use in new apps
|
||||
* \param[in] dirFile An open SdFat instance for the directory containing the
|
||||
* file to be opened.
|
||||
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool open(SdBaseFile& dirFile, const char* path) {
|
||||
return open(dirFile, path, O_RDWR);
|
||||
}
|
||||
|
||||
/**
|
||||
* \deprecated Use:
|
||||
* bool open(SdBaseFile* dirFile, uint16_t index, uint8_t oflag);
|
||||
* \param[in] dirFile An open SdFat instance for the directory.
|
||||
* \param[in] index The \a index of the directory entry for the file to be
|
||||
* opened. The value for \a index is (directory file position)/32.
|
||||
* \param[in] oflag Values for \a oflag are constructed by a bitwise-inclusive
|
||||
* OR of flags O_READ, O_WRITE, O_TRUNC, and O_SYNC.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool open(SdBaseFile& dirFile, uint16_t index, uint8_t oflag) {
|
||||
return open(&dirFile, index, oflag);
|
||||
}
|
||||
|
||||
/**
|
||||
* \deprecated Use: bool openRoot(SdVolume* vol);
|
||||
* \param[in] vol The FAT volume containing the root directory to be opened.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool openRoot(SdVolume& vol) { return openRoot(&vol); }
|
||||
|
||||
/**
|
||||
* \deprecated Use: int8_t readDir(dir_t* dir);
|
||||
* \param[out] dir The dir_t struct that will receive the data.
|
||||
* \return bytes read for success zero for eof or -1 for failure.
|
||||
*/
|
||||
int8_t readDir(dir_t& dir, char* longFilename) {
|
||||
return readDir(&dir, longFilename);
|
||||
}
|
||||
|
||||
/**
|
||||
* \deprecated Use:
|
||||
* static uint8_t remove(SdBaseFile* dirFile, const char* path);
|
||||
* \param[in] dirFile The directory that contains the file.
|
||||
* \param[in] path The name of the file to be removed.
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
static bool remove(SdBaseFile& dirFile, const char* path) { return remove(&dirFile, path); }
|
||||
|
||||
private:
|
||||
static void (*oldDateTime_)(uint16_t &date, uint16_t &time);
|
||||
static void oldToNew(uint16_t * const date, uint16_t * const time) {
|
||||
uint16_t d, t;
|
||||
oldDateTime_(d, t);
|
||||
*date = d;
|
||||
*time = t;
|
||||
}
|
||||
#endif // ALLOW_DEPRECATED_FUNCTIONS
|
||||
};
|
||||
|
||||
#endif // _SDBASEFILE_H_
|
||||
|
||||
@@ -61,11 +61,6 @@
|
||||
*/
|
||||
#define ENDL_CALLS_FLUSH 0
|
||||
|
||||
/**
|
||||
* Allow use of deprecated functions if ALLOW_DEPRECATED_FUNCTIONS is nonzero
|
||||
*/
|
||||
#define ALLOW_DEPRECATED_FUNCTIONS 1
|
||||
|
||||
/**
|
||||
* Allow FAT12 volumes if FAT12_SUPPORT is nonzero.
|
||||
* FAT12 has not been well tested.
|
||||
|
||||
+1
-1
@@ -204,7 +204,7 @@ bool SdVolume::fatPut(uint32_t cluster, uint32_t value) {
|
||||
index &= 0x1FF;
|
||||
uint8_t tmp = value;
|
||||
if (cluster & 1) {
|
||||
tmp = (cacheBuffer_.data[index] & 0XF) | tmp << 4;
|
||||
tmp = (cacheBuffer_.data[index] & 0xF) | tmp << 4;
|
||||
}
|
||||
cacheBuffer_.data[index] = tmp;
|
||||
index++;
|
||||
|
||||
+2
-2
@@ -35,7 +35,7 @@
|
||||
/**
|
||||
* Marlin release version identifier
|
||||
*/
|
||||
#define SHORT_BUILD_VERSION "TM3D 1.1.8_R4"
|
||||
#define SHORT_BUILD_VERSION "TM3D 1.1.8_R5"
|
||||
|
||||
/**
|
||||
* Verbose version identifier which should contain a reference to the location
|
||||
@@ -48,7 +48,7 @@
|
||||
* here we define this default string as the date where the latest release
|
||||
* version was tagged.
|
||||
*/
|
||||
#define STRING_DISTRIBUTION_DATE "2018-05-09"
|
||||
#define STRING_DISTRIBUTION_DATE "2018-05-26"
|
||||
|
||||
/**
|
||||
* Required minimum Configuration.h and Configuration_adv.h file versions.
|
||||
|
||||
+87
-122
@@ -88,25 +88,25 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
||||
uint8_t cnt = 0;
|
||||
|
||||
// Read the next entry from a directory
|
||||
while (parent.readDir(p, longFilename) > 0) {
|
||||
while (parent.readDir(&p, longFilename) > 0) {
|
||||
|
||||
// If the entry is a directory and the action is LS_SerialPrint
|
||||
if (DIR_IS_SUBDIR(&p) && lsAction != LS_Count && lsAction != LS_GetFilename) {
|
||||
|
||||
// Get the short name for the item, which we know is a folder
|
||||
char lfilename[FILENAME_LENGTH];
|
||||
createFilename(lfilename, p);
|
||||
char dosFilename[FILENAME_LENGTH];
|
||||
createFilename(dosFilename, p);
|
||||
|
||||
// Allocate enough stack space for the full path to a folder, trailing slash, and nul
|
||||
bool prepend_is_empty = (prepend[0] == '\0');
|
||||
int len = (prepend_is_empty ? 1 : strlen(prepend)) + strlen(lfilename) + 1 + 1;
|
||||
int len = (prepend_is_empty ? 1 : strlen(prepend)) + strlen(dosFilename) + 1 + 1;
|
||||
char path[len];
|
||||
|
||||
// Append the FOLDERNAME12/ to the passed string.
|
||||
// It contains the full path to the "parent" argument.
|
||||
// We now have the full path to the item in this folder.
|
||||
strcpy(path, prepend_is_empty ? "/" : prepend); // root slash if prepend is empty
|
||||
strcat(path, lfilename); // FILENAME_LENGTH-1 characters maximum
|
||||
strcat(path, dosFilename); // FILENAME_LENGTH-1 characters maximum
|
||||
strcat(path, "/"); // 1 character
|
||||
|
||||
// Serial.print(path);
|
||||
@@ -114,11 +114,11 @@ void CardReader::lsDive(const char *prepend, SdFile parent, const char * const m
|
||||
// Get a new directory object using the full path
|
||||
// and dive recursively into it.
|
||||
SdFile dir;
|
||||
if (!dir.open(parent, lfilename, O_READ)) {
|
||||
if (!dir.open(&parent, dosFilename, O_READ)) {
|
||||
if (lsAction == LS_SerialPrint) {
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
|
||||
SERIAL_ECHOLN(lfilename);
|
||||
SERIAL_ECHOLN(dosFilename);
|
||||
}
|
||||
}
|
||||
lsDive(path, dir);
|
||||
@@ -214,7 +214,7 @@ void CardReader::ls() {
|
||||
|
||||
// Open the sub-item as the new dive parent
|
||||
SdFile dir;
|
||||
if (!dir.open(diveDir, segment, O_READ)) {
|
||||
if (!dir.open(&diveDir, segment, O_READ)) {
|
||||
SERIAL_EOL();
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPGM(MSG_SD_CANT_OPEN_SUBDIR);
|
||||
@@ -237,11 +237,11 @@ void CardReader::ls() {
|
||||
*/
|
||||
void CardReader::printFilename() {
|
||||
if (file.isOpen()) {
|
||||
char lfilename[FILENAME_LENGTH];
|
||||
file.getFilename(lfilename);
|
||||
SERIAL_ECHO(lfilename);
|
||||
char dosFilename[FILENAME_LENGTH];
|
||||
file.getFilename(dosFilename);
|
||||
SERIAL_ECHO(dosFilename);
|
||||
#if ENABLED(LONG_FILENAME_HOST_SUPPORT)
|
||||
getfilename(0, lfilename);
|
||||
getfilename(0, dosFilename);
|
||||
if (longFilename[0]) {
|
||||
SERIAL_ECHO(' ');
|
||||
SERIAL_ECHO(longFilename);
|
||||
@@ -262,16 +262,16 @@ void CardReader::initsd() {
|
||||
#define SPI_SPEED SPI_FULL_SPEED
|
||||
#endif
|
||||
|
||||
if (!card.init(SPI_SPEED, SDSS)
|
||||
if (!sd2card.init(SPI_SPEED, SDSS)
|
||||
#if defined(LCD_SDSS) && (LCD_SDSS != SDSS)
|
||||
&& !card.init(SPI_SPEED, LCD_SDSS)
|
||||
&& !sd2card.init(SPI_SPEED, LCD_SDSS)
|
||||
#endif
|
||||
) {
|
||||
//if (!card.init(SPI_HALF_SPEED,SDSS))
|
||||
//if (!sd2card.init(SPI_HALF_SPEED,SDSS))
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOLNPGM(MSG_SD_INIT_FAIL);
|
||||
}
|
||||
else if (!volume.init(&card)) {
|
||||
else if (!volume.init(&sd2card)) {
|
||||
SERIAL_ERROR_START();
|
||||
SERIAL_ERRORLNPGM(MSG_SD_VOL_INIT_FAIL);
|
||||
}
|
||||
@@ -287,17 +287,6 @@ void CardReader::initsd() {
|
||||
setroot();
|
||||
}
|
||||
|
||||
void CardReader::setroot() {
|
||||
/*if (!workDir.openRoot(&volume)) {
|
||||
SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
|
||||
}*/
|
||||
workDir = root;
|
||||
curDir = &workDir;
|
||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||
presort();
|
||||
#endif
|
||||
}
|
||||
|
||||
void CardReader::release() {
|
||||
sdprinting = false;
|
||||
cardOK = false;
|
||||
@@ -335,9 +324,9 @@ void CardReader::stopSDPrint(
|
||||
#endif
|
||||
}
|
||||
|
||||
void CardReader::openLogFile(char* name) {
|
||||
void CardReader::openLogFile(char * const path) {
|
||||
logging = true;
|
||||
openFile(name, false);
|
||||
openFile(path, false);
|
||||
}
|
||||
|
||||
void appendAtom(SdFile &file, char *& dst, uint8_t &cnt) {
|
||||
@@ -360,7 +349,7 @@ void CardReader::getAbsFilename(char *t) {
|
||||
*t = '\0';
|
||||
}
|
||||
|
||||
void CardReader::openFile(char* name, const bool read, const bool subcall/*=false*/) {
|
||||
void CardReader::openFile(char * const path, const bool read, const bool subcall/*=false*/) {
|
||||
|
||||
if (!cardOK) return;
|
||||
|
||||
@@ -380,7 +369,7 @@ void CardReader::openFile(char* name, const bool read, const bool subcall/*=fals
|
||||
filespos[file_subcall_ctr] = sdpos;
|
||||
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPAIR("SUBROUTINE CALL target:\"", name);
|
||||
SERIAL_ECHOPAIR("SUBROUTINE CALL target:\"", path);
|
||||
SERIAL_ECHOPAIR("\" parent:\"", proc_filenames[file_subcall_ctr]);
|
||||
SERIAL_ECHOLNPAIR("\" pos", sdpos);
|
||||
file_subcall_ctr++;
|
||||
@@ -401,48 +390,14 @@ void CardReader::openFile(char* name, const bool read, const bool subcall/*=fals
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPGM("Now ");
|
||||
serialprintPGM(doing == 1 ? PSTR("doing") : PSTR("fresh"));
|
||||
SERIAL_ECHOLNPAIR(" file: ", name);
|
||||
SERIAL_ECHOLNPAIR(" file: ", path);
|
||||
}
|
||||
|
||||
stopSDPrint();
|
||||
|
||||
SdFile myDir;
|
||||
curDir = &root;
|
||||
char *fname = name;
|
||||
char *dirname_start, *dirname_end;
|
||||
|
||||
if (name[0] == '/') {
|
||||
dirname_start = &name[1];
|
||||
while (dirname_start != NULL) {
|
||||
dirname_end = strchr(dirname_start, '/');
|
||||
//SERIAL_ECHOPGM("start:");SERIAL_ECHOLN((int)(dirname_start - name));
|
||||
//SERIAL_ECHOPGM("end :");SERIAL_ECHOLN((int)(dirname_end - name));
|
||||
if (dirname_end != NULL && dirname_end > dirname_start) {
|
||||
char subdirname[FILENAME_LENGTH];
|
||||
strncpy(subdirname, dirname_start, dirname_end - dirname_start);
|
||||
subdirname[dirname_end - dirname_start] = '\0';
|
||||
if (!myDir.open(curDir, subdirname, O_READ)) {
|
||||
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, subdirname);
|
||||
SERIAL_PROTOCOLCHAR('.');
|
||||
return;
|
||||
}
|
||||
else {
|
||||
//SERIAL_ECHOLNPGM("dive ok");
|
||||
}
|
||||
|
||||
curDir = &myDir;
|
||||
dirname_start = dirname_end + 1;
|
||||
}
|
||||
else { // the remainder after all /fsa/fdsa/ is the filename
|
||||
fname = dirname_start;
|
||||
//SERIAL_ECHOLNPGM("remainder");
|
||||
//SERIAL_ECHOLN(fname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
curDir = &workDir; // Relative paths start in current directory
|
||||
SdFile *curDir;
|
||||
const char * const fname = diveToFile(curDir, path, false);
|
||||
if (!fname) return;
|
||||
|
||||
if (read) {
|
||||
if (file.open(curDir, fname, O_READ)) {
|
||||
@@ -472,7 +427,7 @@ void CardReader::openFile(char* name, const bool read, const bool subcall/*=fals
|
||||
}
|
||||
else {
|
||||
saving = true;
|
||||
SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, name);
|
||||
SERIAL_PROTOCOLLNPAIR(MSG_SD_WRITE_TO_FILE, path);
|
||||
lcd_setstatus(fname);
|
||||
}
|
||||
}
|
||||
@@ -483,40 +438,9 @@ void CardReader::removeFile(const char * const name) {
|
||||
|
||||
stopSDPrint();
|
||||
|
||||
SdFile myDir;
|
||||
curDir = &root;
|
||||
const char *fname = name;
|
||||
|
||||
char *dirname_start, *dirname_end;
|
||||
if (name[0] == '/') {
|
||||
dirname_start = strchr(name, '/') + 1;
|
||||
while (dirname_start != NULL) {
|
||||
dirname_end = strchr(dirname_start, '/');
|
||||
//SERIAL_ECHOPGM("start:");SERIAL_ECHOLN((int)(dirname_start - name));
|
||||
//SERIAL_ECHOPGM("end :");SERIAL_ECHOLN((int)(dirname_end - name));
|
||||
if (dirname_end != NULL && dirname_end > dirname_start) {
|
||||
char subdirname[FILENAME_LENGTH];
|
||||
strncpy(subdirname, dirname_start, dirname_end - dirname_start);
|
||||
subdirname[dirname_end - dirname_start] = 0;
|
||||
SERIAL_ECHOLN(subdirname);
|
||||
if (!myDir.open(curDir, subdirname, O_READ)) {
|
||||
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, subdirname);
|
||||
SERIAL_PROTOCOLCHAR('.');
|
||||
SERIAL_EOL();
|
||||
return;
|
||||
}
|
||||
|
||||
curDir = &myDir;
|
||||
dirname_start = dirname_end + 1;
|
||||
}
|
||||
else {
|
||||
fname = dirname_start;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else // Relative paths are rooted in the current directory
|
||||
curDir = &workDir;
|
||||
SdFile *curDir;
|
||||
const char * const fname = diveToFile(curDir, name, false);
|
||||
if (!fname) return;
|
||||
|
||||
if (file.remove(curDir, fname)) {
|
||||
SERIAL_PROTOCOLPGM("File deleted:");
|
||||
@@ -582,7 +506,7 @@ void CardReader::checkautostart() {
|
||||
sprintf_P(autoname, PSTR("auto%i.g"), autostart_index);
|
||||
dir_t p;
|
||||
root.rewind();
|
||||
while (root.readDir(p, NULL) > 0) {
|
||||
while (root.readDir(&p, NULL) > 0) {
|
||||
for (int8_t i = (int8_t)strlen((char*)p.name); i--;) p.name[i] = tolower(p.name[i]);
|
||||
if (p.name[9] != '~' && strncmp((char*)p.name, autoname, 5) == 0) {
|
||||
openAndPrintFile(autoname);
|
||||
@@ -612,6 +536,7 @@ void CardReader::closefile(const bool store_location) {
|
||||
|
||||
/**
|
||||
* Get the name of a file in the current directory by index
|
||||
* with optional name to match.
|
||||
*/
|
||||
void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) {
|
||||
#if ENABLED(SDSORT_CACHE_NAMES)
|
||||
@@ -628,35 +553,60 @@ void CardReader::getfilename(uint16_t nr, const char * const match/*=NULL*/) {
|
||||
return;
|
||||
}
|
||||
#endif // SDSORT_CACHE_NAMES
|
||||
curDir = &workDir;
|
||||
lsAction = LS_GetFilename;
|
||||
nrFile_index = nr;
|
||||
curDir->rewind();
|
||||
lsDive(NULL, *curDir, match);
|
||||
workDir.rewind();
|
||||
lsDive(NULL, workDir, match);
|
||||
}
|
||||
|
||||
uint16_t CardReader::getnrfilenames() {
|
||||
curDir = &workDir;
|
||||
lsAction = LS_Count;
|
||||
nrFiles = 0;
|
||||
curDir->rewind();
|
||||
lsDive(NULL, *curDir);
|
||||
workDir.rewind();
|
||||
lsDive(NULL, workDir);
|
||||
//SERIAL_ECHOLN(nrFiles);
|
||||
return nrFiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dive to the given file path, with optional echo.
|
||||
* On exit set curDir and return the name part of the path.
|
||||
* A NULL result indicates an unrecoverable error.
|
||||
*/
|
||||
const char* CardReader::diveToFile(SdFile*& curDir, const char * const path, const bool echo) {
|
||||
SdFile myDir;
|
||||
if (path[0] != '/') { curDir = &workDir; return path; }
|
||||
|
||||
curDir = &root;
|
||||
const char *dirname_start = &path[1];
|
||||
while (dirname_start) {
|
||||
char * const dirname_end = strchr(dirname_start, '/');
|
||||
if (dirname_end <= dirname_start) break;
|
||||
|
||||
char dosSubdirname[FILENAME_LENGTH];
|
||||
const uint8_t len = dirname_end - dirname_start;
|
||||
strncpy(dosSubdirname, dirname_start, len);
|
||||
dosSubdirname[len] = 0;
|
||||
|
||||
if (echo) SERIAL_ECHOLN(dosSubdirname);
|
||||
|
||||
if (!myDir.open(curDir, dosSubdirname, O_READ)) {
|
||||
SERIAL_PROTOCOLPAIR(MSG_SD_OPEN_FILE_FAIL, dosSubdirname);
|
||||
SERIAL_PROTOCOLCHAR('.');
|
||||
SERIAL_EOL();
|
||||
return NULL;
|
||||
}
|
||||
curDir = &myDir;
|
||||
dirname_start = dirname_end + 1;
|
||||
}
|
||||
return dirname_start;
|
||||
}
|
||||
|
||||
void CardReader::chdir(const char * relpath) {
|
||||
SdFile newDir;
|
||||
SdFile *parent = &root;
|
||||
SdFile *parent = workDir.isOpen() ? &workDir : &root;
|
||||
|
||||
if (workDir.isOpen()) parent = &workDir;
|
||||
|
||||
if (!newDir.open(*parent, relpath, O_READ)) {
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR);
|
||||
SERIAL_ECHOLN(relpath);
|
||||
}
|
||||
else {
|
||||
if (newDir.open(parent, relpath, O_READ)) {
|
||||
workDir = newDir;
|
||||
if (workDirDepth < MAX_DIR_DEPTH)
|
||||
workDirParents[workDirDepth++] = workDir;
|
||||
@@ -664,6 +614,11 @@ void CardReader::chdir(const char * relpath) {
|
||||
presort();
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
SERIAL_ECHO_START();
|
||||
SERIAL_ECHOPGM(MSG_SD_CANT_ENTER_SUBDIR);
|
||||
SERIAL_ECHOLN(relpath);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t CardReader::updir() {
|
||||
@@ -676,6 +631,16 @@ int8_t CardReader::updir() {
|
||||
return workDirDepth;
|
||||
}
|
||||
|
||||
void CardReader::setroot() {
|
||||
/*if (!workDir.openRoot(&volume)) {
|
||||
SERIAL_ECHOLNPGM(MSG_SD_WORKDIR_FAIL);
|
||||
}*/
|
||||
workDir = root;
|
||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||
presort();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||
|
||||
/**
|
||||
@@ -921,7 +886,7 @@ uint16_t CardReader::get_num_Files() {
|
||||
}
|
||||
|
||||
void CardReader::printingHasFinished() {
|
||||
stepper.synchronize();
|
||||
planner.synchronize();
|
||||
file.close();
|
||||
if (file_subcall_ctr > 0) { // Heading up to a parent file that called current as a procedure.
|
||||
file_subcall_ctr--;
|
||||
@@ -941,7 +906,7 @@ void CardReader::printingHasFinished() {
|
||||
#endif
|
||||
|
||||
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
|
||||
stepper.cleaning_buffer_counter = 1; // The command will fire from the Stepper ISR
|
||||
planner.finish_and_disable();
|
||||
#endif
|
||||
print_job_timer.stop();
|
||||
if (print_job_timer.duration() > 60)
|
||||
|
||||
+7
-7
@@ -32,8 +32,6 @@
|
||||
#define MAX_DIR_DEPTH 10 // Maximum folder depth
|
||||
|
||||
#include "SdFile.h"
|
||||
#include "types.h"
|
||||
#include "enum.h"
|
||||
|
||||
class CardReader {
|
||||
public:
|
||||
@@ -45,8 +43,8 @@ public:
|
||||
void beginautostart();
|
||||
void checkautostart();
|
||||
|
||||
void openFile(char* name, const bool read, const bool subcall=false);
|
||||
void openLogFile(char* name);
|
||||
void openFile(char * const path, const bool read, const bool subcall=false);
|
||||
void openLogFile(char * const path);
|
||||
void removeFile(const char * const name);
|
||||
void closefile(const bool store_location=false);
|
||||
void release();
|
||||
@@ -75,6 +73,8 @@ public:
|
||||
int8_t updir();
|
||||
void setroot();
|
||||
|
||||
const char* diveToFile(SdFile*& curDir, const char * const path, const bool echo);
|
||||
|
||||
uint16_t get_num_Files();
|
||||
|
||||
#if ENABLED(SDCARD_SORT_ALPHA)
|
||||
@@ -114,12 +114,12 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
public:
|
||||
bool saving, logging, sdprinting, cardOK, filenameIsDir;
|
||||
char filename[FILENAME_LENGTH], longFilename[LONG_FILENAME_LENGTH];
|
||||
int autostart_index;
|
||||
|
||||
private:
|
||||
SdFile root, *curDir, workDir, workDirParents[MAX_DIR_DEPTH];
|
||||
SdFile root, workDir, workDirParents[MAX_DIR_DEPTH];
|
||||
uint8_t workDirDepth;
|
||||
|
||||
// Sort files and folders alphabetically.
|
||||
@@ -172,7 +172,7 @@ private:
|
||||
|
||||
#endif // SDCARD_SORT_ALPHA
|
||||
|
||||
Sd2Card card;
|
||||
Sd2Card sd2card;
|
||||
SdVolume volume;
|
||||
SdFile file;
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
#if HAS_TRINAMIC
|
||||
#include "stepper_indirection.h"
|
||||
#include "tmc_util.h"
|
||||
#define TMC_GET_PWMTHRS(P,Q) _tmc_thrs(stepper##Q.microsteps(), stepper##Q.TPWMTHRS(), planner.axis_steps_per_mm[P##_AXIS])
|
||||
#define TMC_GET_PWMTHRS(A,Q) _tmc_thrs(stepper##Q.microsteps(), stepper##Q.TPWMTHRS(), planner.axis_steps_per_mm[_AXIS(A)])
|
||||
#endif
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
@@ -73,6 +73,10 @@
|
||||
#include "fwretract.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
#define LPQ_LEN thermalManager.lpq_len
|
||||
#endif
|
||||
|
||||
#pragma pack(push, 1) // No padding between variables
|
||||
|
||||
typedef struct PID { float Kp, Ki, Kd; } PID;
|
||||
@@ -183,7 +187,7 @@ typedef struct SettingsDataStruct {
|
||||
//
|
||||
PIDC hotendPID[MAX_EXTRUDERS]; // M301 En PIDC / M303 En U
|
||||
|
||||
int lpq_len; // M301 L
|
||||
int16_t lpq_len; // M301 L
|
||||
|
||||
//
|
||||
// PIDTEMPBED
|
||||
@@ -609,9 +613,9 @@ void MarlinSettings::postprocess() {
|
||||
_FIELD_TEST(lpq_len);
|
||||
|
||||
#if DISABLED(PID_EXTRUSION_SCALING)
|
||||
int lpq_len = 20;
|
||||
const int16_t LPQ_LEN = 20;
|
||||
#endif
|
||||
EEPROM_WRITE(lpq_len);
|
||||
EEPROM_WRITE(LPQ_LEN);
|
||||
|
||||
#if DISABLED(PIDTEMPBED)
|
||||
dummy = DUMMY_PID_VALUE;
|
||||
@@ -968,7 +972,6 @@ void MarlinSettings::postprocess() {
|
||||
SERIAL_ECHOPAIR("(EEPROM=", stored_ver);
|
||||
SERIAL_ECHOLNPGM(" Marlin=" EEPROM_VERSION ")");
|
||||
#endif
|
||||
if (!validating) reset();
|
||||
eeprom_error = true;
|
||||
}
|
||||
else {
|
||||
@@ -1214,9 +1217,9 @@ void MarlinSettings::postprocess() {
|
||||
_FIELD_TEST(lpq_len);
|
||||
|
||||
#if DISABLED(PID_EXTRUSION_SCALING)
|
||||
int lpq_len;
|
||||
int16_t LPQ_LEN;
|
||||
#endif
|
||||
EEPROM_READ(lpq_len);
|
||||
EEPROM_READ(LPQ_LEN);
|
||||
|
||||
//
|
||||
// Heated Bed PID
|
||||
@@ -1340,7 +1343,7 @@ void MarlinSettings::postprocess() {
|
||||
#endif
|
||||
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
#define TMC_SET_PWMTHRS(P,Q) tmc_set_pwmthrs(stepper##Q, TMC_##Q, tmc_hybrid_threshold[TMC_##Q], planner.axis_steps_per_mm[P##_AXIS])
|
||||
#define TMC_SET_PWMTHRS(A,Q) tmc_set_pwmthrs(stepper##Q, tmc_hybrid_threshold[TMC_##Q], planner.axis_steps_per_mm[_AXIS(A)])
|
||||
uint32_t tmc_hybrid_threshold[TMC_AXES];
|
||||
EEPROM_READ(tmc_hybrid_threshold);
|
||||
if (!validating) {
|
||||
@@ -1523,14 +1526,12 @@ void MarlinSettings::postprocess() {
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!validating) {
|
||||
if (eeprom_error) reset(); else postprocess();
|
||||
}
|
||||
if (!validating && !eeprom_error) postprocess();
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
ubl.report_state();
|
||||
|
||||
if (!validating) {
|
||||
ubl.report_state();
|
||||
|
||||
if (!ubl.sanity_check()) {
|
||||
SERIAL_EOL();
|
||||
#if ENABLED(EEPROM_CHITCHAT)
|
||||
@@ -1717,7 +1718,7 @@ void MarlinSettings::reset() {
|
||||
constexpr float tmp4[XYZ][HOTENDS] = {
|
||||
HOTEND_OFFSET_X,
|
||||
HOTEND_OFFSET_Y
|
||||
#ifdef HOTEND_OFFSET_Z
|
||||
#if HAS_HOTEND_OFFSET_Z
|
||||
, HOTEND_OFFSET_Z
|
||||
#else
|
||||
, { 0 }
|
||||
@@ -1811,7 +1812,7 @@ void MarlinSettings::reset() {
|
||||
#endif
|
||||
}
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
lpq_len = 20; // default last-position-queue size
|
||||
thermalManager.lpq_len = 20; // default last-position-queue size
|
||||
#endif
|
||||
#endif // PIDTEMP
|
||||
|
||||
@@ -2108,7 +2109,7 @@ void MarlinSettings::reset() {
|
||||
SERIAL_ECHOPAIR(" M218 T", (int)e);
|
||||
SERIAL_ECHOPAIR(" X", LINEAR_UNIT(hotend_offset[X_AXIS][e]));
|
||||
SERIAL_ECHOPAIR(" Y", LINEAR_UNIT(hotend_offset[Y_AXIS][e]));
|
||||
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(SWITCHING_NOZZLE) ||ENABLED(PARKING_EXTRUDER)
|
||||
#if HAS_HOTEND_OFFSET_Z
|
||||
SERIAL_ECHOPAIR(" Z", LINEAR_UNIT(hotend_offset[Z_AXIS][e]));
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
@@ -2274,7 +2275,7 @@ void MarlinSettings::reset() {
|
||||
SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, e)));
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
SERIAL_ECHOPAIR(" C", PID_PARAM(Kc, e));
|
||||
if (e == 0) SERIAL_ECHOPAIR(" L", lpq_len);
|
||||
if (e == 0) SERIAL_ECHOPAIR(" L", thermalManager.lpq_len);
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
}
|
||||
@@ -2289,7 +2290,7 @@ void MarlinSettings::reset() {
|
||||
SERIAL_ECHOPAIR(" D", unscalePID_d(PID_PARAM(Kd, 0)));
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
SERIAL_ECHOPAIR(" C", PID_PARAM(Kc, 0));
|
||||
SERIAL_ECHOPAIR(" L", lpq_len);
|
||||
SERIAL_ECHOPAIR(" L", thermalManager.lpq_len);
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
}
|
||||
|
||||
@@ -35,15 +35,16 @@ class MarlinSettings {
|
||||
static bool save(); // Return 'true' if data was saved
|
||||
|
||||
FORCE_INLINE static bool init_eeprom() {
|
||||
bool success = true;
|
||||
reset();
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
success = save();
|
||||
const bool success = save();
|
||||
#if ENABLED(EEPROM_CHITCHAT)
|
||||
if (success) report();
|
||||
#endif
|
||||
return success;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
return success;
|
||||
}
|
||||
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/**
|
||||
* Marlin 3D Printer Firmware
|
||||
* Copyright (C) 2016 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
|
||||
*
|
||||
* Based on Sprinter and grbl.
|
||||
* Copyright (C) 2011 Camiel Gubbels / Erik van der Zalm
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* AVR busy wait delay Cycles routines:
|
||||
*
|
||||
* DELAY_CYCLES(count): Delay execution in cycles
|
||||
* DELAY_NS(count): Delay execution in nanoseconds
|
||||
* DELAY_US(count): Delay execution in microseconds
|
||||
*/
|
||||
|
||||
#ifndef MARLIN_DELAY_H
|
||||
#define MARLIN_DELAY_H
|
||||
|
||||
#define nop() __asm__ __volatile__("nop;\n\t":::)
|
||||
|
||||
FORCE_INLINE static void __delay_4cycles(uint8_t cy) {
|
||||
__asm__ __volatile__(
|
||||
L("1")
|
||||
A("dec %[cnt]")
|
||||
A("nop")
|
||||
A("brne 1b")
|
||||
: [cnt] "+r"(cy) // output: +r means input+output
|
||||
: // input:
|
||||
: "cc" // clobbers:
|
||||
);
|
||||
}
|
||||
|
||||
/* ---------------- Delay in cycles */
|
||||
FORCE_INLINE static void DELAY_CYCLES(uint16_t x) {
|
||||
|
||||
if (__builtin_constant_p(x)) {
|
||||
#define MAXNOPS 4
|
||||
|
||||
if (x <= (MAXNOPS)) {
|
||||
switch (x) { case 4: nop(); case 3: nop(); case 2: nop(); case 1: nop(); }
|
||||
}
|
||||
else {
|
||||
const uint32_t rem = (x) % (MAXNOPS);
|
||||
switch (rem) { case 3: nop(); case 2: nop(); case 1: nop(); }
|
||||
if ((x = (x) / (MAXNOPS)))
|
||||
__delay_4cycles(x); // if need more then 4 nop loop is more optimal
|
||||
}
|
||||
|
||||
#undef MAXNOPS
|
||||
}
|
||||
else
|
||||
__delay_4cycles(x / 4);
|
||||
}
|
||||
#undef nop
|
||||
|
||||
/* ---------------- Delay in nanoseconds */
|
||||
#define DELAY_NS(x) DELAY_CYCLES( (x) * (F_CPU/1000000L) / 1000L )
|
||||
|
||||
/* ---------------- Delay in microseconds */
|
||||
#define DELAY_US(x) DELAY_CYCLES( (x) * (F_CPU/1000000L) )
|
||||
|
||||
#endif // MARLIN_DELAY_H
|
||||
@@ -89,7 +89,7 @@ static void i2c_send(const uint8_t channel, const byte v) {
|
||||
|
||||
// This is for the MCP4018 I2C based digipot
|
||||
void digipot_i2c_set_current(uint8_t channel, float current) {
|
||||
i2c_send(channel, current_to_wiper(min(max(current, 0.0f), float(DIGIPOT_A4988_MAX_CURRENT))));
|
||||
i2c_send(channel, current_to_wiper(MIN(MAX(current, 0.0f), float(DIGIPOT_A4988_MAX_CURRENT))));
|
||||
}
|
||||
|
||||
void digipot_i2c_init() {
|
||||
|
||||
@@ -50,7 +50,7 @@ static void i2c_send(const byte addr, const byte a, const byte b) {
|
||||
|
||||
// This is for the MCP4451 I2C based digipot
|
||||
void digipot_i2c_set_current(uint8_t channel, float current) {
|
||||
current = min((float) max(current, 0.0f), DIGIPOT_I2C_MAX_CURRENT);
|
||||
current = MIN((float) MAX(current, 0.0f), DIGIPOT_I2C_MAX_CURRENT);
|
||||
// these addresses are specific to Azteeg X3 Pro, can be set to others,
|
||||
// In this case first digipot is at address A0=0, A1= 0, second one is at A0=0, A1= 1
|
||||
byte addr = 0x2C; // channel 0-3
|
||||
|
||||
@@ -137,6 +137,7 @@
|
||||
|
||||
#else // !CUSTOM_STATUS_SCREEN_IMAGE
|
||||
|
||||
// Can also be overridden in Configuration.h
|
||||
// If you can afford it, try the 3-frame fan animation!
|
||||
#ifndef FAN_ANIM_FRAMES
|
||||
#define FAN_ANIM_FRAMES 2
|
||||
@@ -1148,7 +1149,9 @@
|
||||
#define CUSTOM_BOOTSCREEN_BMPHEIGHT (sizeof(custom_start_bmp) / (CUSTOM_BOOTSCREEN_BMP_BYTEWIDTH))
|
||||
#endif
|
||||
|
||||
#if FAN_ANIM_FRAMES > 3
|
||||
#ifndef FAN_ANIM_FRAMES
|
||||
#define FAN_ANIM_FRAMES 2
|
||||
#elif FAN_ANIM_FRAMES > 3
|
||||
#error "Only 3 fan animation frames currently supported."
|
||||
#endif
|
||||
#ifndef STATUS_SCREEN_X
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
* Endstop Interrupts
|
||||
*
|
||||
* Without endstop interrupts the endstop pins must be polled continually in
|
||||
* the stepper-ISR via endstops.update(), most of the time finding no change.
|
||||
* the temperature-ISR via endstops.update(), most of the time finding no change.
|
||||
* With this feature endstops.update() is called only when we know that at
|
||||
* least one endstop has changed state, saving valuable CPU cycles.
|
||||
*
|
||||
@@ -40,6 +40,9 @@
|
||||
|
||||
#include "macros.h"
|
||||
|
||||
// One ISR for all EXT-Interrupts
|
||||
void endstop_ISR(void) { endstops.check_possible_change(); }
|
||||
|
||||
/**
|
||||
* Patch for pins_arduino.h (...\Arduino\hardware\arduino\avr\variants\mega\pins_arduino.h)
|
||||
*
|
||||
@@ -72,40 +75,30 @@
|
||||
0 )
|
||||
#endif
|
||||
|
||||
volatile uint8_t e_hit = 0; // Different from 0 when the endstops should be tested in detail.
|
||||
// Must be reset to 0 by the test function when finished.
|
||||
|
||||
// Install Pin change interrupt for a pin. Can be called multiple times.
|
||||
void pciSetup(byte pin) {
|
||||
void pciSetup(const int8_t pin) {
|
||||
SBI(*digitalPinToPCMSK(pin), digitalPinToPCMSKbit(pin)); // enable pin
|
||||
SBI(PCIFR, digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
|
||||
SBI(PCICR, digitalPinToPCICRbit(pin)); // enable interrupt for the group
|
||||
}
|
||||
|
||||
// This is what is really done inside the interrupts.
|
||||
FORCE_INLINE void endstop_ISR_worker( void ) {
|
||||
e_hit = 2; // Because the detection of a e-stop hit has a 1 step debouncer it has to be called at least twice.
|
||||
}
|
||||
|
||||
// Use one Routine to handle each group
|
||||
// One ISR for all EXT-Interrupts
|
||||
void endstop_ISR(void) { endstop_ISR_worker(); }
|
||||
|
||||
// Handlers for pin change interrupts
|
||||
#ifdef PCINT0_vect
|
||||
ISR(PCINT0_vect) { endstop_ISR_worker(); }
|
||||
ISR(PCINT0_vect) { endstop_ISR(); }
|
||||
#endif
|
||||
|
||||
#ifdef PCINT1_vect
|
||||
ISR(PCINT1_vect) { endstop_ISR_worker(); }
|
||||
ISR(PCINT1_vect) { endstop_ISR(); }
|
||||
#endif
|
||||
|
||||
#ifdef PCINT2_vect
|
||||
ISR(PCINT2_vect) { endstop_ISR_worker(); }
|
||||
ISR(PCINT2_vect) { endstop_ISR(); }
|
||||
#endif
|
||||
|
||||
#ifdef PCINT3_vect
|
||||
ISR(PCINT3_vect) { endstop_ISR_worker(); }
|
||||
ISR(PCINT3_vect) { endstop_ISR(); }
|
||||
#endif
|
||||
|
||||
void setup_endstop_interrupts( void ) {
|
||||
|
||||
+457
-237
@@ -31,18 +31,29 @@
|
||||
#include "stepper.h"
|
||||
#include "ultralcd.h"
|
||||
|
||||
// TEST_ENDSTOP: test the old and the current status of an endstop
|
||||
#define TEST_ENDSTOP(ENDSTOP) (TEST(current_endstop_bits & old_endstop_bits, ENDSTOP))
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
#include "endstop_interrupts.h"
|
||||
#endif
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
#define ENDSTOPS_ENABLED (enabled || z_probe_enabled)
|
||||
#else
|
||||
#define ENDSTOPS_ENABLED enabled
|
||||
#endif
|
||||
|
||||
Endstops endstops;
|
||||
|
||||
// public:
|
||||
|
||||
bool Endstops::enabled, Endstops::enabled_globally; // Initialized by settings.load()
|
||||
volatile char Endstops::endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
|
||||
volatile uint8_t Endstops::hit_state;
|
||||
|
||||
Endstops::esbits_t Endstops::current_endstop_bits = 0,
|
||||
Endstops::old_endstop_bits = 0;
|
||||
Endstops::esbits_t Endstops::live_state = 0;
|
||||
#if ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
Endstops::esbits_t Endstops::old_live_state,
|
||||
Endstops::validated_live_state;
|
||||
uint8_t Endstops::endstop_poll_count;
|
||||
#endif
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
volatile bool Endstops::z_probe_enabled = false;
|
||||
@@ -169,10 +180,85 @@ void Endstops::init() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
setup_endstop_interrupts();
|
||||
#endif
|
||||
|
||||
// Enable endstops
|
||||
enable_globally(
|
||||
#if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
);
|
||||
|
||||
} // Endstops::init
|
||||
|
||||
// Called from ISR. A change was detected. Find out what happened!
|
||||
void Endstops::check_possible_change() { if (ENDSTOPS_ENABLED) update(); }
|
||||
|
||||
// Called from ISR: Poll endstop state if required
|
||||
void Endstops::poll() {
|
||||
|
||||
#if ENABLED(PINS_DEBUGGING)
|
||||
run_monitor(); // report changes in endstop status
|
||||
#endif
|
||||
|
||||
#if DISABLED(ENDSTOP_INTERRUPTS_FEATURE) || ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
if (ENDSTOPS_ENABLED) update();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Endstops::enable_globally(const bool onoff) {
|
||||
enabled_globally = enabled = onoff;
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
if (onoff) update(); // If enabling, update state now
|
||||
#endif
|
||||
}
|
||||
|
||||
// Enable / disable endstop checking
|
||||
void Endstops::enable(const bool onoff) {
|
||||
enabled = onoff;
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
if (onoff) update(); // If enabling, update state now
|
||||
#endif
|
||||
}
|
||||
|
||||
// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
|
||||
void Endstops::not_homing() {
|
||||
enabled = enabled_globally;
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
if (enabled) update(); // If enabling, update state now
|
||||
#endif
|
||||
}
|
||||
|
||||
// Enable / disable endstop z-probe checking
|
||||
#if HAS_BED_PROBE
|
||||
void Endstops::enable_z_probe(bool onoff) {
|
||||
z_probe_enabled = onoff;
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
if (enabled) update(); // If enabling, update state now
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLED(PINS_DEBUGGING)
|
||||
void Endstops::run_monitor() {
|
||||
if (!monitor_flag) return;
|
||||
static uint8_t monitor_count = 16; // offset this check from the others
|
||||
monitor_count += _BV(1); // 15 Hz
|
||||
monitor_count &= 0x7F;
|
||||
if (!monitor_count) monitor(); // report changes in endstop status
|
||||
}
|
||||
#endif
|
||||
|
||||
void Endstops::report_state() {
|
||||
if (endstop_hit_bits) {
|
||||
if (hit_state) {
|
||||
#if ENABLED(ULTRA_LCD)
|
||||
char chrX = ' ', chrY = ' ', chrZ = ' ', chrP = ' ';
|
||||
#define _SET_STOP_CHAR(A,C) (chr## A = C)
|
||||
@@ -181,11 +267,11 @@ void Endstops::report_state() {
|
||||
#endif
|
||||
|
||||
#define _ENDSTOP_HIT_ECHO(A,C) do{ \
|
||||
SERIAL_ECHOPAIR(" " STRINGIFY(A) ":", stepper.triggered_position_mm(A ##_AXIS)); \
|
||||
SERIAL_ECHOPAIR(" " STRINGIFY(A) ":", planner.triggered_position_mm(_AXIS(A))); \
|
||||
_SET_STOP_CHAR(A,C); }while(0)
|
||||
|
||||
#define _ENDSTOP_HIT_TEST(A,C) \
|
||||
if (TEST(endstop_hit_bits, A ##_MIN) || TEST(endstop_hit_bits, A ##_MAX)) \
|
||||
if (TEST(hit_state, A ##_MIN) || TEST(hit_state, A ##_MAX)) \
|
||||
_ENDSTOP_HIT_ECHO(A,C)
|
||||
|
||||
#define ENDSTOP_HIT_TEST_X() _ENDSTOP_HIT_TEST(X,'X')
|
||||
@@ -200,7 +286,7 @@ void Endstops::report_state() {
|
||||
|
||||
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
|
||||
#define P_AXIS Z_AXIS
|
||||
if (TEST(endstop_hit_bits, Z_MIN_PROBE)) _ENDSTOP_HIT_ECHO(P, 'P');
|
||||
if (TEST(hit_state, Z_MIN_PROBE)) _ENDSTOP_HIT_ECHO(P, 'P');
|
||||
#endif
|
||||
SERIAL_EOL();
|
||||
|
||||
@@ -211,7 +297,7 @@ void Endstops::report_state() {
|
||||
hit_on_purpose();
|
||||
|
||||
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED) && ENABLED(SDSUPPORT)
|
||||
if (stepper.abort_on_endstop_hit) {
|
||||
if (planner.abort_on_endstop_hit) {
|
||||
card.sdprinting = false;
|
||||
card.closefile();
|
||||
quickstop_stepper();
|
||||
@@ -273,144 +359,29 @@ void Endstops::M119() {
|
||||
#endif
|
||||
} // Endstops::M119
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
void Endstops::test_dual_x_endstops(const EndstopEnum es1, const EndstopEnum es2) {
|
||||
const byte x_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for X, bit 1 for X2
|
||||
if (x_test && stepper.current_block->steps[X_AXIS] > 0) {
|
||||
SBI(endstop_hit_bits, X_MIN);
|
||||
if (!stepper.performing_homing || (x_test == 0x3)) //if not performing home or if both endstops were trigged during homing...
|
||||
stepper.kill_current_block();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
void Endstops::test_dual_y_endstops(const EndstopEnum es1, const EndstopEnum es2) {
|
||||
const byte y_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Y, bit 1 for Y2
|
||||
if (y_test && stepper.current_block->steps[Y_AXIS] > 0) {
|
||||
SBI(endstop_hit_bits, Y_MIN);
|
||||
if (!stepper.performing_homing || (y_test == 0x3)) //if not performing home or if both endstops were trigged during homing...
|
||||
stepper.kill_current_block();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
void Endstops::test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2) {
|
||||
const byte z_test = TEST_ENDSTOP(es1) | (TEST_ENDSTOP(es2) << 1); // bit 0 for Z, bit 1 for Z2
|
||||
if (z_test && stepper.current_block->steps[Z_AXIS] > 0) {
|
||||
SBI(endstop_hit_bits, Z_MIN);
|
||||
if (!stepper.performing_homing || (z_test == 0x3)) //if not performing home or if both endstops were trigged during homing...
|
||||
stepper.kill_current_block();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// The following routines are called from an ISR context. It could be the temperature ISR, the
|
||||
// endstop ISR or the Stepper ISR.
|
||||
|
||||
// Check endstops - Called from ISR!
|
||||
#define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
|
||||
#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
|
||||
#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
|
||||
|
||||
// Check endstops - Could be called from ISR!
|
||||
void Endstops::update() {
|
||||
|
||||
#define _ENDSTOP(AXIS, MINMAX) AXIS ##_## MINMAX
|
||||
#define _ENDSTOP_PIN(AXIS, MINMAX) AXIS ##_## MINMAX ##_PIN
|
||||
#define _ENDSTOP_INVERTING(AXIS, MINMAX) AXIS ##_## MINMAX ##_ENDSTOP_INVERTING
|
||||
#define _ENDSTOP_HIT(AXIS, MINMAX) SBI(endstop_hit_bits, _ENDSTOP(AXIS, MINMAX))
|
||||
|
||||
#define SET_BIT(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
|
||||
// UPDATE_ENDSTOP_BIT: set the current endstop bits for an endstop to its status
|
||||
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT(current_endstop_bits, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
|
||||
#define UPDATE_ENDSTOP_BIT(AXIS, MINMAX) SET_BIT_TO(live_state, _ENDSTOP(AXIS, MINMAX), (READ(_ENDSTOP_PIN(AXIS, MINMAX)) != _ENDSTOP_INVERTING(AXIS, MINMAX)))
|
||||
// COPY_BIT: copy the value of SRC_BIT to DST_BIT in DST
|
||||
#define COPY_BIT(DST, SRC_BIT, DST_BIT) SET_BIT(DST, DST_BIT, TEST(DST, SRC_BIT))
|
||||
|
||||
#define UPDATE_ENDSTOP(AXIS,MINMAX) do { \
|
||||
UPDATE_ENDSTOP_BIT(AXIS, MINMAX); \
|
||||
if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
|
||||
_ENDSTOP_HIT(AXIS, MINMAX); \
|
||||
stepper.endstop_triggered(_AXIS(AXIS)); \
|
||||
} \
|
||||
}while(0)
|
||||
#define COPY_BIT(DST, SRC_BIT, DST_BIT) SET_BIT_TO(DST, DST_BIT, TEST(DST, SRC_BIT))
|
||||
|
||||
#if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
|
||||
// If G38 command is active check Z_MIN_PROBE for ALL movement
|
||||
if (G38_move) {
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
|
||||
if (TEST_ENDSTOP(_ENDSTOP(Z, MIN_PROBE))) {
|
||||
if (stepper.current_block->steps[_AXIS(X)] > 0) { _ENDSTOP_HIT(X, MIN); stepper.endstop_triggered(_AXIS(X)); }
|
||||
else if (stepper.current_block->steps[_AXIS(Y)] > 0) { _ENDSTOP_HIT(Y, MIN); stepper.endstop_triggered(_AXIS(Y)); }
|
||||
else if (stepper.current_block->steps[_AXIS(Z)] > 0) { _ENDSTOP_HIT(Z, MIN); stepper.endstop_triggered(_AXIS(Z)); }
|
||||
G38_endstop_hit = true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Define conditions for checking endstops
|
||||
*/
|
||||
|
||||
#if IS_CORE
|
||||
#define S_(N) stepper.current_block->steps[CORE_AXIS_##N]
|
||||
#define D_(N) stepper.motor_direction(CORE_AXIS_##N)
|
||||
#endif
|
||||
|
||||
#if CORE_IS_XY || CORE_IS_XZ
|
||||
/**
|
||||
* Head direction in -X axis for CoreXY and CoreXZ bots.
|
||||
*
|
||||
* If steps differ, both axes are moving.
|
||||
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z, handled below)
|
||||
* If DeltaA == DeltaB, the movement is only in the 1st axis (X)
|
||||
*/
|
||||
#if ENABLED(COREXY) || ENABLED(COREXZ)
|
||||
#define X_CMP ==
|
||||
#else
|
||||
#define X_CMP !=
|
||||
#endif
|
||||
#define X_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) X_CMP D_(2)) )
|
||||
#define X_AXIS_HEAD X_HEAD
|
||||
#else
|
||||
#define X_MOVE_TEST stepper.current_block->steps[X_AXIS] > 0
|
||||
#define X_AXIS_HEAD X_AXIS
|
||||
#endif
|
||||
|
||||
#if CORE_IS_XY || CORE_IS_YZ
|
||||
/**
|
||||
* Head direction in -Y axis for CoreXY / CoreYZ bots.
|
||||
*
|
||||
* If steps differ, both axes are moving
|
||||
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y)
|
||||
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Y or Z)
|
||||
*/
|
||||
#if ENABLED(COREYX) || ENABLED(COREYZ)
|
||||
#define Y_CMP ==
|
||||
#else
|
||||
#define Y_CMP !=
|
||||
#endif
|
||||
#define Y_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Y_CMP D_(2)) )
|
||||
#define Y_AXIS_HEAD Y_HEAD
|
||||
#else
|
||||
#define Y_MOVE_TEST stepper.current_block->steps[Y_AXIS] > 0
|
||||
#define Y_AXIS_HEAD Y_AXIS
|
||||
#endif
|
||||
|
||||
#if CORE_IS_XZ || CORE_IS_YZ
|
||||
/**
|
||||
* Head direction in -Z axis for CoreXZ or CoreYZ bots.
|
||||
*
|
||||
* If steps differ, both axes are moving
|
||||
* If DeltaA == DeltaB, the movement is only in the 1st axis (X or Y, already handled above)
|
||||
* If DeltaA == -DeltaB, the movement is only in the 2nd axis (Z)
|
||||
*/
|
||||
#if ENABLED(COREZX) || ENABLED(COREZY)
|
||||
#define Z_CMP ==
|
||||
#else
|
||||
#define Z_CMP !=
|
||||
#endif
|
||||
#define Z_MOVE_TEST ( S_(1) != S_(2) || (S_(1) > 0 && D_(1) Z_CMP D_(2)) )
|
||||
#define Z_AXIS_HEAD Z_HEAD
|
||||
#else
|
||||
#define Z_MOVE_TEST stepper.current_block->steps[Z_AXIS] > 0
|
||||
#define Z_AXIS_HEAD Z_AXIS
|
||||
if (G38_move) UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
|
||||
#endif
|
||||
|
||||
// With Dual X, endstops are only checked in the homing direction for the active extruder
|
||||
#if ENABLED(DUAL_X_CARRIAGE)
|
||||
#define E0_ACTIVE stepper.current_block->active_extruder == 0
|
||||
#define E0_ACTIVE stepper.movement_extruder() == 0
|
||||
#define X_MIN_TEST ((X_HOME_DIR < 0 && E0_ACTIVE) || (X2_HOME_DIR < 0 && !E0_ACTIVE))
|
||||
#define X_MAX_TEST ((X_HOME_DIR > 0 && E0_ACTIVE) || (X2_HOME_DIR > 0 && !E0_ACTIVE))
|
||||
#else
|
||||
@@ -418,127 +389,376 @@ void Endstops::update() {
|
||||
#define X_MAX_TEST true
|
||||
#endif
|
||||
|
||||
// Use HEAD for core axes, AXIS for others
|
||||
#if CORE_IS_XY || CORE_IS_XZ
|
||||
#define X_AXIS_HEAD X_HEAD
|
||||
#else
|
||||
#define X_AXIS_HEAD X_AXIS
|
||||
#endif
|
||||
#if CORE_IS_XY || CORE_IS_YZ
|
||||
#define Y_AXIS_HEAD Y_HEAD
|
||||
#else
|
||||
#define Y_AXIS_HEAD Y_AXIS
|
||||
#endif
|
||||
#if CORE_IS_XZ || CORE_IS_YZ
|
||||
#define Z_AXIS_HEAD Z_HEAD
|
||||
#else
|
||||
#define Z_AXIS_HEAD Z_AXIS
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Check and update endstops according to conditions
|
||||
*/
|
||||
if (stepper.current_block) {
|
||||
|
||||
if (X_MOVE_TEST) {
|
||||
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
|
||||
#if HAS_X_MIN
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(X, MIN);
|
||||
#if HAS_X2_MIN
|
||||
UPDATE_ENDSTOP_BIT(X2, MIN);
|
||||
#else
|
||||
COPY_BIT(current_endstop_bits, X_MIN, X2_MIN);
|
||||
#endif
|
||||
test_dual_x_endstops(X_MIN, X2_MIN);
|
||||
if (stepper.axis_is_moving(X_AXIS)) {
|
||||
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
|
||||
#if HAS_X_MIN
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(X, MIN);
|
||||
#if HAS_X2_MIN
|
||||
UPDATE_ENDSTOP_BIT(X2, MIN);
|
||||
#else
|
||||
if (X_MIN_TEST) UPDATE_ENDSTOP(X, MIN);
|
||||
COPY_BIT(live_state, X_MIN, X2_MIN);
|
||||
#endif
|
||||
#else
|
||||
if (X_MIN_TEST) UPDATE_ENDSTOP_BIT(X, MIN);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_X_MAX
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(X, MAX);
|
||||
#if HAS_X2_MAX
|
||||
UPDATE_ENDSTOP_BIT(X2, MAX);
|
||||
#else
|
||||
COPY_BIT(current_endstop_bits, X_MAX, X2_MAX);
|
||||
#endif
|
||||
test_dual_x_endstops(X_MAX, X2_MAX);
|
||||
#else
|
||||
if (X_MAX_TEST) UPDATE_ENDSTOP(X, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (Y_MOVE_TEST) {
|
||||
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
|
||||
#if HAS_Y_MIN
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Y, MIN);
|
||||
#if HAS_Y2_MIN
|
||||
UPDATE_ENDSTOP_BIT(Y2, MIN);
|
||||
#else
|
||||
COPY_BIT(current_endstop_bits, Y_MIN, Y2_MIN);
|
||||
#endif
|
||||
test_dual_y_endstops(Y_MIN, Y2_MIN);
|
||||
else { // +direction
|
||||
#if HAS_X_MAX
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(X, MAX);
|
||||
#if HAS_X2_MAX
|
||||
UPDATE_ENDSTOP_BIT(X2, MAX);
|
||||
#else
|
||||
UPDATE_ENDSTOP(Y, MIN);
|
||||
COPY_BIT(live_state, X_MAX, X2_MAX);
|
||||
#endif
|
||||
#else
|
||||
if (X_MAX_TEST) UPDATE_ENDSTOP_BIT(X, MAX);
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_Y_MAX
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Y, MAX);
|
||||
#if HAS_Y2_MAX
|
||||
UPDATE_ENDSTOP_BIT(Y2, MAX);
|
||||
#else
|
||||
COPY_BIT(current_endstop_bits, Y_MAX, Y2_MAX);
|
||||
#endif
|
||||
test_dual_y_endstops(Y_MAX, Y2_MAX);
|
||||
#else
|
||||
UPDATE_ENDSTOP(Y, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (Z_MOVE_TEST) {
|
||||
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
|
||||
#if HAS_Z_MIN
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
if (stepper.axis_is_moving(Y_AXIS)) {
|
||||
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
|
||||
#if HAS_Y_MIN
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Y, MIN);
|
||||
#if HAS_Y2_MIN
|
||||
UPDATE_ENDSTOP_BIT(Y2, MIN);
|
||||
#else
|
||||
COPY_BIT(live_state, Y_MIN, Y2_MIN);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(Y, MIN);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_Y_MAX
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Y, MAX);
|
||||
#if HAS_Y2_MAX
|
||||
UPDATE_ENDSTOP_BIT(Y2, MAX);
|
||||
#else
|
||||
COPY_BIT(live_state, Y_MAX, Y2_MAX);
|
||||
#endif
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(Y, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (stepper.axis_is_moving(Z_AXIS)) {
|
||||
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
|
||||
#if HAS_Z_MIN
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#if HAS_Z2_MIN
|
||||
UPDATE_ENDSTOP_BIT(Z2, MIN);
|
||||
#else
|
||||
COPY_BIT(live_state, Z_MIN, Z2_MIN);
|
||||
#endif
|
||||
#else
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
if (z_probe_enabled) UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#else
|
||||
UPDATE_ENDSTOP_BIT(Z, MIN);
|
||||
#if HAS_Z2_MIN
|
||||
UPDATE_ENDSTOP_BIT(Z2, MIN);
|
||||
#else
|
||||
COPY_BIT(current_endstop_bits, Z_MIN, Z2_MIN);
|
||||
#endif
|
||||
test_dual_z_endstops(Z_MIN, Z2_MIN);
|
||||
#else
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
if (z_probe_enabled) UPDATE_ENDSTOP(Z, MIN);
|
||||
#else
|
||||
UPDATE_ENDSTOP(Z, MIN);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// When closing the gap check the enabled probe
|
||||
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
|
||||
if (z_probe_enabled) {
|
||||
UPDATE_ENDSTOP(Z, MIN_PROBE);
|
||||
if (TEST_ENDSTOP(Z_MIN_PROBE)) SBI(endstop_hit_bits, Z_MIN_PROBE);
|
||||
}
|
||||
// When closing the gap check the enabled probe
|
||||
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
|
||||
if (z_probe_enabled) UPDATE_ENDSTOP_BIT(Z, MIN_PROBE);
|
||||
#endif
|
||||
}
|
||||
else { // Z +direction. Gantry up, bed down.
|
||||
#if HAS_Z_MAX
|
||||
// Check both Z dual endstops
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Z, MAX);
|
||||
#if HAS_Z2_MAX
|
||||
UPDATE_ENDSTOP_BIT(Z2, MAX);
|
||||
#else
|
||||
COPY_BIT(live_state, Z_MAX, Z2_MAX);
|
||||
#endif
|
||||
// If this pin is not hijacked for the bed probe
|
||||
// then it belongs to the Z endstop
|
||||
#elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
|
||||
UPDATE_ENDSTOP_BIT(Z, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
// All endstops were updated.
|
||||
#if ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
if (old_live_state != live_state) { // We detected a change. Reinit the timeout
|
||||
/**
|
||||
* Filtering out noise on endstops requires a delayed decision. Let's assume, due to noise,
|
||||
* that 50% of endstop signal samples are good and 50% are bad (assuming normal distribution
|
||||
* of random noise). Then the first sample has a 50% chance to be good or bad. The 2nd sample
|
||||
* also has a 50% chance to be good or bad. The chances of 2 samples both being bad becomes
|
||||
* 50% of 50%, or 25%. That was the previous implementation of Marlin endstop handling. It
|
||||
* reduces chances of bad readings in half, at the cost of 1 extra sample period, but chances
|
||||
* still exist. The only way to reduce them further is to increase the number of samples.
|
||||
* To reduce the chance to 1% (1/128th) requires 7 samples (adding 7ms of delay).
|
||||
*/
|
||||
endstop_poll_count = 7;
|
||||
old_live_state = live_state;
|
||||
}
|
||||
else if (endstop_poll_count && !--endstop_poll_count)
|
||||
validated_live_state = live_state;
|
||||
|
||||
#else
|
||||
|
||||
// Lets accept the new endstop values as valid - We assume hardware filtering of lines
|
||||
esbits_t validated_live_state = live_state;
|
||||
|
||||
#endif
|
||||
|
||||
// Endstop readings are validated in validated_live_state
|
||||
|
||||
// Test the current status of an endstop
|
||||
#define TEST_ENDSTOP(ENDSTOP) (TEST(validated_live_state, ENDSTOP))
|
||||
|
||||
// Record endstop was hit
|
||||
#define _ENDSTOP_HIT(AXIS, MINMAX) SBI(hit_state, _ENDSTOP(AXIS, MINMAX))
|
||||
|
||||
// Call the endstop triggered routine for single endstops
|
||||
#define PROCESS_ENDSTOP(AXIS,MINMAX) do { \
|
||||
if (TEST_ENDSTOP(_ENDSTOP(AXIS, MINMAX))) { \
|
||||
_ENDSTOP_HIT(AXIS, MINMAX); \
|
||||
planner.endstop_triggered(_AXIS(AXIS)); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
// Call the endstop triggered routine for single endstops
|
||||
#define PROCESS_DUAL_ENDSTOP(AXIS1, AXIS2, MINMAX) do { \
|
||||
if (TEST_ENDSTOP(_ENDSTOP(AXIS1, MINMAX)) || TEST_ENDSTOP(_ENDSTOP(AXIS2, MINMAX))) { \
|
||||
_ENDSTOP_HIT(AXIS1, MINMAX); \
|
||||
planner.endstop_triggered(_AXIS(AXIS1)); \
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#if ENABLED(G38_PROBE_TARGET) && PIN_EXISTS(Z_MIN_PROBE) && !(CORE_IS_XY || CORE_IS_XZ)
|
||||
// If G38 command is active check Z_MIN_PROBE for ALL movement
|
||||
if (G38_move) {
|
||||
if (TEST_ENDSTOP(_ENDSTOP(Z, MIN_PROBE))) {
|
||||
if (stepper.axis_is_moving(X_AXIS)) { _ENDSTOP_HIT(X, MIN); planner.endstop_triggered(X_AXIS); }
|
||||
else if (stepper.axis_is_moving(Y_AXIS)) { _ENDSTOP_HIT(Y, MIN); planner.endstop_triggered(Y_AXIS); }
|
||||
else if (stepper.axis_is_moving(Z_AXIS)) { _ENDSTOP_HIT(Z, MIN); planner.endstop_triggered(Z_AXIS); }
|
||||
G38_endstop_hit = true;
|
||||
}
|
||||
else { // Z +direction. Gantry up, bed down.
|
||||
#if HAS_Z_MAX
|
||||
// Check both Z dual endstops
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
UPDATE_ENDSTOP_BIT(Z, MAX);
|
||||
#if HAS_Z2_MAX
|
||||
UPDATE_ENDSTOP_BIT(Z2, MAX);
|
||||
#else
|
||||
COPY_BIT(current_endstop_bits, Z_MAX, Z2_MAX);
|
||||
#endif
|
||||
test_dual_z_endstops(Z_MAX, Z2_MAX);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Now, we must signal, after validation, if an endstop limit is pressed or not
|
||||
if (stepper.axis_is_moving(X_AXIS)) {
|
||||
if (stepper.motor_direction(X_AXIS_HEAD)) { // -direction
|
||||
#if HAS_X_MIN
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
PROCESS_DUAL_ENDSTOP(X, X2, MIN);
|
||||
#else
|
||||
if (X_MIN_TEST) PROCESS_ENDSTOP(X, MIN);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_X_MAX
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
PROCESS_DUAL_ENDSTOP(X, X2, MAX);
|
||||
#else
|
||||
if (X_MAX_TEST) PROCESS_ENDSTOP(X, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (stepper.axis_is_moving(Y_AXIS)) {
|
||||
if (stepper.motor_direction(Y_AXIS_HEAD)) { // -direction
|
||||
#if HAS_Y_MIN
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
PROCESS_DUAL_ENDSTOP(Y, Y2, MIN);
|
||||
#else
|
||||
PROCESS_ENDSTOP(Y, MIN);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
else { // +direction
|
||||
#if HAS_Y_MAX
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
PROCESS_DUAL_ENDSTOP(Y, Y2, MAX);
|
||||
#else
|
||||
PROCESS_ENDSTOP(Y, MAX);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (stepper.axis_is_moving(Z_AXIS)) {
|
||||
if (stepper.motor_direction(Z_AXIS_HEAD)) { // Z -direction. Gantry down, bed up.
|
||||
#if HAS_Z_MIN
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
PROCESS_DUAL_ENDSTOP(Z, Z2, MIN);
|
||||
#else
|
||||
#if ENABLED(Z_MIN_PROBE_USES_Z_MIN_ENDSTOP_PIN)
|
||||
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN);
|
||||
#else
|
||||
PROCESS_ENDSTOP(Z, MIN);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// When closing the gap check the enabled probe
|
||||
#if ENABLED(Z_MIN_PROBE_ENDSTOP)
|
||||
if (z_probe_enabled) PROCESS_ENDSTOP(Z, MIN_PROBE);
|
||||
#endif
|
||||
}
|
||||
else { // Z +direction. Gantry up, bed down.
|
||||
#if HAS_Z_MAX
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
PROCESS_DUAL_ENDSTOP(Z, Z2, MAX);
|
||||
#elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
|
||||
// If this pin is not hijacked for the bed probe
|
||||
// then it belongs to the Z endstop
|
||||
#elif DISABLED(Z_MIN_PROBE_ENDSTOP) || Z_MAX_PIN != Z_MIN_PROBE_PIN
|
||||
UPDATE_ENDSTOP(Z, MAX);
|
||||
#endif
|
||||
PROCESS_ENDSTOP(Z, MAX);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
} // stepper.current_block
|
||||
|
||||
old_endstop_bits = current_endstop_bits;
|
||||
|
||||
}
|
||||
} // Endstops::update()
|
||||
|
||||
#if ENABLED(PINS_DEBUGGING)
|
||||
|
||||
bool Endstops::monitor_flag = false;
|
||||
|
||||
/**
|
||||
* monitors endstops & Z probe for changes
|
||||
*
|
||||
* If a change is detected then the LED is toggled and
|
||||
* a message is sent out the serial port
|
||||
*
|
||||
* Yes, we could miss a rapid back & forth change but
|
||||
* that won't matter because this is all manual.
|
||||
*
|
||||
*/
|
||||
void Endstops::monitor() {
|
||||
|
||||
static uint16_t old_live_state_local = 0;
|
||||
static uint8_t local_LED_status = 0;
|
||||
uint16_t live_state_local = 0;
|
||||
|
||||
#if HAS_X_MIN
|
||||
if (READ(X_MIN_PIN)) SBI(live_state_local, X_MIN);
|
||||
#endif
|
||||
#if HAS_X_MAX
|
||||
if (READ(X_MAX_PIN)) SBI(live_state_local, X_MAX);
|
||||
#endif
|
||||
#if HAS_Y_MIN
|
||||
if (READ(Y_MIN_PIN)) SBI(live_state_local, Y_MIN);
|
||||
#endif
|
||||
#if HAS_Y_MAX
|
||||
if (READ(Y_MAX_PIN)) SBI(live_state_local, Y_MAX);
|
||||
#endif
|
||||
#if HAS_Z_MIN
|
||||
if (READ(Z_MIN_PIN)) SBI(live_state_local, Z_MIN);
|
||||
#endif
|
||||
#if HAS_Z_MAX
|
||||
if (READ(Z_MAX_PIN)) SBI(live_state_local, Z_MAX);
|
||||
#endif
|
||||
#if HAS_Z_MIN_PROBE_PIN
|
||||
if (READ(Z_MIN_PROBE_PIN)) SBI(live_state_local, Z_MIN_PROBE);
|
||||
#endif
|
||||
#if HAS_X2_MIN
|
||||
if (READ(X2_MIN_PIN)) SBI(live_state_local, X2_MIN);
|
||||
#endif
|
||||
#if HAS_X2_MAX
|
||||
if (READ(X2_MAX_PIN)) SBI(live_state_local, X2_MAX);
|
||||
#endif
|
||||
#if HAS_Y2_MIN
|
||||
if (READ(Y2_MIN_PIN)) SBI(live_state_local, Y2_MIN);
|
||||
#endif
|
||||
#if HAS_Y2_MAX
|
||||
if (READ(Y2_MAX_PIN)) SBI(live_state_local, Y2_MAX);
|
||||
#endif
|
||||
#if HAS_Z2_MIN
|
||||
if (READ(Z2_MIN_PIN)) SBI(live_state_local, Z2_MIN);
|
||||
#endif
|
||||
#if HAS_Z2_MAX
|
||||
if (READ(Z2_MAX_PIN)) SBI(live_state_local, Z2_MAX);
|
||||
#endif
|
||||
|
||||
uint16_t endstop_change = live_state_local ^ old_live_state_local;
|
||||
|
||||
if (endstop_change) {
|
||||
#if HAS_X_MIN
|
||||
if (TEST(endstop_change, X_MIN)) SERIAL_PROTOCOLPAIR(" X_MIN:", TEST(live_state_local, X_MIN));
|
||||
#endif
|
||||
#if HAS_X_MAX
|
||||
if (TEST(endstop_change, X_MAX)) SERIAL_PROTOCOLPAIR(" X_MAX:", TEST(live_state_local, X_MAX));
|
||||
#endif
|
||||
#if HAS_Y_MIN
|
||||
if (TEST(endstop_change, Y_MIN)) SERIAL_PROTOCOLPAIR(" Y_MIN:", TEST(live_state_local, Y_MIN));
|
||||
#endif
|
||||
#if HAS_Y_MAX
|
||||
if (TEST(endstop_change, Y_MAX)) SERIAL_PROTOCOLPAIR(" Y_MAX:", TEST(live_state_local, Y_MAX));
|
||||
#endif
|
||||
#if HAS_Z_MIN
|
||||
if (TEST(endstop_change, Z_MIN)) SERIAL_PROTOCOLPAIR(" Z_MIN:", TEST(live_state_local, Z_MIN));
|
||||
#endif
|
||||
#if HAS_Z_MAX
|
||||
if (TEST(endstop_change, Z_MAX)) SERIAL_PROTOCOLPAIR(" Z_MAX:", TEST(live_state_local, Z_MAX));
|
||||
#endif
|
||||
#if HAS_Z_MIN_PROBE_PIN
|
||||
if (TEST(endstop_change, Z_MIN_PROBE)) SERIAL_PROTOCOLPAIR(" PROBE:", TEST(live_state_local, Z_MIN_PROBE));
|
||||
#endif
|
||||
#if HAS_X2_MIN
|
||||
if (TEST(endstop_change, X2_MIN)) SERIAL_PROTOCOLPAIR(" X2_MIN:", TEST(live_state_local, X2_MIN));
|
||||
#endif
|
||||
#if HAS_X2_MAX
|
||||
if (TEST(endstop_change, X2_MAX)) SERIAL_PROTOCOLPAIR(" X2_MAX:", TEST(live_state_local, X2_MAX));
|
||||
#endif
|
||||
#if HAS_Y2_MIN
|
||||
if (TEST(endstop_change, Y2_MIN)) SERIAL_PROTOCOLPAIR(" Y2_MIN:", TEST(live_state_local, Y2_MIN));
|
||||
#endif
|
||||
#if HAS_Y2_MAX
|
||||
if (TEST(endstop_change, Y2_MAX)) SERIAL_PROTOCOLPAIR(" Y2_MAX:", TEST(live_state_local, Y2_MAX));
|
||||
#endif
|
||||
#if HAS_Z2_MIN
|
||||
if (TEST(endstop_change, Z2_MIN)) SERIAL_PROTOCOLPAIR(" Z2_MIN:", TEST(live_state_local, Z2_MIN));
|
||||
#endif
|
||||
#if HAS_Z2_MAX
|
||||
if (TEST(endstop_change, Z2_MAX)) SERIAL_PROTOCOLPAIR(" Z2_MAX:", TEST(live_state_local, Z2_MAX));
|
||||
#endif
|
||||
SERIAL_PROTOCOLPGM("\n\n");
|
||||
analogWrite(LED_PIN, local_LED_status);
|
||||
local_LED_status ^= 255;
|
||||
old_live_state_local = live_state_local;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // PINS_DEBUGGING
|
||||
|
||||
+60
-36
@@ -27,15 +27,29 @@
|
||||
#ifndef __ENDSTOPS_H__
|
||||
#define __ENDSTOPS_H__
|
||||
|
||||
#include "enum.h"
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
enum EndstopEnum : char {
|
||||
X_MIN,
|
||||
Y_MIN,
|
||||
Z_MIN,
|
||||
Z_MIN_PROBE,
|
||||
X_MAX,
|
||||
Y_MAX,
|
||||
Z_MAX,
|
||||
X2_MIN,
|
||||
X2_MAX,
|
||||
Y2_MIN,
|
||||
Y2_MAX,
|
||||
Z2_MIN,
|
||||
Z2_MAX
|
||||
};
|
||||
|
||||
class Endstops {
|
||||
|
||||
public:
|
||||
|
||||
static bool enabled, enabled_globally;
|
||||
static volatile char endstop_hit_bits; // use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT value
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
|
||||
typedef uint16_t esbits_t;
|
||||
@@ -49,35 +63,56 @@ class Endstops {
|
||||
static float z_endstop_adj;
|
||||
#endif
|
||||
#else
|
||||
typedef byte esbits_t;
|
||||
typedef uint8_t esbits_t;
|
||||
#endif
|
||||
|
||||
static esbits_t current_endstop_bits, old_endstop_bits;
|
||||
private:
|
||||
static esbits_t live_state;
|
||||
static volatile uint8_t hit_state; // Use X_MIN, Y_MIN, Z_MIN and Z_MIN_PROBE as BIT index
|
||||
#if ENABLED(ENDSTOP_NOISE_FILTER)
|
||||
static esbits_t old_live_state, // Old endstop value for debouncing and denoising
|
||||
validated_live_state; // The validated (accepted as true) endstop bits
|
||||
static uint8_t endstop_poll_count; // Countdown from threshold for polling
|
||||
#endif
|
||||
|
||||
Endstops() {
|
||||
enable_globally(
|
||||
#if ENABLED(ENDSTOPS_ALWAYS_ON_DEFAULT)
|
||||
true
|
||||
#else
|
||||
false
|
||||
#endif
|
||||
);
|
||||
};
|
||||
public:
|
||||
Endstops() {};
|
||||
|
||||
/**
|
||||
* Initialize the endstop pins
|
||||
*/
|
||||
static void init();
|
||||
|
||||
/**
|
||||
* A change was detected or presumed to be in endstops pins. Find out what
|
||||
* changed, if anything. Called from ISR contexts
|
||||
*/
|
||||
static void check_possible_change();
|
||||
|
||||
/**
|
||||
* Periodic call to poll endstops if required. Called from temperature ISR
|
||||
*/
|
||||
static void poll();
|
||||
|
||||
/**
|
||||
* Update the endstops bits from the pins
|
||||
*/
|
||||
static void update();
|
||||
|
||||
/**
|
||||
* Print an error message reporting the position when the endstops were last hit.
|
||||
* Get Endstop hit state.
|
||||
*/
|
||||
static void report_state(); //call from somewhere to create an serial error message with the locations the endstops where hit, in case they were triggered
|
||||
FORCE_INLINE static uint8_t trigger_state() { return hit_state; }
|
||||
|
||||
/**
|
||||
* Get current endstops state
|
||||
*/
|
||||
FORCE_INLINE static esbits_t state() { return live_state; }
|
||||
|
||||
/**
|
||||
* Report endstop hits to serial. Called from loop().
|
||||
*/
|
||||
static void report_state();
|
||||
|
||||
/**
|
||||
* Report endstop positions in response to M119
|
||||
@@ -85,42 +120,31 @@ class Endstops {
|
||||
static void M119();
|
||||
|
||||
// Enable / disable endstop checking globally
|
||||
static void enable_globally(bool onoff=true) { enabled_globally = enabled = onoff; }
|
||||
static void enable_globally(const bool onoff=true);
|
||||
|
||||
// Enable / disable endstop checking
|
||||
static void enable(bool onoff=true) { enabled = onoff; }
|
||||
static void enable(const bool onoff=true);
|
||||
|
||||
// Disable / Enable endstops based on ENSTOPS_ONLY_FOR_HOMING and global enable
|
||||
static void not_homing() { enabled = enabled_globally; }
|
||||
static void not_homing();
|
||||
|
||||
// Clear endstops (i.e., they were hit intentionally) to suppress the report
|
||||
static void hit_on_purpose() { endstop_hit_bits = 0; }
|
||||
FORCE_INLINE static void hit_on_purpose() { hit_state = 0; }
|
||||
|
||||
// Enable / disable endstop z-probe checking
|
||||
#if HAS_BED_PROBE
|
||||
static volatile bool z_probe_enabled;
|
||||
static void enable_z_probe(bool onoff=true) { z_probe_enabled = onoff; }
|
||||
static void enable_z_probe(bool onoff=true);
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
static void test_dual_x_endstops(const EndstopEnum es1, const EndstopEnum es2);
|
||||
#endif
|
||||
#if ENABLED(Y_DUAL_ENDSTOPS)
|
||||
static void test_dual_y_endstops(const EndstopEnum es1, const EndstopEnum es2);
|
||||
#endif
|
||||
#if ENABLED(Z_DUAL_ENDSTOPS)
|
||||
static void test_dual_z_endstops(const EndstopEnum es1, const EndstopEnum es2);
|
||||
// Debugging of endstops
|
||||
#if ENABLED(PINS_DEBUGGING)
|
||||
static bool monitor_flag;
|
||||
static void monitor();
|
||||
static void run_monitor();
|
||||
#endif
|
||||
};
|
||||
|
||||
extern Endstops endstops;
|
||||
|
||||
#if HAS_BED_PROBE
|
||||
#define ENDSTOPS_ENABLED (endstops.enabled || endstops.z_probe_enabled)
|
||||
#else
|
||||
#define ENDSTOPS_ENABLED endstops.enabled
|
||||
#endif
|
||||
|
||||
#endif // __ENDSTOPS_H__
|
||||
|
||||
+3
-20
@@ -28,10 +28,9 @@
|
||||
/**
|
||||
* Axis indices as enumerated constants
|
||||
*
|
||||
* Special axis:
|
||||
* - A_AXIS and B_AXIS are used by COREXY printers
|
||||
* - X_HEAD and Y_HEAD is used for systems that don't have a 1:1 relationship
|
||||
* between X_AXIS and X Head movement, like CoreXY bots
|
||||
* - X_AXIS, Y_AXIS, and Z_AXIS should be used for axes in Cartesian space
|
||||
* - A_AXIS, B_AXIS, and C_AXIS should be used for Steppers, corresponding to XYZ on Cartesians
|
||||
* - X_HEAD, Y_HEAD, and Z_HEAD should be used for Steppers on Core kinematics
|
||||
*/
|
||||
enum AxisEnum : unsigned char {
|
||||
X_AXIS = 0,
|
||||
@@ -88,22 +87,6 @@ enum DebugFlags : unsigned char {
|
||||
DEBUG_ALL = 0xFF
|
||||
};
|
||||
|
||||
enum EndstopEnum : char {
|
||||
X_MIN,
|
||||
Y_MIN,
|
||||
Z_MIN,
|
||||
Z_MIN_PROBE,
|
||||
X_MAX,
|
||||
Y_MAX,
|
||||
Z_MAX,
|
||||
X2_MIN,
|
||||
X2_MAX,
|
||||
Y2_MIN,
|
||||
Y2_MAX,
|
||||
Z2_MIN,
|
||||
Z2_MAX
|
||||
};
|
||||
|
||||
#if ENABLED(ADVANCED_PAUSE_FEATURE)
|
||||
enum AdvancedPauseMenuResponse : char {
|
||||
ADVANCED_PAUSE_RESPONSE_WAIT_FOR,
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int8_t pin_t;
|
||||
#ifndef _FASTIO_ARDUINO_H_
|
||||
#define _FASTIO_ARDUINO_H_
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ int finish_incremental_LSF(struct linear_fit_data *lsf) {
|
||||
lsf->xzbar = lsf->xzbar / N - lsf->xbar * lsf->zbar;
|
||||
const float DD = lsf->x2bar * lsf->y2bar - sq(lsf->xybar);
|
||||
|
||||
if (FABS(DD) <= 1e-10 * (lsf->max_absx + lsf->max_absy))
|
||||
if (ABS(DD) <= 1e-10 * (lsf->max_absx + lsf->max_absy))
|
||||
return 1;
|
||||
|
||||
lsf->A = (lsf->yzbar * lsf->xybar - lsf->xzbar * lsf->y2bar) / DD;
|
||||
|
||||
@@ -65,8 +65,8 @@ void inline incremental_WLSF(struct linear_fit_data *lsf, const float &x, const
|
||||
lsf->xzbar += w * x * z;
|
||||
lsf->yzbar += w * y * z;
|
||||
lsf->N += w;
|
||||
lsf->max_absx = max(FABS(w * x), lsf->max_absx);
|
||||
lsf->max_absy = max(FABS(w * y), lsf->max_absy);
|
||||
lsf->max_absx = MAX(ABS(w * x), lsf->max_absx);
|
||||
lsf->max_absy = MAX(ABS(w * y), lsf->max_absy);
|
||||
}
|
||||
|
||||
void inline incremental_LSF(struct linear_fit_data *lsf, const float &x, const float &y, const float &z) {
|
||||
@@ -79,8 +79,8 @@ void inline incremental_LSF(struct linear_fit_data *lsf, const float &x, const f
|
||||
lsf->xybar += x * y;
|
||||
lsf->xzbar += x * z;
|
||||
lsf->yzbar += y * z;
|
||||
lsf->max_absx = max(FABS(x), lsf->max_absx);
|
||||
lsf->max_absy = max(FABS(y), lsf->max_absy);
|
||||
lsf->max_absx = MAX(ABS(x), lsf->max_absx);
|
||||
lsf->max_absy = MAX(ABS(y), lsf->max_absy);
|
||||
lsf->N += 1.0;
|
||||
}
|
||||
|
||||
|
||||
+52
-69
@@ -30,7 +30,7 @@
|
||||
#define XYZ 3
|
||||
|
||||
// For use in macros that take a single axis letter
|
||||
#define _AXIS(AXIS) AXIS ##_AXIS
|
||||
#define _AXIS(A) (A##_AXIS)
|
||||
|
||||
#define _XMIN_ 100
|
||||
#define _YMIN_ 200
|
||||
@@ -47,68 +47,12 @@
|
||||
#define _O2 __attribute__((optimize("O2")))
|
||||
#define _O3 __attribute__((optimize("O3")))
|
||||
|
||||
// Bracket code that shouldn't be interrupted
|
||||
#ifndef CRITICAL_SECTION_START
|
||||
#define CRITICAL_SECTION_START unsigned char _sreg = SREG; cli();
|
||||
#define CRITICAL_SECTION_END SREG = _sreg;
|
||||
#endif
|
||||
|
||||
// Clock speed factors
|
||||
#define CYCLES_PER_MICROSECOND (F_CPU / 1000000L) // 16 or 20
|
||||
#define INT0_PRESCALER 8
|
||||
|
||||
// Processor-level delays for hardware interfaces
|
||||
#ifndef _NOP
|
||||
#define _NOP() do { __asm__ volatile ("nop"); } while (0)
|
||||
#endif
|
||||
#define DELAY_NOPS(X) \
|
||||
switch (X) { \
|
||||
case 20: _NOP(); case 19: _NOP(); case 18: _NOP(); case 17: _NOP(); \
|
||||
case 16: _NOP(); case 15: _NOP(); case 14: _NOP(); case 13: _NOP(); \
|
||||
case 12: _NOP(); case 11: _NOP(); case 10: _NOP(); case 9: _NOP(); \
|
||||
case 8: _NOP(); case 7: _NOP(); case 6: _NOP(); case 5: _NOP(); \
|
||||
case 4: _NOP(); case 3: _NOP(); case 2: _NOP(); case 1: _NOP(); \
|
||||
}
|
||||
#define DELAY_0_NOP NOOP
|
||||
#define DELAY_1_NOP DELAY_NOPS( 1)
|
||||
#define DELAY_2_NOP DELAY_NOPS( 2)
|
||||
#define DELAY_3_NOP DELAY_NOPS( 3)
|
||||
#define DELAY_4_NOP DELAY_NOPS( 4)
|
||||
#define DELAY_5_NOP DELAY_NOPS( 5)
|
||||
#define DELAY_10_NOP DELAY_NOPS(10)
|
||||
#define DELAY_20_NOP DELAY_NOPS(20)
|
||||
|
||||
#if CYCLES_PER_MICROSECOND <= 200
|
||||
#define DELAY_100NS DELAY_NOPS((CYCLES_PER_MICROSECOND + 9) / 10)
|
||||
#else
|
||||
#define DELAY_100NS DELAY_20_NOP
|
||||
#endif
|
||||
|
||||
// Microsecond delays for hardware interfaces
|
||||
#if CYCLES_PER_MICROSECOND <= 20
|
||||
#define DELAY_1US DELAY_NOPS(CYCLES_PER_MICROSECOND)
|
||||
#define DELAY_US(X) \
|
||||
switch (X) { \
|
||||
case 20: DELAY_1US; case 19: DELAY_1US; case 18: DELAY_1US; case 17: DELAY_1US; \
|
||||
case 16: DELAY_1US; case 15: DELAY_1US; case 14: DELAY_1US; case 13: DELAY_1US; \
|
||||
case 12: DELAY_1US; case 11: DELAY_1US; case 10: DELAY_1US; case 9: DELAY_1US; \
|
||||
case 8: DELAY_1US; case 7: DELAY_1US; case 6: DELAY_1US; case 5: DELAY_1US; \
|
||||
case 4: DELAY_1US; case 3: DELAY_1US; case 2: DELAY_1US; case 1: DELAY_1US; \
|
||||
}
|
||||
#else
|
||||
#define DELAY_US(X) delayMicroseconds(X) // May not be usable in CRITICAL_SECTION
|
||||
#define DELAY_1US DELAY_US(1)
|
||||
#endif
|
||||
#define DELAY_2US DELAY_US( 2)
|
||||
#define DELAY_3US DELAY_US( 3)
|
||||
#define DELAY_4US DELAY_US( 4)
|
||||
#define DELAY_5US DELAY_US( 5)
|
||||
#define DELAY_6US DELAY_US( 6)
|
||||
#define DELAY_7US DELAY_US( 7)
|
||||
#define DELAY_8US DELAY_US( 8)
|
||||
#define DELAY_9US DELAY_US( 9)
|
||||
#define DELAY_10US DELAY_US(10)
|
||||
#define DELAY_20US DELAY_US(20)
|
||||
// Nanoseconds per cycle
|
||||
#define NANOSECONDS_PER_CYCLE (1000000000.0 / F_CPU)
|
||||
|
||||
// Remove compiler warning on an unused variable
|
||||
#define UNUSED(x) (void) (x)
|
||||
@@ -122,10 +66,11 @@
|
||||
|
||||
// Macros for bit masks
|
||||
#undef _BV
|
||||
#define _BV(b) (1<<(b))
|
||||
#define _BV(b) (1 << (b))
|
||||
#define TEST(n,b) !!((n)&_BV(b))
|
||||
#define SBI(n,b) (n |= _BV(b))
|
||||
#define CBI(n,b) (n &= ~_BV(b))
|
||||
#define SET_BIT_TO(N,B,TF) do{ if (TF) SBI(N,B); else CBI(N,B); }while(0)
|
||||
|
||||
#define _BV32(b) (1UL << (b))
|
||||
#define TEST32(n,b) !!((n)&_BV32(b))
|
||||
@@ -152,6 +97,7 @@
|
||||
// Macros to contrain values
|
||||
#define NOLESS(v,n) do{ if (v < n) v = n; }while(0)
|
||||
#define NOMORE(v,n) do{ if (v > n) v = n; }while(0)
|
||||
#define LIMIT(v,n1,n2) do{ if (v < n1) v = n1; else if (v > n2) v = n2; }while(0)
|
||||
|
||||
// Macros to support option testing
|
||||
#define _CAT(a, ...) a ## __VA_ARGS__
|
||||
@@ -159,9 +105,11 @@
|
||||
#define SWITCH_ENABLED_true 1
|
||||
#define SWITCH_ENABLED_0 0
|
||||
#define SWITCH_ENABLED_1 1
|
||||
#define SWITCH_ENABLED_0x0 0
|
||||
#define SWITCH_ENABLED_0x1 1
|
||||
#define SWITCH_ENABLED_ 1
|
||||
#define ENABLED(b) _CAT(SWITCH_ENABLED_, b)
|
||||
#define DISABLED(b) (!_CAT(SWITCH_ENABLED_, b))
|
||||
#define DISABLED(b) !ENABLED(b)
|
||||
|
||||
#define WITHIN(V,L,H) ((V) >= (L) && (V) <= (H))
|
||||
#define NUMERIC(a) WITHIN(a, '0', '9')
|
||||
@@ -170,7 +118,7 @@
|
||||
#define DECIMAL_SIGNED(a) (DECIMAL(a) || (a) == '-' || (a) == '+')
|
||||
#define COUNT(a) (sizeof(a)/sizeof(*a))
|
||||
#define ZERO(a) memset(a,0,sizeof(a))
|
||||
#define COPY(a,b) memcpy(a,b,min(sizeof(a),sizeof(b)))
|
||||
#define COPY(a,b) memcpy(a,b,MIN(sizeof(a),sizeof(b)))
|
||||
|
||||
// Macros for initializing arrays
|
||||
#define ARRAY_6(v1, v2, v3, v4, v5, v6, ...) { v1, v2, v3, v4, v5, v6 }
|
||||
@@ -221,12 +169,48 @@
|
||||
|
||||
#define CEILING(x,y) (((x) + (y) - 1) / (y))
|
||||
|
||||
#define MIN3(a, b, c) min(min(a, b), c)
|
||||
#define MIN4(a, b, c, d) min(MIN3(a, b, c), d)
|
||||
#define MIN5(a, b, c, d, e) min(MIN4(a, b, c, d), e)
|
||||
#define MAX3(a, b, c) max(max(a, b), c)
|
||||
#define MAX4(a, b, c, d) max(MAX3(a, b, c), d)
|
||||
#define MAX5(a, b, c, d, e) max(MAX4(a, b, c, d), e)
|
||||
// Avoid double evaluation of arguments on MIN/MAX/ABS
|
||||
#undef MIN
|
||||
#undef MAX
|
||||
#undef ABS
|
||||
#ifdef __cplusplus
|
||||
|
||||
// C++11 solution that is standards compliant. Return type is deduced automatically
|
||||
template <class L, class R> static inline constexpr auto MIN(const L lhs, const R rhs) -> decltype(lhs + rhs) {
|
||||
return lhs < rhs ? lhs : rhs;
|
||||
}
|
||||
template <class L, class R> static inline constexpr auto MAX(const L lhs, const R rhs) -> decltype(lhs + rhs){
|
||||
return lhs > rhs ? lhs : rhs;
|
||||
}
|
||||
template <class T> static inline constexpr const T ABS(const T v) {
|
||||
return v >= 0 ? v : -v;
|
||||
}
|
||||
#else
|
||||
|
||||
// Using GCC extensions, but Travis GCC version does not like it and gives
|
||||
// "error: statement-expressions are not allowed outside functions nor in template-argument lists"
|
||||
#define MIN(a, b) \
|
||||
({__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b;})
|
||||
|
||||
#define MAX(a, b) \
|
||||
({__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b;})
|
||||
|
||||
#define ABS(a) \
|
||||
({__typeof__(a) _a = (a); \
|
||||
_a >= 0 ? _a : -_a;})
|
||||
|
||||
#endif
|
||||
|
||||
#define MIN3(a, b, c) MIN(MIN(a, b), c)
|
||||
#define MIN4(a, b, c, d) MIN(MIN3(a, b, c), d)
|
||||
#define MIN5(a, b, c, d, e) MIN(MIN4(a, b, c, d), e)
|
||||
#define MAX3(a, b, c) MAX(MAX(a, b), c)
|
||||
#define MAX4(a, b, c, d) MAX(MAX3(a, b, c), d)
|
||||
#define MAX5(a, b, c, d, e) MAX(MAX4(a, b, c, d), e)
|
||||
|
||||
#define UNEAR_ZERO(x) ((x) < 0.000001)
|
||||
#define NEAR_ZERO(x) WITHIN(x, -0.000001, 0.000001)
|
||||
@@ -239,7 +223,6 @@
|
||||
// Maths macros that can be overridden by HAL
|
||||
//
|
||||
#define ATAN2(y, x) atan2(y, x)
|
||||
#define FABS(x) fabs(x)
|
||||
#define POW(x, y) pow(x, y)
|
||||
#define SQRT(x) sqrt(x)
|
||||
#define CEIL(x) ceil(x)
|
||||
|
||||
+105
-73
@@ -45,8 +45,13 @@
|
||||
|
||||
#if ENABLED(MALYAN_LCD)
|
||||
|
||||
#include "cardreader.h"
|
||||
#include "SdFatConfig.h"
|
||||
#if ENABLED(SDSUPPORT)
|
||||
#include "cardreader.h"
|
||||
#include "SdFatConfig.h"
|
||||
#else
|
||||
#define LONG_FILENAME_LENGTH 0
|
||||
#endif
|
||||
|
||||
#include "temperature.h"
|
||||
#include "planner.h"
|
||||
#include "stepper.h"
|
||||
@@ -57,6 +62,15 @@
|
||||
|
||||
#include "Marlin.h"
|
||||
|
||||
#if USE_MARLINSERIAL
|
||||
// Make an exception to use HardwareSerial too
|
||||
#undef HardwareSerial_h
|
||||
#include <HardwareSerial.h>
|
||||
#define USB_STATUS true
|
||||
#else
|
||||
#define USB_STATUS Serial
|
||||
#endif
|
||||
|
||||
// On the Malyan M200, this will be Serial1. On a RAMPS board,
|
||||
// it might not be.
|
||||
#define LCD_SERIAL Serial1
|
||||
@@ -72,7 +86,7 @@ int inbound_count;
|
||||
// Everything written needs the high bit set.
|
||||
void write_to_lcd_P(const char * const message) {
|
||||
char encoded_message[MAX_CURLY_COMMAND];
|
||||
uint8_t message_length = min(strlen_P(message), sizeof(encoded_message));
|
||||
uint8_t message_length = MIN(strlen_P(message), sizeof(encoded_message));
|
||||
|
||||
for (uint8_t i = 0; i < message_length; i++)
|
||||
encoded_message[i] = pgm_read_byte(&message[i]) | 0x80;
|
||||
@@ -82,7 +96,7 @@ void write_to_lcd_P(const char * const message) {
|
||||
|
||||
void write_to_lcd(const char * const message) {
|
||||
char encoded_message[MAX_CURLY_COMMAND];
|
||||
const uint8_t message_length = min(strlen(message), sizeof(encoded_message));
|
||||
const uint8_t message_length = MIN(strlen(message), sizeof(encoded_message));
|
||||
|
||||
for (uint8_t i = 0; i < message_length; i++)
|
||||
encoded_message[i] = message[i] | 0x80;
|
||||
@@ -132,8 +146,6 @@ void process_lcd_c_command(const char* command) {
|
||||
void process_lcd_eb_command(const char* command) {
|
||||
char elapsed_buffer[10];
|
||||
duration_t elapsed;
|
||||
bool has_days;
|
||||
uint8_t len;
|
||||
switch (command[0]) {
|
||||
case '0': {
|
||||
elapsed = print_job_timer.duration();
|
||||
@@ -144,9 +156,17 @@ void process_lcd_eb_command(const char* command) {
|
||||
PSTR("{T0:%03.0f/%03i}{T1:000/000}{TP:%03.0f/%03i}{TQ:%03i}{TT:%s}"),
|
||||
thermalManager.degHotend(0),
|
||||
thermalManager.degTargetHotend(0),
|
||||
thermalManager.degBed(),
|
||||
thermalManager.degTargetBed(),
|
||||
card.percentDone(),
|
||||
#if HAS_HEATED_BED
|
||||
thermalManager.degBed(),
|
||||
thermalManager.degTargetBed(),
|
||||
#else
|
||||
0, 0,
|
||||
#endif
|
||||
#if ENABLED(SDSUPPORT)
|
||||
card.percentDone(),
|
||||
#else
|
||||
0,
|
||||
#endif
|
||||
elapsed_buffer);
|
||||
write_to_lcd(message_buffer);
|
||||
} break;
|
||||
@@ -223,51 +243,55 @@ void process_lcd_p_command(const char* command) {
|
||||
|
||||
switch (command[0]) {
|
||||
case 'X':
|
||||
// cancel print
|
||||
write_to_lcd_P(PSTR("{SYS:CANCELING}"));
|
||||
card.stopSDPrint(
|
||||
#if SD_RESORT
|
||||
true
|
||||
#if ENABLED(SDSUPPORT)
|
||||
// cancel print
|
||||
write_to_lcd_P(PSTR("{SYS:CANCELING}"));
|
||||
card.stopSDPrint(
|
||||
#if SD_RESORT
|
||||
true
|
||||
#endif
|
||||
);
|
||||
clear_command_queue();
|
||||
quickstop_stepper();
|
||||
print_job_timer.stop();
|
||||
thermalManager.disable_all_heaters();
|
||||
#if FAN_COUNT > 0
|
||||
for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0;
|
||||
#endif
|
||||
);
|
||||
clear_command_queue();
|
||||
quickstop_stepper();
|
||||
print_job_timer.stop();
|
||||
thermalManager.disable_all_heaters();
|
||||
#if FAN_COUNT > 0
|
||||
for (uint8_t i = 0; i < FAN_COUNT; i++) fanSpeeds[i] = 0;
|
||||
wait_for_heatup = false;
|
||||
write_to_lcd_P(PSTR("{SYS:STARTED}"));
|
||||
#endif
|
||||
wait_for_heatup = false;
|
||||
write_to_lcd_P(PSTR("{SYS:STARTED}"));
|
||||
break;
|
||||
case 'H':
|
||||
// Home all axis
|
||||
enqueue_and_echo_commands_now_P(PSTR("G28"));
|
||||
break;
|
||||
default: {
|
||||
// Print file 000 - a three digit number indicating which
|
||||
// file to print in the SD card. If it's a directory,
|
||||
// then switch to the directory.
|
||||
#if ENABLED(SDSUPPORT)
|
||||
// Print file 000 - a three digit number indicating which
|
||||
// file to print in the SD card. If it's a directory,
|
||||
// then switch to the directory.
|
||||
|
||||
// Find the name of the file to print.
|
||||
// It's needed to echo the PRINTFILE option.
|
||||
// The {S:L} command should've ensured the SD card was mounted.
|
||||
card.getfilename(atoi(command));
|
||||
// Find the name of the file to print.
|
||||
// It's needed to echo the PRINTFILE option.
|
||||
// The {S:L} command should've ensured the SD card was mounted.
|
||||
card.getfilename(atoi(command));
|
||||
|
||||
// There may be a difference in how V1 and V2 LCDs handle subdirectory
|
||||
// prints. Investigate more. This matches the V1 motion controller actions
|
||||
// but the V2 LCD switches to "print" mode on {SYS:DIR} response.
|
||||
if (card.filenameIsDir) {
|
||||
card.chdir(card.filename);
|
||||
write_to_lcd_P(PSTR("{SYS:DIR}"));
|
||||
}
|
||||
else {
|
||||
char message_buffer[MAX_CURLY_COMMAND];
|
||||
sprintf_P(message_buffer, PSTR("{PRINTFILE:%s}"), card.filename);
|
||||
write_to_lcd(message_buffer);
|
||||
write_to_lcd_P(PSTR("{SYS:BUILD}"));
|
||||
card.openAndPrintFile(card.filename);
|
||||
}
|
||||
// There may be a difference in how V1 and V2 LCDs handle subdirectory
|
||||
// prints. Investigate more. This matches the V1 motion controller actions
|
||||
// but the V2 LCD switches to "print" mode on {SYS:DIR} response.
|
||||
if (card.filenameIsDir) {
|
||||
card.chdir(card.filename);
|
||||
write_to_lcd_P(PSTR("{SYS:DIR}"));
|
||||
}
|
||||
else {
|
||||
char message_buffer[MAX_CURLY_COMMAND];
|
||||
sprintf_P(message_buffer, PSTR("{PRINTFILE:%s}"), card.filename);
|
||||
write_to_lcd(message_buffer);
|
||||
write_to_lcd_P(PSTR("{SYS:BUILD}"));
|
||||
card.openAndPrintFile(card.filename);
|
||||
}
|
||||
#endif
|
||||
} break; // default
|
||||
} // switch
|
||||
}
|
||||
@@ -292,7 +316,11 @@ void process_lcd_s_command(const char* command) {
|
||||
char message_buffer[MAX_CURLY_COMMAND];
|
||||
sprintf_P(message_buffer, PSTR("{T0:%03.0f/%03i}{T1:000/000}{TP:%03.0f/%03i}"),
|
||||
thermalManager.degHotend(0), thermalManager.degTargetHotend(0),
|
||||
thermalManager.degBed(), thermalManager.degTargetBed()
|
||||
#if HAS_HEATED_BED
|
||||
thermalManager.degBed(), thermalManager.degTargetBed()
|
||||
#else
|
||||
0, 0
|
||||
#endif
|
||||
);
|
||||
write_to_lcd(message_buffer);
|
||||
} break;
|
||||
@@ -303,23 +331,25 @@ void process_lcd_s_command(const char* command) {
|
||||
break;
|
||||
|
||||
case 'L': {
|
||||
if (!card.cardOK) card.initsd();
|
||||
#if ENABLED(SDSUPPORT)
|
||||
if (!card.cardOK) card.initsd();
|
||||
|
||||
// A more efficient way to do this would be to
|
||||
// implement a callback in the ls_SerialPrint code, but
|
||||
// that requires changes to the core cardreader class that
|
||||
// would not benefit the majority of users. Since one can't
|
||||
// select a file for printing during a print, there's
|
||||
// little reason not to do it this way.
|
||||
char message_buffer[MAX_CURLY_COMMAND];
|
||||
uint16_t file_count = card.get_num_Files();
|
||||
for (uint16_t i = 0; i < file_count; i++) {
|
||||
card.getfilename(i);
|
||||
sprintf_P(message_buffer, card.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.filename);
|
||||
write_to_lcd(message_buffer);
|
||||
}
|
||||
// A more efficient way to do this would be to
|
||||
// implement a callback in the ls_SerialPrint code, but
|
||||
// that requires changes to the core cardreader class that
|
||||
// would not benefit the majority of users. Since one can't
|
||||
// select a file for printing during a print, there's
|
||||
// little reason not to do it this way.
|
||||
char message_buffer[MAX_CURLY_COMMAND];
|
||||
uint16_t file_count = card.get_num_Files();
|
||||
for (uint16_t i = 0; i < file_count; i++) {
|
||||
card.getfilename(i);
|
||||
sprintf_P(message_buffer, card.filenameIsDir ? PSTR("{DIR:%s}") : PSTR("{FILE:%s}"), card.filename);
|
||||
write_to_lcd(message_buffer);
|
||||
}
|
||||
|
||||
write_to_lcd_P(PSTR("{SYS:OK}"));
|
||||
write_to_lcd_P(PSTR("{SYS:OK}"));
|
||||
#endif
|
||||
} break;
|
||||
|
||||
default:
|
||||
@@ -371,15 +401,15 @@ void process_lcd_command(const char* command) {
|
||||
/**
|
||||
* UC means connected.
|
||||
* UD means disconnected
|
||||
* The stock firmware considers USB initialied as "connected."
|
||||
* The stock firmware considers USB initialized as "connected."
|
||||
*/
|
||||
void update_usb_status(const bool forceUpdate) {
|
||||
static bool last_usb_connected_status = false;
|
||||
// This is mildly different than stock, which
|
||||
// appears to use the usb discovery status.
|
||||
// This is more logical.
|
||||
if (last_usb_connected_status != Serial || forceUpdate) {
|
||||
last_usb_connected_status = Serial;
|
||||
if (last_usb_connected_status != USB_STATUS || forceUpdate) {
|
||||
last_usb_connected_status = USB_STATUS;
|
||||
write_to_lcd_P(last_usb_connected_status ? PSTR("{R:UC}\r\n") : PSTR("{R:UD}\r\n"));
|
||||
}
|
||||
}
|
||||
@@ -390,7 +420,7 @@ void update_usb_status(const bool forceUpdate) {
|
||||
* The optimize attribute fixes a register Compile
|
||||
* error for amtel.
|
||||
*/
|
||||
void lcd_update() _O2 {
|
||||
void _O2 lcd_update() {
|
||||
static char inbound_buffer[MAX_CURLY_COMMAND];
|
||||
|
||||
// First report USB status.
|
||||
@@ -408,15 +438,17 @@ void lcd_update() _O2 {
|
||||
}
|
||||
}
|
||||
|
||||
// If there's a print in progress, we need to emit the status as
|
||||
// {TQ:<PERCENT>}
|
||||
if (card.sdprinting) {
|
||||
// We also need to send: T:-2538.0 E:0
|
||||
// I have no idea what this means.
|
||||
char message_buffer[10];
|
||||
sprintf_P(message_buffer, PSTR("{TQ:%03i}"), card.percentDone());
|
||||
write_to_lcd(message_buffer);
|
||||
}
|
||||
#if ENABLED(SDSUPPORT)
|
||||
// If there's a print in progress, we need to emit the status as
|
||||
// {TQ:<PERCENT>}
|
||||
if (card.sdprinting) {
|
||||
// We also need to send: T:-2538.0 E:0
|
||||
// I have no idea what this means.
|
||||
char message_buffer[10];
|
||||
sprintf_P(message_buffer, PSTR("{TQ:%03i}"), card.percentDone());
|
||||
write_to_lcd(message_buffer);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -78,7 +78,7 @@
|
||||
do_blocking_move_to(start.x, start.y, start.z);
|
||||
|
||||
const uint8_t zigs = objects << 1;
|
||||
const bool horiz = FABS(diffx) >= FABS(diffy); // Do a horizontal wipe?
|
||||
const bool horiz = ABS(diffx) >= ABS(diffy); // Do a horizontal wipe?
|
||||
const float P = (horiz ? diffx : diffy) / zigs; // Period of each zig / zag
|
||||
const point_t *side;
|
||||
for (uint8_t j = 0; j < strokes; j++) {
|
||||
@@ -171,11 +171,11 @@
|
||||
break;
|
||||
|
||||
case 2: // Raise by Z-park height
|
||||
do_blocking_move_to_z(min(current_position[Z_AXIS] + park.z, Z_MAX_POS), fr_z);
|
||||
do_blocking_move_to_z(MIN(current_position[Z_AXIS] + park.z, Z_MAX_POS), fr_z);
|
||||
break;
|
||||
|
||||
default: // Raise to at least the Z-park height
|
||||
do_blocking_move_to_z(max(park.z, current_position[Z_AXIS]), fr_z);
|
||||
do_blocking_move_to_z(MAX(park.z, current_position[Z_AXIS]), fr_z);
|
||||
}
|
||||
|
||||
do_blocking_move_to_xy(park.x, park.y, fr_xy);
|
||||
|
||||
+2
-2
@@ -153,7 +153,7 @@ public:
|
||||
// Code is found in the string. If not found, value_ptr is unchanged.
|
||||
// This allows "if (seen('A')||seen('B'))" to use the last-found value.
|
||||
static bool seen(const char c) {
|
||||
const char *p = strchr(command_args, c);
|
||||
char *p = strchr(command_args, c);
|
||||
const bool b = !!p;
|
||||
if (b) value_ptr = valid_float(&p[1]) ? &p[1] : (char*)NULL;
|
||||
return b;
|
||||
@@ -317,7 +317,7 @@ public:
|
||||
|
||||
// Provide simple value accessors with default option
|
||||
FORCE_INLINE static float floatval(const char c, const float dval=0.0) { return seenval(c) ? value_float() : dval; }
|
||||
FORCE_INLINE static bool boolval(const char c) { return seenval(c) ? value_bool() : seen(c); }
|
||||
FORCE_INLINE static bool boolval(const char c, const bool dval=false) { return seenval(c) ? value_bool() : (seen(c) ? true : dval); }
|
||||
FORCE_INLINE static uint8_t byteval(const char c, const uint8_t dval=0) { return seenval(c) ? value_byte() : dval; }
|
||||
FORCE_INLINE static int16_t intval(const char c, const int16_t dval=0) { return seenval(c) ? value_int() : dval; }
|
||||
FORCE_INLINE static uint16_t ushortval(const char c, const uint16_t dval=0) { return seenval(c) ? value_ushort() : dval; }
|
||||
|
||||
+7
-8
@@ -248,22 +248,21 @@
|
||||
//
|
||||
|
||||
#elif MB(TEENSYLU)
|
||||
#include "pins_TEENSYLU.h" // AT90USB1286, AT90USB1286P env:teensy20
|
||||
#include "pins_TEENSYLU.h" // AT90USB1286, AT90USB1286P env:at90USB1286_CDC
|
||||
#elif MB(PRINTRBOARD)
|
||||
#include "pins_PRINTRBOARD.h" // AT90USB1286 env:teensy20
|
||||
#include "pins_PRINTRBOARD.h" // AT90USB1286 env:at90USB1286_DFU
|
||||
#elif MB(PRINTRBOARD_REVF)
|
||||
#include "pins_PRINTRBOARD_REVF.h" // AT90USB1286 env:teensy20
|
||||
#include "pins_PRINTRBOARD_REVF.h" // AT90USB1286 env:at90USB1286_DFU
|
||||
#elif MB(BRAINWAVE)
|
||||
#include "pins_BRAINWAVE.h" // AT90USB646 env:teensy20
|
||||
#include "pins_BRAINWAVE.h" // AT90USB646 env:at90USB1286_CDC
|
||||
#elif MB(BRAINWAVE_PRO)
|
||||
#include "pins_BRAINWAVE_PRO.h" // AT90USB1286 env:teensy20
|
||||
#include "pins_BRAINWAVE_PRO.h" // AT90USB1286 env:at90USB1286_CDC
|
||||
#elif MB(SAV_MKI)
|
||||
#include "pins_SAV_MKI.h" // AT90USB1286 env:teensy20
|
||||
#include "pins_SAV_MKI.h" // AT90USB1286 env:at90USB1286_CDC
|
||||
#elif MB(TEENSY2)
|
||||
#include "pins_TEENSY2.h" // AT90USB1286 env:teensy20
|
||||
#elif MB(5DPRINT)
|
||||
#include "pins_5DPRINT.h" // AT90USB1286 env:teensy20
|
||||
|
||||
#include "pins_5DPRINT.h" // AT90USB1286 ?env:at90USB1286_DFU
|
||||
|
||||
#else
|
||||
#error "Unknown MOTHERBOARD value set in Configuration.h"
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
*/
|
||||
|
||||
#ifndef __AVR_ATmega1284P__
|
||||
#error "Oops! Make sure you have 'Anet V1.0', 'Anet V1.0 (Optiboot)' or 'Sanguino' selected from the 'Tools -> Boards' menu."
|
||||
#error "Oops! Make sure you have 'Anet V1.0', 'Anet V1.0 (Optiboot)' or 'Sanguino' selected in the 'Tools -> Boards' menu and ATmega1284P selected in 'Tools -> Processor' menu."
|
||||
#endif
|
||||
|
||||
#ifndef BOARD_NAME
|
||||
@@ -153,7 +153,7 @@
|
||||
#if ENABLED(ULTRA_LCD) && ENABLED(NEWPANEL)
|
||||
#define LCD_SDSS 28
|
||||
#if ENABLED(ADC_KEYPAD)
|
||||
#define SERVO0_PIN 27 // free for BLTouch/3D-Touch
|
||||
#define SERVO0_PIN 27 // free for BLTouch/3D-Touch
|
||||
#define LCD_PINS_RS 28
|
||||
#define LCD_PINS_ENABLE 29
|
||||
#define LCD_PINS_D4 10
|
||||
@@ -168,7 +168,7 @@
|
||||
// Pin definitions for the Anet A6 Full Graphics display and the RepRapDiscount Full Graphics
|
||||
// display using an adapter board // https://go.aisler.net/benlye/anet-lcd-adapter/pcb
|
||||
// See below for alternative pin definitions for use with https://www.thingiverse.com/thing:2103748
|
||||
#define SERVO0_PIN 29 // free for BLTouch/3D-Touch
|
||||
#define SERVO0_PIN 29 // free for BLTouch/3D-Touch
|
||||
#define BEEPER_PIN 17
|
||||
#define LCD_PINS_RS 27
|
||||
#define LCD_PINS_ENABLE 28
|
||||
@@ -177,13 +177,13 @@
|
||||
#define BTN_EN2 10
|
||||
#define BTN_ENC 16
|
||||
#ifndef ST7920_DELAY_1
|
||||
#define ST7920_DELAY_1 DELAY_0_NOP
|
||||
#define ST7920_DELAY_1 DELAY_NS(0)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_2
|
||||
#define ST7920_DELAY_2 DELAY_1_NOP
|
||||
#define ST7920_DELAY_2 DELAY_NS(63)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_3
|
||||
#define ST7920_DELAY_3 DELAY_2_NOP
|
||||
#define ST7920_DELAY_3 DELAY_NS(125)
|
||||
#endif
|
||||
#define STD_ENCODER_PULSES_PER_STEP 4
|
||||
#define STD_ENCODER_STEPS_PER_MENU_ITEM 1
|
||||
@@ -201,7 +201,7 @@
|
||||
* published by oderwat on Thingiverse at https://www.thingiverse.com/thing:2103748.
|
||||
*
|
||||
* Using that adapter requires changing the pin definition as follows:
|
||||
* #define SERVO0_PIN 27 // free for BLTouch/3D-Touch
|
||||
* #define SERVO0_PIN 27 // free for BLTouch/3D-Touch
|
||||
* #define BEEPER_PIN 28
|
||||
* #define LCD_PINS_RS 30
|
||||
* #define LCD_PINS_ENABLE 29
|
||||
|
||||
@@ -55,13 +55,13 @@
|
||||
|
||||
// Alter timing for graphical display
|
||||
#ifndef ST7920_DELAY_1
|
||||
#define ST7920_DELAY_1 DELAY_2_NOP
|
||||
#define ST7920_DELAY_1 DELAY_NS(125)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_2
|
||||
#define ST7920_DELAY_2 DELAY_2_NOP
|
||||
#define ST7920_DELAY_2 DELAY_NS(125)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_3
|
||||
#define ST7920_DELAY_3 DELAY_2_NOP
|
||||
#define ST7920_DELAY_3 DELAY_NS(125)
|
||||
#endif
|
||||
|
||||
#if ENABLED(MINIPANEL)
|
||||
|
||||
@@ -44,11 +44,11 @@
|
||||
|
||||
// Alter timing for graphical display
|
||||
#ifndef ST7920_DELAY_1
|
||||
#define ST7920_DELAY_1 DELAY_2_NOP
|
||||
#define ST7920_DELAY_1 DELAY_NS(125)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_2
|
||||
#define ST7920_DELAY_2 DELAY_2_NOP
|
||||
#define ST7920_DELAY_2 DELAY_NS(125)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_3
|
||||
#define ST7920_DELAY_3 DELAY_2_NOP
|
||||
#define ST7920_DELAY_3 DELAY_NS(125)
|
||||
#endif
|
||||
|
||||
@@ -51,11 +51,11 @@
|
||||
#define BTN_ENC 26
|
||||
|
||||
#ifndef ST7920_DELAY_1
|
||||
#define ST7920_DELAY_1 DELAY_0_NOP
|
||||
#define ST7920_DELAY_1 DELAY_NS(0)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_2
|
||||
#define ST7920_DELAY_2 DELAY_2_NOP
|
||||
#define ST7920_DELAY_2 DELAY_NS(125)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_3
|
||||
#define ST7920_DELAY_3 DELAY_0_NOP
|
||||
#define ST7920_DELAY_3 DELAY_NS(0)
|
||||
#endif
|
||||
|
||||
@@ -74,11 +74,7 @@
|
||||
// Limit Switches
|
||||
//
|
||||
#define X_STOP_PIN 47 // E3
|
||||
#if ENABLED(SDSUPPORT)
|
||||
#define Y_STOP_PIN 37 // E5 - Move Ystop to Estop socket
|
||||
#else
|
||||
#define Y_STOP_PIN 20 // B0 SS - Ystop in Ystop socket
|
||||
#endif
|
||||
#define Y_STOP_PIN 20 // B0 SS
|
||||
#define Z_STOP_PIN 36 // E4
|
||||
|
||||
//
|
||||
@@ -120,7 +116,7 @@
|
||||
//
|
||||
// Misc. Functions
|
||||
//
|
||||
#define SDSS 20 // B0 SS
|
||||
#define SDSS 26 // B6 SDCS
|
||||
#define FILWIDTH_PIN 2 // Analog Input
|
||||
|
||||
//
|
||||
@@ -146,16 +142,18 @@
|
||||
#define BTN_EN2 3 // D3 RX1 JP2-7
|
||||
#define BTN_ENC 45 // F7 TDI JP2-12
|
||||
|
||||
#undef SDSS
|
||||
#define SDSS 43 // F5 TMS JP2-8
|
||||
|
||||
#define STAT_LED_RED_PIN 12 // C2 JP11-14
|
||||
#define STAT_LED_BLUE_PIN 10 // C0 JP11-12
|
||||
#define STAT_LED_RED_PIN 12 // C2 JP11-14
|
||||
#define STAT_LED_BLUE_PIN 10 // C0 JP11-12
|
||||
|
||||
#elif ENABLED(LCD_I2C_PANELOLU2)
|
||||
|
||||
#define BTN_EN1 3 // D3 RX1 JP2-7
|
||||
#define BTN_EN2 2 // D2 TX1 JP2-5
|
||||
#define BTN_ENC 41 // F3 JP2-4
|
||||
#undef SDSS
|
||||
#define SDSS 38 // F0 B-THERM connector - use SD card on Panelolu2
|
||||
|
||||
#else
|
||||
|
||||
@@ -244,13 +244,13 @@
|
||||
|
||||
// increase delays
|
||||
#ifndef ST7920_DELAY_1
|
||||
#define ST7920_DELAY_1 DELAY_5_NOP
|
||||
#define ST7920_DELAY_1 DELAY_NS(313)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_2
|
||||
#define ST7920_DELAY_2 DELAY_5_NOP
|
||||
#define ST7920_DELAY_2 DELAY_NS(313)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_3
|
||||
#define ST7920_DELAY_3 DELAY_5_NOP
|
||||
#define ST7920_DELAY_3 DELAY_NS(313)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
@@ -239,13 +239,13 @@
|
||||
#define BTN_EN2 30
|
||||
|
||||
#ifndef ST7920_DELAY_1
|
||||
#define ST7920_DELAY_1 DELAY_0_NOP
|
||||
#define ST7920_DELAY_1 DELAY_NS(0)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_2
|
||||
#define ST7920_DELAY_2 DELAY_3_NOP
|
||||
#define ST7920_DELAY_2 DELAY_NS(188)
|
||||
#endif
|
||||
#ifndef ST7920_DELAY_3
|
||||
#define ST7920_DELAY_3 DELAY_0_NOP
|
||||
#define ST7920_DELAY_3 DELAY_NS(0)
|
||||
#endif
|
||||
|
||||
#elif ENABLED(ZONESTAR_LCD) // For the Tronxy Melzi boards
|
||||
|
||||
+644
-374
File diff suppressed because it is too large
Load Diff
+192
-90
@@ -49,7 +49,7 @@ enum BlockFlagBit : char {
|
||||
// from a safe speed (in consideration of jerking from zero speed).
|
||||
BLOCK_BIT_NOMINAL_LENGTH,
|
||||
|
||||
// The block is busy
|
||||
// The block is busy, being interpreted by the stepper ISR
|
||||
BLOCK_BIT_BUSY,
|
||||
|
||||
// The block is segment 2+ of a longer move
|
||||
@@ -80,24 +80,35 @@ typedef struct {
|
||||
|
||||
uint8_t flag; // Block flags (See BlockFlag enum above)
|
||||
|
||||
unsigned char active_extruder; // The extruder to move (if E move)
|
||||
// Fields used by the motion planner to manage acceleration
|
||||
float nominal_speed_sqr, // The nominal speed for this block in (mm/sec)^2
|
||||
entry_speed_sqr, // Entry speed at previous-current junction in (mm/sec)^2
|
||||
max_entry_speed_sqr, // Maximum allowable junction entry speed in (mm/sec)^2
|
||||
millimeters, // The total travel of this block in mm
|
||||
acceleration; // acceleration mm/sec^2
|
||||
|
||||
// Fields used by the Bresenham algorithm for tracing the line
|
||||
int32_t steps[NUM_AXIS]; // Step count along each axis
|
||||
union {
|
||||
// Data used by all move blocks
|
||||
struct {
|
||||
// Fields used by the Bresenham algorithm for tracing the line
|
||||
uint32_t steps[NUM_AXIS]; // Step count along each axis
|
||||
};
|
||||
// Data used by all sync blocks
|
||||
struct {
|
||||
int32_t position[NUM_AXIS]; // New position to force when this sync block is executed
|
||||
};
|
||||
};
|
||||
uint32_t step_event_count; // The number of step events required to complete this block
|
||||
|
||||
uint8_t active_extruder; // The extruder to move (if E move)
|
||||
|
||||
#if ENABLED(MIXING_EXTRUDER)
|
||||
uint32_t mix_event_count[MIXING_STEPPERS]; // Scaled step_event_count for the mixing steppers
|
||||
#endif
|
||||
|
||||
// Settings for the trapezoid generator
|
||||
int32_t accelerate_until, // The index of the step event on which to stop acceleration
|
||||
decelerate_after; // The index of the step event on which to start decelerating
|
||||
|
||||
uint32_t nominal_rate, // The nominal step rate for this block in step_events/sec
|
||||
initial_rate, // The jerk-adjusted step rate at start of block
|
||||
final_rate, // The minimal rate at exit
|
||||
acceleration_steps_per_s2; // acceleration steps/sec^2
|
||||
uint32_t accelerate_until, // The index of the step event on which to stop acceleration
|
||||
decelerate_after; // The index of the step event on which to start decelerating
|
||||
|
||||
#if ENABLED(BEZIER_JERK_CONTROL)
|
||||
uint32_t cruise_rate; // The actual cruise rate to use, between end of the acceleration phase and start of deceleration phase
|
||||
@@ -106,7 +117,7 @@ typedef struct {
|
||||
uint32_t acceleration_time_inverse, // Inverse of acceleration and deceleration periods, expressed as integer. Scale depends on CPU being used
|
||||
deceleration_time_inverse;
|
||||
#else
|
||||
int32_t acceleration_rate; // The acceleration rate used for acceleration calculation
|
||||
uint32_t acceleration_rate; // The acceleration rate used for acceleration calculation
|
||||
#endif
|
||||
|
||||
uint8_t direction_bits; // The direction bit set for this block (refers to *_DIRECTION_BIT in config.h)
|
||||
@@ -120,12 +131,10 @@ typedef struct {
|
||||
float e_D_ratio;
|
||||
#endif
|
||||
|
||||
// Fields used by the motion planner to manage acceleration
|
||||
float nominal_speed, // The nominal speed for this block in mm/sec
|
||||
entry_speed, // Entry speed at previous-current junction in mm/sec
|
||||
max_entry_speed, // Maximum allowable junction entry speed in mm/sec
|
||||
millimeters, // The total travel of this block in mm
|
||||
acceleration; // acceleration mm/sec^2
|
||||
uint32_t nominal_rate, // The nominal step rate for this block in step_events/sec
|
||||
initial_rate, // The jerk-adjusted step rate at start of block
|
||||
final_rate, // The minimal rate at exit
|
||||
acceleration_steps_per_s2; // acceleration steps/sec^2
|
||||
|
||||
#if FAN_COUNT > 0
|
||||
uint16_t fan_speed[FAN_COUNT];
|
||||
@@ -162,6 +171,10 @@ class Planner {
|
||||
static block_t block_buffer[BLOCK_BUFFER_SIZE];
|
||||
static volatile uint8_t block_buffer_head, // Index of the next block to be pushed
|
||||
block_buffer_tail; // Index of the busy block, if any
|
||||
static uint16_t cleaning_buffer_counter; // A counter to disable queuing of blocks
|
||||
static uint8_t delay_before_delivering, // This counter delays delivery of blocks when queue becomes empty to allow the opportunity of merging blocks
|
||||
block_buffer_planned; // Index of the optimally planned block
|
||||
|
||||
|
||||
#if ENABLED(DISTINCT_E_FACTORS)
|
||||
static uint8_t last_extruder; // Respond to extruder change
|
||||
@@ -229,6 +242,10 @@ class Planner {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
|
||||
static bool abort_on_endstop_hit;
|
||||
#endif
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
@@ -243,9 +260,9 @@ class Planner {
|
||||
static float previous_speed[NUM_AXIS];
|
||||
|
||||
/**
|
||||
* Nominal speed of previous path line segment
|
||||
* Nominal speed of previous path line segment (mm/s)^2
|
||||
*/
|
||||
static float previous_nominal_speed;
|
||||
static float previous_nominal_speed_sqr;
|
||||
|
||||
/**
|
||||
* Limit where 64bit math is necessary for acceleration calculation
|
||||
@@ -304,15 +321,6 @@ class Planner {
|
||||
// Manage fans, paste pressure, etc.
|
||||
static void check_axes_activity();
|
||||
|
||||
/**
|
||||
* Number of moves currently in the planner
|
||||
*/
|
||||
FORCE_INLINE static uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail + BLOCK_BUFFER_SIZE); }
|
||||
|
||||
FORCE_INLINE static void clear_block_buffer() { block_buffer_head = block_buffer_tail = 0; }
|
||||
|
||||
FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); }
|
||||
|
||||
// Update multipliers based on new diameter measurements
|
||||
static void calculate_volumetric_multipliers();
|
||||
|
||||
@@ -420,16 +428,32 @@ class Planner {
|
||||
#define ARG_Z const float &rz
|
||||
#endif
|
||||
|
||||
// Number of moves currently in the planner
|
||||
FORCE_INLINE static uint8_t movesplanned() { return BLOCK_MOD(block_buffer_head - block_buffer_tail); }
|
||||
|
||||
// Remove all blocks from the buffer
|
||||
FORCE_INLINE static void clear_block_buffer() { block_buffer_head = block_buffer_tail = 0; }
|
||||
|
||||
// Check if movement queue is full
|
||||
FORCE_INLINE static bool is_full() { return block_buffer_tail == next_block_index(block_buffer_head); }
|
||||
|
||||
// Get count of movement slots free
|
||||
FORCE_INLINE static uint8_t moves_free() { return BLOCK_BUFFER_SIZE - 1 - movesplanned(); }
|
||||
|
||||
/**
|
||||
* Planner::get_next_free_block
|
||||
*
|
||||
* - Get the next head index (passed by reference)
|
||||
* - Wait for a space to open up in the planner
|
||||
* - Return the head block
|
||||
* - Get the next head indices (passed by reference)
|
||||
* - Wait for the number of spaces to open up in the planner
|
||||
* - Return the first head block
|
||||
*/
|
||||
FORCE_INLINE static block_t* get_next_free_block(uint8_t &next_buffer_head) {
|
||||
FORCE_INLINE static block_t* get_next_free_block(uint8_t &next_buffer_head, const uint8_t count=1) {
|
||||
|
||||
// Wait until there are enough slots free
|
||||
while (moves_free() < count) { idle(); }
|
||||
|
||||
// Return the first available block
|
||||
next_buffer_head = next_block_index(block_buffer_head);
|
||||
while (block_buffer_tail == next_buffer_head) idle(); // while (is_full)
|
||||
return &block_buffer[block_buffer_head];
|
||||
}
|
||||
|
||||
@@ -442,8 +466,30 @@ class Planner {
|
||||
* fr_mm_s - (target) speed of the move
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
*
|
||||
* Returns true if movement was buffered, false otherwise
|
||||
*/
|
||||
static void _buffer_steps(const int32_t (&target)[XYZE]
|
||||
static bool _buffer_steps(const int32_t (&target)[XYZE]
|
||||
#if HAS_POSITION_FLOAT
|
||||
, const float (&target_float)[XYZE]
|
||||
#endif
|
||||
, float fr_mm_s, const uint8_t extruder, const float &millimeters=0.0
|
||||
);
|
||||
|
||||
/**
|
||||
* Planner::_populate_block
|
||||
*
|
||||
* Fills a new linear movement in the block (in terms of steps).
|
||||
*
|
||||
* target - target position in steps units
|
||||
* fr_mm_s - (target) speed of the move
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
*
|
||||
* Returns true is movement is acceptable, false otherwise
|
||||
*/
|
||||
static bool _populate_block(block_t * const block, bool split_move,
|
||||
const int32_t (&target)[XYZE]
|
||||
#if HAS_POSITION_FLOAT
|
||||
, const float (&target_float)[XYZE]
|
||||
#endif
|
||||
@@ -468,7 +514,7 @@ class Planner {
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
*/
|
||||
static void buffer_segment(const float &a, const float &b, const float &c, const float &e, const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0);
|
||||
static bool buffer_segment(const float &a, const float &b, const float &c, const float &e, const float &fr_mm_s, const uint8_t extruder, const float &millimeters=0.0);
|
||||
|
||||
static void _set_position_mm(const float &a, const float &b, const float &c, const float &e);
|
||||
|
||||
@@ -485,11 +531,11 @@ class Planner {
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
*/
|
||||
FORCE_INLINE static void buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
|
||||
FORCE_INLINE static bool buffer_line(ARG_X, ARG_Y, ARG_Z, const float &e, const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
|
||||
#if PLANNER_LEVELING && IS_CARTESIAN
|
||||
apply_leveling(rx, ry, rz);
|
||||
#endif
|
||||
buffer_segment(rx, ry, rz, e, fr_mm_s, extruder, millimeters);
|
||||
return buffer_segment(rx, ry, rz, e, fr_mm_s, extruder, millimeters);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -502,7 +548,7 @@ class Planner {
|
||||
* extruder - target extruder
|
||||
* millimeters - the length of the movement, if known
|
||||
*/
|
||||
FORCE_INLINE static void buffer_line_kinematic(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
|
||||
FORCE_INLINE static bool buffer_line_kinematic(const float (&cart)[XYZE], const float &fr_mm_s, const uint8_t extruder, const float millimeters = 0.0) {
|
||||
#if PLANNER_LEVELING
|
||||
float raw[XYZ] = { cart[X_AXIS], cart[Y_AXIS], cart[Z_AXIS] };
|
||||
apply_leveling(raw);
|
||||
@@ -511,9 +557,9 @@ class Planner {
|
||||
#endif
|
||||
#if IS_KINEMATIC
|
||||
inverse_kinematics(raw);
|
||||
buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], cart[E_AXIS], fr_mm_s, extruder, millimeters);
|
||||
return buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], cart[E_AXIS], fr_mm_s, extruder, millimeters);
|
||||
#else
|
||||
buffer_segment(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], cart[E_AXIS], fr_mm_s, extruder, millimeters);
|
||||
return buffer_segment(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS], cart[E_AXIS], fr_mm_s, extruder, millimeters);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -538,72 +584,122 @@ class Planner {
|
||||
FORCE_INLINE static void set_e_position_mm(const float &e) { set_position_mm(E_AXIS, e); }
|
||||
|
||||
/**
|
||||
* Sync from the stepper positions. (e.g., after an interrupted move)
|
||||
* Get an axis position according to stepper position(s)
|
||||
* For CORE machines apply translation from ABC to XYZ.
|
||||
*/
|
||||
static void sync_from_steppers();
|
||||
static float get_axis_position_mm(const AxisEnum axis);
|
||||
|
||||
// SCARA AB axes are in degrees, not mm
|
||||
#if IS_SCARA
|
||||
FORCE_INLINE static float get_axis_position_degrees(const AxisEnum axis) { return get_axis_position_mm(axis); }
|
||||
#endif
|
||||
|
||||
// Called to force a quick stop of the machine (for example, when an emergency
|
||||
// stop is required, or when endstops are hit)
|
||||
static void quick_stop();
|
||||
|
||||
// Called when an endstop is triggered. Causes the machine to stop inmediately
|
||||
static void endstop_triggered(const AxisEnum axis);
|
||||
|
||||
// Triggered position of an axis in mm (not core-savvy)
|
||||
static float triggered_position_mm(const AxisEnum axis);
|
||||
|
||||
// Block until all buffered steps are executed / cleaned
|
||||
static void synchronize();
|
||||
|
||||
// Wait for moves to finish and disable all steppers
|
||||
static void finish_and_disable();
|
||||
|
||||
// Periodic tick to handle cleaning timeouts
|
||||
// Called from the Temperature ISR at ~1kHz
|
||||
static void tick() {
|
||||
if (cleaning_buffer_counter) {
|
||||
--cleaning_buffer_counter;
|
||||
#if ENABLED(SD_FINISHED_STEPPERRELEASE) && defined(SD_FINISHED_RELEASECOMMAND)
|
||||
if (!cleaning_buffer_counter) enqueue_and_echo_commands_P(PSTR(SD_FINISHED_RELEASECOMMAND));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the buffer have any blocks queued?
|
||||
*/
|
||||
FORCE_INLINE static bool has_blocks_queued() { return (block_buffer_head != block_buffer_tail); }
|
||||
|
||||
/**
|
||||
* "Discard" the block and "release" the memory.
|
||||
* Called when the current block is no longer needed.
|
||||
*/
|
||||
FORCE_INLINE static void discard_current_block() {
|
||||
if (has_blocks_queued())
|
||||
block_buffer_tail = BLOCK_MOD(block_buffer_tail + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* "Discard" the next block if it's continued.
|
||||
* Called after an interrupted move to throw away the rest of the move.
|
||||
*/
|
||||
FORCE_INLINE static bool discard_continued_block() {
|
||||
const bool discard = has_blocks_queued() && TEST(block_buffer[block_buffer_tail].flag, BLOCK_BIT_CONTINUED);
|
||||
if (discard) discard_current_block();
|
||||
return discard;
|
||||
}
|
||||
|
||||
/**
|
||||
* The current block. NULL if the buffer is empty.
|
||||
* This also marks the block as busy.
|
||||
* WARNING: Called from Stepper ISR context!
|
||||
*/
|
||||
static block_t* get_current_block() {
|
||||
if (has_blocks_queued()) {
|
||||
|
||||
// Get the number of moves in the planner queue so far
|
||||
uint8_t nr_moves = movesplanned();
|
||||
|
||||
// If there are any moves queued ...
|
||||
if (nr_moves) {
|
||||
|
||||
// If there is still delay of delivery of blocks running, decrement it
|
||||
if (delay_before_delivering) {
|
||||
--delay_before_delivering;
|
||||
// If the number of movements queued is less than 3, and there is still time
|
||||
// to wait, do not deliver anything
|
||||
if (nr_moves < 3 && delay_before_delivering) return NULL;
|
||||
delay_before_delivering = 0;
|
||||
}
|
||||
|
||||
// If we are here, there is no excuse to deliver the block
|
||||
block_t * const block = &block_buffer[block_buffer_tail];
|
||||
|
||||
// If the block has no trapezoid calculated, it's unsafe to execute.
|
||||
if (movesplanned() > 1) {
|
||||
const block_t * const next = &block_buffer[next_block_index(block_buffer_tail)];
|
||||
if (TEST(block->flag, BLOCK_BIT_RECALCULATE) || TEST(next->flag, BLOCK_BIT_RECALCULATE))
|
||||
return NULL;
|
||||
}
|
||||
else if (TEST(block->flag, BLOCK_BIT_RECALCULATE))
|
||||
return NULL;
|
||||
// No trapezoid calculated? Don't execute yet.
|
||||
if (TEST(block->flag, BLOCK_BIT_RECALCULATE)) return NULL;
|
||||
|
||||
#if ENABLED(ULTRA_LCD)
|
||||
block_buffer_runtime_us -= block->segment_time_us; // We can't be sure how long an active block will take, so don't count it.
|
||||
#endif
|
||||
|
||||
// Mark the block as busy, so the planner does not attempt to replan it
|
||||
SBI(block->flag, BLOCK_BIT_BUSY);
|
||||
return block;
|
||||
}
|
||||
else {
|
||||
#if ENABLED(ULTRA_LCD)
|
||||
clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero.
|
||||
#endif
|
||||
return NULL;
|
||||
|
||||
// The queue became empty
|
||||
#if ENABLED(ULTRA_LCD)
|
||||
clear_block_buffer_runtime(); // paranoia. Buffer is empty now - so reset accumulated time to zero.
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* "Discard" the block and "release" the memory.
|
||||
* Called when the current block is no longer needed.
|
||||
* NB: There MUST be a current block to call this function!!
|
||||
*/
|
||||
FORCE_INLINE static void discard_current_block() {
|
||||
if (has_blocks_queued()) { // Discard non-empty buffer.
|
||||
uint8_t block_index = next_block_index( block_buffer_tail );
|
||||
|
||||
// Push block_buffer_planned pointer, if encountered.
|
||||
if (!has_blocks_queued()) block_buffer_planned = block_index;
|
||||
|
||||
block_buffer_tail = block_index;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLED(ULTRA_LCD)
|
||||
|
||||
static uint16_t block_buffer_runtime() {
|
||||
CRITICAL_SECTION_START
|
||||
millis_t bbru = block_buffer_runtime_us;
|
||||
CRITICAL_SECTION_END
|
||||
// Protect the access to the variable. Only required for AVR, as
|
||||
// any 32bit CPU offers atomic access to 32bit variables
|
||||
bool was_enabled = STEPPER_ISR_ENABLED();
|
||||
if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
millis_t bbru = block_buffer_runtime_us;
|
||||
|
||||
// Reenable Stepper ISR
|
||||
if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
// To translate µs to ms a division by 1000 would be required.
|
||||
// We introduce 2.4% error here by dividing by 1024.
|
||||
// Doesn't matter because block_buffer_runtime_us is already too small an estimation.
|
||||
@@ -614,9 +710,15 @@ class Planner {
|
||||
}
|
||||
|
||||
static void clear_block_buffer_runtime() {
|
||||
CRITICAL_SECTION_START
|
||||
block_buffer_runtime_us = 0;
|
||||
CRITICAL_SECTION_END
|
||||
// Protect the access to the variable. Only required for AVR, as
|
||||
// any 32bit CPU offers atomic access to 32bit variables
|
||||
bool was_enabled = STEPPER_ISR_ENABLED();
|
||||
if (was_enabled) DISABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
|
||||
block_buffer_runtime_us = 0;
|
||||
|
||||
// Reenable Stepper ISR
|
||||
if (was_enabled) ENABLE_STEPPER_DRIVER_INTERRUPT();
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -633,8 +735,8 @@ class Planner {
|
||||
/**
|
||||
* Get the index of the next / previous block in the ring buffer
|
||||
*/
|
||||
static constexpr int8_t next_block_index(const int8_t block_index) { return BLOCK_MOD(block_index + 1); }
|
||||
static constexpr int8_t prev_block_index(const int8_t block_index) { return BLOCK_MOD(block_index - 1); }
|
||||
static constexpr uint8_t next_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index + 1); }
|
||||
static constexpr uint8_t prev_block_index(const uint8_t block_index) { return BLOCK_MOD(block_index - 1); }
|
||||
|
||||
/**
|
||||
* Calculate the distance (not time) it takes to accelerate
|
||||
@@ -659,12 +761,12 @@ class Planner {
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the maximum allowable speed at this point, in order
|
||||
* to reach 'target_velocity' using 'acceleration' within a given
|
||||
* Calculate the maximum allowable speed squared at this point, in order
|
||||
* to reach 'target_velocity_sqr' using 'acceleration' within a given
|
||||
* 'distance'.
|
||||
*/
|
||||
static float max_allowable_speed(const float &accel, const float &target_velocity, const float &distance) {
|
||||
return SQRT(sq(target_velocity) - 2 * accel * distance);
|
||||
static float max_allowable_speed_sqr(const float &accel, const float &target_velocity_sqr, const float &distance) {
|
||||
return target_velocity_sqr - 2 * accel * distance;
|
||||
}
|
||||
|
||||
#if ENABLED(BEZIER_JERK_CONTROL)
|
||||
@@ -679,7 +781,7 @@ class Planner {
|
||||
static void calculate_trapezoid_for_block(block_t* const block, const float &entry_factor, const float &exit_factor);
|
||||
|
||||
static void reverse_pass_kernel(block_t* const current, const block_t * const next);
|
||||
static void forward_pass_kernel(const block_t * const previous, block_t* const current);
|
||||
static void forward_pass_kernel(const block_t * const previous, block_t* const current, uint8_t block_index);
|
||||
|
||||
static void reverse_pass();
|
||||
static void forward_pass();
|
||||
@@ -690,7 +792,7 @@ class Planner {
|
||||
|
||||
};
|
||||
|
||||
#define PLANNER_XY_FEEDRATE() (min(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]))
|
||||
#define PLANNER_XY_FEEDRATE() (MIN(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]))
|
||||
|
||||
extern Planner planner;
|
||||
|
||||
|
||||
@@ -41,8 +41,7 @@
|
||||
#define MAX_STEP 0.1
|
||||
#define SIGMA 0.1
|
||||
|
||||
/* Compute the linear interpolation between to real numbers.
|
||||
*/
|
||||
// Compute the linear interpolation between two real numbers.
|
||||
inline static float interp(float a, float b, float t) { return (1.0 - t) * a + t * b; }
|
||||
|
||||
/**
|
||||
@@ -65,7 +64,7 @@ inline static float eval_bezier(float a, float b, float c, float d, float t) {
|
||||
* We approximate Euclidean distance with the sum of the coordinates
|
||||
* offset (so-called "norm 1"), which is quicker to compute.
|
||||
*/
|
||||
inline static float dist1(float x1, float y1, float x2, float y2) { return FABS(x1 - x2) + FABS(y1 - y2); }
|
||||
inline static float dist1(float x1, float y1, float x2, float y2) { return ABS(x1 - x2) + ABS(y1 - y2); }
|
||||
|
||||
/**
|
||||
* The algorithm for computing the step is loosely based on the one in Kig
|
||||
@@ -188,12 +187,15 @@ void cubic_b_spline(const float position[NUM_AXIS], const float target[NUM_AXIS]
|
||||
bez_target[Z_AXIS] = interp(position[Z_AXIS], target[Z_AXIS], t);
|
||||
bez_target[E_AXIS] = interp(position[E_AXIS], target[E_AXIS], t);
|
||||
clamp_to_software_endstops(bez_target);
|
||||
|
||||
#if HAS_UBL_AND_CURVES
|
||||
float pos[XYZ] = { bez_target[X_AXIS], bez_target[Y_AXIS], bez_target[Z_AXIS] };
|
||||
planner.apply_leveling(pos);
|
||||
planner.buffer_segment(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], bez_target[E_AXIS], fr_mm_s, active_extruder);
|
||||
if (!planner.buffer_segment(pos[X_AXIS], pos[Y_AXIS], pos[Z_AXIS], bez_target[E_AXIS], fr_mm_s, active_extruder))
|
||||
break;
|
||||
#else
|
||||
planner.buffer_line_kinematic(bez_target, fr_mm_s, extruder);
|
||||
if (!planner.buffer_line_kinematic(bez_target, fr_mm_s, extruder))
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,13 +127,15 @@ void do_print_job_recovery() {
|
||||
#endif
|
||||
));
|
||||
|
||||
char str_1[16], str_2[16];
|
||||
|
||||
#if HAS_LEVELING
|
||||
// Restore leveling state before G92 sets Z
|
||||
// This ensures the steppers correspond to the native Z
|
||||
sprintf_P(job_recovery_commands[ind++], PSTR("M420 S%i Z%s"), int(job_recovery_info.leveling), job_recovery_info.fade);
|
||||
dtostrf(job_recovery_info.fade, 1, 1, str_1);
|
||||
sprintf_P(job_recovery_commands[ind++], PSTR("M420 S%i Z%s"), int(job_recovery_info.leveling), str_1);
|
||||
#endif
|
||||
|
||||
char str_1[16], str_2[16];
|
||||
dtostrf(job_recovery_info.current_position[Z_AXIS] + 2, 1, 3, str_1);
|
||||
dtostrf(job_recovery_info.current_position[E_AXIS]
|
||||
#if ENABLED(SAVE_EACH_CMD_MODE)
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ class FilamentRunoutSensor {
|
||||
if ((IS_SD_PRINTING || print_job_timer.isRunning()) && check() && !filament_ran_out) {
|
||||
filament_ran_out = true;
|
||||
enqueue_and_echo_commands_P(PSTR(FILAMENT_RUNOUT_SCRIPT));
|
||||
stepper.synchronize();
|
||||
planner.synchronize();
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
+4
-4
@@ -25,7 +25,10 @@
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
#if defined(__AVR__) && defined(USBCON)
|
||||
#if USE_MARLINSERIAL
|
||||
#include "MarlinSerial.h"
|
||||
#define MYSERIAL0 customizedSerial
|
||||
#else
|
||||
#include <HardwareSerial.h>
|
||||
#if ENABLED(BLUETOOTH)
|
||||
extern HardwareSerial bluetoothSerial;
|
||||
@@ -33,9 +36,6 @@
|
||||
#else
|
||||
#define MYSERIAL0 Serial
|
||||
#endif // BLUETOOTH
|
||||
#else
|
||||
#include "MarlinSerial.h"
|
||||
#define MYSERIAL0 customizedSerial
|
||||
#endif
|
||||
|
||||
extern const char echomagic[] PROGMEM;
|
||||
|
||||
+1
-1
@@ -259,7 +259,7 @@ int8_t Servo::attach(const int pin, const int min, const int max) {
|
||||
if (pin > 0) servo_info[this->servoIndex].Pin.nbr = pin;
|
||||
pinMode(servo_info[this->servoIndex].Pin.nbr, OUTPUT); // set servo pin to output
|
||||
|
||||
// todo min/max check: abs(min - MIN_PULSE_WIDTH) /4 < 128
|
||||
// todo min/max check: ABS(min - MIN_PULSE_WIDTH) /4 < 128
|
||||
this->min = (MIN_PULSE_WIDTH - min) / 4; //resolution of min/max is 4 uS
|
||||
this->max = (MAX_PULSE_WIDTH - max) / 4;
|
||||
|
||||
|
||||
+96
-53
@@ -71,7 +71,7 @@ FORCE_INLINE void _draw_heater_status(const uint8_t x, const int8_t heater, cons
|
||||
);
|
||||
}
|
||||
|
||||
if (PAGE_CONTAINS(21, 28))
|
||||
if (PAGE_CONTAINS(21, 28)) {
|
||||
_draw_centered_temp(0.5 + (
|
||||
#if HAS_HEATED_BED
|
||||
isBed ? thermalManager.degBed() :
|
||||
@@ -80,37 +80,43 @@ FORCE_INLINE void _draw_heater_status(const uint8_t x, const int8_t heater, cons
|
||||
), x, 28
|
||||
);
|
||||
|
||||
if (PAGE_CONTAINS(17, 20)) {
|
||||
const uint8_t h = isBed ? 7 : HEAT_INDICATOR_X,
|
||||
y = isBed ? 18 : 17;
|
||||
if (
|
||||
#if HAS_HEATED_BED
|
||||
isBed ? thermalManager.isHeatingBed() :
|
||||
#endif
|
||||
thermalManager.isHeatingHotend(heater)
|
||||
) {
|
||||
u8g.setColorIndex(0); // white on black
|
||||
u8g.drawBox(x + h, y, 2, 2);
|
||||
u8g.setColorIndex(1); // black on white
|
||||
if (PAGE_CONTAINS(17, 20)) {
|
||||
const uint8_t h = isBed ? 7 : HEAT_INDICATOR_X,
|
||||
y = isBed ? 18 : 17;
|
||||
if (
|
||||
#if HAS_HEATED_BED
|
||||
isBed ? thermalManager.isHeatingBed() :
|
||||
#endif
|
||||
thermalManager.isHeatingHotend(heater)
|
||||
) {
|
||||
u8g.setColorIndex(0); // white on black
|
||||
u8g.drawBox(x + h, y, 2, 2);
|
||||
u8g.setColorIndex(1); // black on white
|
||||
}
|
||||
else
|
||||
u8g.drawBox(x + h, y, 2, 2);
|
||||
}
|
||||
else
|
||||
u8g.drawBox(x + h, y, 2, 2);
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_INLINE void _draw_axis_label(const AxisEnum axis, const char* const pstr, const bool blink) {
|
||||
//
|
||||
// Before homing, blink '123' <-> '???'.
|
||||
// Homed but unknown... '123' <-> ' '.
|
||||
// Homed and known, display constantly.
|
||||
//
|
||||
FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink) {
|
||||
if (blink)
|
||||
lcd_printPGM(pstr);
|
||||
lcd_print(value);
|
||||
else {
|
||||
if (!axis_homed[axis])
|
||||
u8g.print('?');
|
||||
while (const char c = *value++) lcd_print(c <= '.' ? c : '?');
|
||||
else {
|
||||
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
|
||||
if (!axis_known_position[axis])
|
||||
u8g.print(' ');
|
||||
lcd_printPGM(axis == Z_AXIS ? PSTR(" ") : PSTR(" "));
|
||||
else
|
||||
#endif
|
||||
lcd_printPGM(pstr);
|
||||
lcd_print(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -118,36 +124,77 @@ FORCE_INLINE void _draw_axis_label(const AxisEnum axis, const char* const pstr,
|
||||
inline void lcd_implementation_status_message(const bool blink) {
|
||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||
static bool last_blink = false;
|
||||
const uint8_t slen = lcd_strlen(lcd_status_message);
|
||||
const char *stat = lcd_status_message + status_scroll_pos;
|
||||
if (slen <= LCD_WIDTH)
|
||||
lcd_print_utf(stat); // The string isn't scrolling
|
||||
|
||||
// Get the UTF8 character count of the string
|
||||
uint8_t slen = lcd_strlen(lcd_status_message);
|
||||
|
||||
// If the string fits into the LCD, just print it and do not scroll it
|
||||
if (slen <= LCD_WIDTH) {
|
||||
|
||||
// The string isn't scrolling and may not fill the screen
|
||||
lcd_print_utf(lcd_status_message);
|
||||
|
||||
// Fill the rest with spaces
|
||||
while (slen < LCD_WIDTH) {
|
||||
u8g.print(' ');
|
||||
++slen;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (status_scroll_pos <= slen - LCD_WIDTH)
|
||||
lcd_print_utf(stat); // The string fills the screen
|
||||
// String is larger than the available space in screen.
|
||||
|
||||
// Get a pointer to the next valid UTF8 character
|
||||
const char *stat = lcd_status_message + status_scroll_offset;
|
||||
|
||||
// Get the string remaining length
|
||||
const uint8_t rlen = lcd_strlen(stat);
|
||||
|
||||
// If we have enough characters to display
|
||||
if (rlen >= LCD_WIDTH) {
|
||||
// The remaining string fills the screen - Print it
|
||||
lcd_print_utf(stat, LCD_WIDTH);
|
||||
}
|
||||
else {
|
||||
uint8_t chars = LCD_WIDTH;
|
||||
if (status_scroll_pos < slen) { // First string still visible
|
||||
lcd_print_utf(stat); // The string leaves space
|
||||
chars -= slen - status_scroll_pos; // Amount of space left
|
||||
}
|
||||
u8g.print('.'); // Always at 1+ spaces left, draw a dot
|
||||
if (--chars) {
|
||||
if (status_scroll_pos < slen + 1) // Draw a second dot if there's space
|
||||
--chars, u8g.print('.');
|
||||
if (chars) lcd_print_utf(lcd_status_message, chars); // Print a second copy of the message
|
||||
// The remaining string does not completely fill the screen
|
||||
lcd_print_utf(stat, LCD_WIDTH); // The string leaves space
|
||||
uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters
|
||||
|
||||
u8g.print('.'); // Always at 1+ spaces left, draw a dot
|
||||
if (--chars) { // Draw a second dot if there's space
|
||||
u8g.print('.');
|
||||
if (--chars) {
|
||||
// Print a second copy of the message
|
||||
lcd_print_utf(lcd_status_message, LCD_WIDTH - (rlen+2));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (last_blink != blink) {
|
||||
last_blink = blink;
|
||||
// Skip any non-printing bytes
|
||||
if (status_scroll_pos < slen) while (!PRINTABLE(lcd_status_message[status_scroll_pos])) status_scroll_pos++;
|
||||
if (++status_scroll_pos >= slen + 2) status_scroll_pos = 0;
|
||||
if (last_blink != blink) {
|
||||
last_blink = blink;
|
||||
|
||||
// Adjust by complete UTF8 characters
|
||||
if (status_scroll_offset < slen) {
|
||||
status_scroll_offset++;
|
||||
while (!START_OF_UTF8_CHAR(lcd_status_message[status_scroll_offset]))
|
||||
status_scroll_offset++;
|
||||
}
|
||||
else
|
||||
status_scroll_offset = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
UNUSED(blink);
|
||||
lcd_print_utf(lcd_status_message);
|
||||
|
||||
// Get the UTF8 character count of the string
|
||||
uint8_t slen = lcd_strlen(lcd_status_message);
|
||||
|
||||
// Just print the string to the LCD
|
||||
lcd_print_utf(lcd_status_message, LCD_WIDTH);
|
||||
|
||||
// Fill the rest with spaces if there are missing spaces
|
||||
while (slen < LCD_WIDTH) {
|
||||
u8g.print(' ');
|
||||
++slen;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -220,7 +267,7 @@ static void lcd_implementation_status_screen() {
|
||||
#endif
|
||||
|
||||
#if HAS_FAN0
|
||||
if (PAGE_CONTAINS(20, 27)) {
|
||||
if (PAGE_CONTAINS(STATUS_SCREEN_FAN_TEXT_Y - 7, STATUS_SCREEN_FAN_TEXT_Y)) {
|
||||
// Fan
|
||||
const int16_t per = ((fanSpeeds[0] + 1) * 100) / 256;
|
||||
if (per) {
|
||||
@@ -330,10 +377,6 @@ static void lcd_implementation_status_screen() {
|
||||
#define XYZ_FRAME_HEIGHT INFO_FONT_HEIGHT + 1
|
||||
#endif
|
||||
|
||||
// Before homing the axis letters are blinking 'X' <-> '?'.
|
||||
// When axis is homed but axis_known_position is false the axis letters are blinking 'X' <-> ' '.
|
||||
// When everything is ok you see a constant 'X'.
|
||||
|
||||
static char xstring[5], ystring[5], zstring[7];
|
||||
#if ENABLED(FILAMENT_LCD_DISPLAY)
|
||||
static char wstring[5], mstring[4];
|
||||
@@ -370,19 +413,19 @@ static void lcd_implementation_status_screen() {
|
||||
#endif
|
||||
|
||||
u8g.setPrintPos(0 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
|
||||
_draw_axis_label(X_AXIS, PSTR(MSG_X), blink);
|
||||
lcd_printPGM(PSTR(MSG_X));
|
||||
u8g.setPrintPos(0 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
|
||||
lcd_print(xstring);
|
||||
_draw_axis_value(X_AXIS, xstring, blink);
|
||||
|
||||
u8g.setPrintPos(1 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
|
||||
_draw_axis_label(Y_AXIS, PSTR(MSG_Y), blink);
|
||||
lcd_printPGM(PSTR(MSG_Y));
|
||||
u8g.setPrintPos(1 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
|
||||
lcd_print(ystring);
|
||||
_draw_axis_value(Y_AXIS, ystring, blink);
|
||||
|
||||
u8g.setPrintPos(2 * XYZ_SPACING + X_LABEL_POS, XYZ_BASELINE);
|
||||
_draw_axis_label(Z_AXIS, PSTR(MSG_Z), blink);
|
||||
lcd_printPGM(PSTR(MSG_Z));
|
||||
u8g.setPrintPos(2 * XYZ_SPACING + X_VALUE_POS, XYZ_BASELINE);
|
||||
lcd_print(zstring);
|
||||
_draw_axis_value(Z_AXIS, zstring, blink);
|
||||
|
||||
#if DISABLED(XYZ_HOLLOW_FRAME)
|
||||
u8g.setColorIndex(1); // black on white
|
||||
|
||||
@@ -615,36 +615,71 @@ void ST7920_Lite_Status_Screen::draw_feedrate_percentage(const uint8_t percentag
|
||||
void ST7920_Lite_Status_Screen::draw_status_message(const char *str) {
|
||||
set_ddram_address(DDRAM_LINE_4);
|
||||
begin_data();
|
||||
const uint8_t lcd_len = 16;
|
||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||
const uint8_t lcd_len = 16;
|
||||
const uint8_t padding = 2;
|
||||
uint8_t str_len = strlen(str);
|
||||
|
||||
uint8_t slen = lcd_strlen(str);
|
||||
|
||||
// Trim whitespace at the end of the str, as for some reason
|
||||
// messages like "Card Inserted" are padded with many spaces
|
||||
while (str_len && str[str_len - 1] == ' ') str_len--;
|
||||
// If the string fits into the LCD, just print it and do not scroll it
|
||||
if (slen <= lcd_len) {
|
||||
|
||||
if (str_len <= lcd_len) {
|
||||
// It all fits on the LCD without scrolling
|
||||
// The string isn't scrolling and may not fill the screen
|
||||
write_str(str);
|
||||
|
||||
// Fill the rest with spaces
|
||||
while (slen < lcd_len) {
|
||||
write_byte(' ');
|
||||
++slen;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Print the message repeatedly until covering the LCD
|
||||
uint8_t c = status_scroll_pos;
|
||||
for (uint8_t n = 0; n < lcd_len; n++) {
|
||||
write_byte(c < str_len ? str[c] : ' ');
|
||||
c++;
|
||||
c %= str_len + padding; // Wrap around
|
||||
// String is larger than the available space in screen.
|
||||
|
||||
// Get a pointer to the next valid UTF8 character
|
||||
const char *stat = str + status_scroll_offset;
|
||||
|
||||
// Get the string remaining length
|
||||
const uint8_t rlen = lcd_strlen(stat);
|
||||
|
||||
// If we have enough characters to display
|
||||
if (rlen >= lcd_len) {
|
||||
// The remaining string fills the screen - Print it
|
||||
write_str(stat, lcd_len);
|
||||
}
|
||||
else {
|
||||
// The remaining string does not completely fill the screen
|
||||
write_str(stat); // The string leaves space
|
||||
uint8_t chars = lcd_len - rlen; // Amount of space left in characters
|
||||
|
||||
write_byte('.'); // Always at 1+ spaces left, draw a dot
|
||||
if (--chars) { // Draw a second dot if there's space
|
||||
write_byte('.');
|
||||
if (--chars)
|
||||
write_str(str, chars); // Print a second copy of the message
|
||||
}
|
||||
}
|
||||
|
||||
// Scroll the message
|
||||
if (status_scroll_pos == str_len + padding)
|
||||
status_scroll_pos = 0;
|
||||
// Adjust by complete UTF8 characters
|
||||
if (status_scroll_offset < slen) {
|
||||
status_scroll_offset++;
|
||||
while (!START_OF_UTF8_CHAR(str[status_scroll_offset]))
|
||||
status_scroll_offset++;
|
||||
}
|
||||
else
|
||||
status_scroll_pos++;
|
||||
status_scroll_offset = 0;
|
||||
}
|
||||
#else
|
||||
write_str(str, 16);
|
||||
// Get the UTF8 character count of the string
|
||||
uint8_t slen = lcd_strlen(str);
|
||||
|
||||
// Just print the string to the LCD
|
||||
write_str(str, lcd_len);
|
||||
|
||||
// Fill the rest with spaces if there are missing spaces
|
||||
while (slen < lcd_len) {
|
||||
write_byte(' ');
|
||||
++slen;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -792,7 +827,7 @@ void ST7920_Lite_Status_Screen::update_status_or_position(bool forceUpdate) {
|
||||
*/
|
||||
if (forceUpdate || status_changed()) {
|
||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||
status_scroll_pos = 0;
|
||||
status_scroll_offset = 0;
|
||||
#endif
|
||||
#if STATUS_EXPIRE_SECONDS
|
||||
countdown = lcd_status_message[0] ? STATUS_EXPIRE_SECONDS : 0;
|
||||
|
||||
+946
-837
File diff suppressed because it is too large
Load Diff
+95
-150
@@ -52,35 +52,32 @@
|
||||
class Stepper;
|
||||
extern Stepper stepper;
|
||||
|
||||
#define ENABLE_STEPPER_DRIVER_INTERRUPT() SBI(TIMSK1, OCIE1A)
|
||||
#define DISABLE_STEPPER_DRIVER_INTERRUPT() CBI(TIMSK1, OCIE1A)
|
||||
#define STEPPER_ISR_ENABLED() TEST(TIMSK1, OCIE1A)
|
||||
#define HAL_STEPPER_TIMER_RATE ((F_CPU) * 0.125)
|
||||
|
||||
// intRes = intIn1 * intIn2 >> 16
|
||||
// uses:
|
||||
// r26 to store 0
|
||||
// r27 to store the byte 1 of the 24 bit result
|
||||
#define MultiU16X8toH16(intRes, charIn1, intIn2) \
|
||||
asm volatile ( \
|
||||
A("clr r26") \
|
||||
A("mul %A1, %B2") \
|
||||
A("movw %A0, r0") \
|
||||
A("mul %A1, %A2") \
|
||||
A("add %A0, r1") \
|
||||
A("adc %B0, r26") \
|
||||
A("lsr r0") \
|
||||
A("adc %A0, r26") \
|
||||
A("adc %B0, r26") \
|
||||
A("clr r1") \
|
||||
: \
|
||||
"=&r" (intRes) \
|
||||
: \
|
||||
"d" (charIn1), \
|
||||
"d" (intIn2) \
|
||||
: \
|
||||
"r26" \
|
||||
)
|
||||
static FORCE_INLINE uint16_t MultiU16X8toH16(uint8_t charIn1, uint16_t intIn2) {
|
||||
register uint8_t tmp;
|
||||
register uint16_t intRes;
|
||||
__asm__ __volatile__ (
|
||||
A("clr %[tmp]")
|
||||
A("mul %[charIn1], %B[intIn2]")
|
||||
A("movw %A[intRes], r0")
|
||||
A("mul %[charIn1], %A[intIn2]")
|
||||
A("add %A[intRes], r1")
|
||||
A("adc %B[intRes], %[tmp]")
|
||||
A("lsr r0")
|
||||
A("adc %A[intRes], %[tmp]")
|
||||
A("adc %B[intRes], %[tmp]")
|
||||
A("clr r1")
|
||||
: [intRes] "=&r" (intRes),
|
||||
[tmp] "=&r" (tmp)
|
||||
: [charIn1] "d" (charIn1),
|
||||
[intIn2] "d" (intIn2)
|
||||
: "cc"
|
||||
);
|
||||
return intRes;
|
||||
}
|
||||
|
||||
class Stepper {
|
||||
|
||||
@@ -88,10 +85,6 @@ class Stepper {
|
||||
|
||||
static block_t* current_block; // A pointer to the block currently being traced
|
||||
|
||||
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
|
||||
static bool abort_on_endstop_hit;
|
||||
#endif
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS) || ENABLED(Y_DUAL_ENDSTOPS) || ENABLED(Z_DUAL_ENDSTOPS)
|
||||
static bool performing_homing;
|
||||
#endif
|
||||
@@ -103,11 +96,12 @@ class Stepper {
|
||||
static uint32_t motor_current_setting[3];
|
||||
#endif
|
||||
|
||||
static int16_t cleaning_buffer_counter;
|
||||
|
||||
private:
|
||||
|
||||
static uint8_t last_direction_bits; // The next stepping-bits to be output
|
||||
static uint8_t last_direction_bits, // The next stepping-bits to be output
|
||||
last_movement_extruder, // Last movement extruder, as computed when the last movement was fetched from planner
|
||||
axis_did_move; // Last Movement in the given direction is not null, as computed when the last movement was fetched from planner
|
||||
static bool abort_current_block; // Signals to the stepper that current block should be aborted
|
||||
|
||||
#if ENABLED(X_DUAL_ENDSTOPS)
|
||||
static bool locked_x_motor, locked_x2_motor;
|
||||
@@ -121,7 +115,7 @@ class Stepper {
|
||||
|
||||
// Counter variables for the Bresenham line tracer
|
||||
static int32_t counter_X, counter_Y, counter_Z, counter_E;
|
||||
static volatile uint32_t step_events_completed; // The number of step events executed in the current block
|
||||
static uint32_t step_events_completed; // The number of step events executed in the current block
|
||||
|
||||
#if ENABLED(BEZIER_JERK_CONTROL)
|
||||
static int32_t bezier_A, // A coefficient in Bézier speed curve
|
||||
@@ -133,12 +127,14 @@ class Stepper {
|
||||
bezier_2nd_half; // If Bézier curve has been initialized or not
|
||||
#endif
|
||||
|
||||
static uint32_t nextMainISR; // time remaining for the next Step ISR
|
||||
static bool all_steps_done; // all steps done
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
|
||||
static uint32_t LA_decelerate_after; // Copy from current executed block. Needed because current_block is set to NULL "too early".
|
||||
static uint16_t nextMainISR, nextAdvanceISR, eISR_Rate, current_adv_steps,
|
||||
final_adv_steps, max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
|
||||
#define _NEXT_ISR(T) nextMainISR = T
|
||||
static uint32_t nextAdvanceISR, eISR_Rate;
|
||||
static uint16_t current_adv_steps, final_adv_steps, max_adv_steps; // Copy from current executed block. Needed because current_block is set to NULL "too early".
|
||||
static int8_t e_steps;
|
||||
static bool use_advance_lead;
|
||||
#if E_STEPPERS > 1
|
||||
@@ -147,18 +143,14 @@ class Stepper {
|
||||
static constexpr int8_t LA_active_extruder = 0;
|
||||
#endif
|
||||
|
||||
#else // !LIN_ADVANCE
|
||||
#endif // LIN_ADVANCE
|
||||
|
||||
#define _NEXT_ISR(T) OCR1A = T
|
||||
|
||||
#endif // !LIN_ADVANCE
|
||||
|
||||
static int32_t acceleration_time, deceleration_time;
|
||||
static uint32_t acceleration_time, deceleration_time;
|
||||
static uint8_t step_loops, step_loops_nominal;
|
||||
|
||||
static uint16_t OCR1A_nominal;
|
||||
static uint32_t ticks_nominal;
|
||||
#if DISABLED(BEZIER_JERK_CONTROL)
|
||||
static uint16_t acc_step_rate; // needed for deceleration start point
|
||||
static uint32_t acc_step_rate; // needed for deceleration start point
|
||||
#endif
|
||||
|
||||
static volatile int32_t endstops_trigsteps[XYZ];
|
||||
@@ -191,105 +183,53 @@ class Stepper {
|
||||
//
|
||||
Stepper() { };
|
||||
|
||||
//
|
||||
// Initialize stepper hardware
|
||||
//
|
||||
static void init();
|
||||
|
||||
//
|
||||
// Interrupt Service Routines
|
||||
//
|
||||
|
||||
static void isr();
|
||||
// The ISR scheduler
|
||||
static hal_timer_t isr_scheduler();
|
||||
|
||||
// The stepper pulse phase ISR
|
||||
static void stepper_pulse_phase_isr();
|
||||
|
||||
// The stepper block processing phase ISR
|
||||
static uint32_t stepper_block_phase_isr();
|
||||
|
||||
#if ENABLED(LIN_ADVANCE)
|
||||
static void advance_isr();
|
||||
static void advance_isr_scheduler();
|
||||
// The Linear advance stepper ISR
|
||||
static uint32_t advance_isr();
|
||||
#endif
|
||||
|
||||
//
|
||||
// Block until all buffered steps are executed
|
||||
//
|
||||
static void synchronize();
|
||||
|
||||
//
|
||||
// Set the current position in steps
|
||||
//
|
||||
static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
|
||||
|
||||
FORCE_INLINE static void _set_position(const AxisEnum a, const int32_t &v) { count_position[a] = v; }
|
||||
|
||||
FORCE_INLINE static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
|
||||
synchronize();
|
||||
CRITICAL_SECTION_START;
|
||||
_set_position(a, b, c, e);
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
static void set_position(const AxisEnum a, const int32_t &v) {
|
||||
synchronize();
|
||||
CRITICAL_SECTION_START;
|
||||
count_position[a] = v;
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
FORCE_INLINE static void _set_e_position(const int32_t &e) { count_position[E_AXIS] = e; }
|
||||
|
||||
static void set_e_position(const int32_t &e) {
|
||||
synchronize();
|
||||
CRITICAL_SECTION_START;
|
||||
count_position[E_AXIS] = e;
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
//
|
||||
// Set direction bits for all steppers
|
||||
//
|
||||
static void set_directions();
|
||||
|
||||
//
|
||||
// Get the position of a stepper, in steps
|
||||
//
|
||||
static int32_t position(const AxisEnum axis);
|
||||
|
||||
//
|
||||
// Report the positions of the steppers, in steps
|
||||
//
|
||||
static void report_positions();
|
||||
|
||||
//
|
||||
// Get the position (mm) of an axis based on stepper position(s)
|
||||
//
|
||||
static float get_axis_position_mm(const AxisEnum axis);
|
||||
|
||||
//
|
||||
// SCARA AB axes are in degrees, not mm
|
||||
//
|
||||
#if IS_SCARA
|
||||
FORCE_INLINE static float get_axis_position_degrees(const AxisEnum axis) { return get_axis_position_mm(axis); }
|
||||
#endif
|
||||
|
||||
//
|
||||
// The stepper subsystem goes to sleep when it runs out of things to execute. Call this
|
||||
// to notify the subsystem that it is time to go to work.
|
||||
//
|
||||
static void wake_up();
|
||||
|
||||
//
|
||||
// Wait for moves to finish and disable all steppers
|
||||
//
|
||||
static void finish_and_disable();
|
||||
// Quickly stop all steppers
|
||||
FORCE_INLINE static void quick_stop() { abort_current_block = true; }
|
||||
|
||||
//
|
||||
// Quickly stop all steppers and clear the blocks queue
|
||||
//
|
||||
static void quick_stop();
|
||||
|
||||
//
|
||||
// The direction of a single motor
|
||||
//
|
||||
FORCE_INLINE static bool motor_direction(const AxisEnum axis) { return TEST(last_direction_bits, axis); }
|
||||
|
||||
// The last movement direction was not null on the specified axis. Note that motor direction is not necessarily the same.
|
||||
FORCE_INLINE static bool axis_is_moving(const AxisEnum axis) { return TEST(axis_did_move, axis); }
|
||||
|
||||
// The extruder associated to the last movement
|
||||
FORCE_INLINE static uint8_t movement_extruder() { return last_movement_extruder; }
|
||||
|
||||
// Handle a triggered endstop
|
||||
static void endstop_triggered(const AxisEnum axis);
|
||||
|
||||
// Triggered position of an axis in steps
|
||||
static int32_t triggered_position(const AxisEnum axis);
|
||||
|
||||
#if HAS_DIGIPOTSS || HAS_MOTOR_CURRENT_PWM
|
||||
static void digitalPotWrite(const int16_t address, const int16_t value);
|
||||
static void digipot_current(const uint8_t driver, const int16_t current);
|
||||
@@ -321,32 +261,37 @@ class Stepper {
|
||||
static void babystep(const AxisEnum axis, const bool direction); // perform a short step with a single stepper motor, outside of any convention
|
||||
#endif
|
||||
|
||||
static inline void kill_current_block() {
|
||||
step_events_completed = current_block->step_event_count;
|
||||
}
|
||||
|
||||
//
|
||||
// Handle a triggered endstop
|
||||
//
|
||||
static void endstop_triggered(const AxisEnum axis);
|
||||
|
||||
//
|
||||
// Triggered position of an axis in mm (not core-savvy)
|
||||
//
|
||||
FORCE_INLINE static float triggered_position_mm(const AxisEnum axis) {
|
||||
return endstops_trigsteps[axis] * planner.steps_to_mm[axis];
|
||||
}
|
||||
|
||||
#if HAS_MOTOR_CURRENT_PWM
|
||||
static void refresh_motor_power();
|
||||
#endif
|
||||
|
||||
// Set the current position in steps
|
||||
inline static void set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e) {
|
||||
planner.synchronize();
|
||||
CRITICAL_SECTION_START;
|
||||
_set_position(a, b, c, e);
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
inline static void set_position(const AxisEnum a, const int32_t &v) {
|
||||
planner.synchronize();
|
||||
CRITICAL_SECTION_START;
|
||||
count_position[a] = v;
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
FORCE_INLINE static uint16_t calc_timer_interval(uint16_t step_rate) {
|
||||
uint16_t timer;
|
||||
// Set the current position in steps
|
||||
static void _set_position(const int32_t &a, const int32_t &b, const int32_t &c, const int32_t &e);
|
||||
|
||||
NOMORE(step_rate, MAX_STEP_FREQUENCY);
|
||||
// Set direction bits for all steppers
|
||||
static void set_directions();
|
||||
|
||||
FORCE_INLINE static uint32_t calc_timer_interval(uint32_t step_rate) {
|
||||
uint32_t timer;
|
||||
|
||||
NOMORE(step_rate, uint32_t(MAX_STEP_FREQUENCY));
|
||||
|
||||
if (step_rate > 20000) { // If steprate > 20kHz >> step 4 times
|
||||
step_rate >>= 2;
|
||||
@@ -360,26 +305,26 @@ class Stepper {
|
||||
step_loops = 1;
|
||||
}
|
||||
|
||||
NOLESS(step_rate, F_CPU / 500000);
|
||||
NOLESS(step_rate, uint32_t(F_CPU / 500000U));
|
||||
step_rate -= F_CPU / 500000; // Correct for minimal speed
|
||||
if (step_rate >= (8 * 256)) { // higher step rate
|
||||
unsigned short table_address = (unsigned short)&speed_lookuptable_fast[(unsigned char)(step_rate >> 8)][0];
|
||||
unsigned char tmp_step_rate = (step_rate & 0x00FF);
|
||||
unsigned short gain = (unsigned short)pgm_read_word_near(table_address + 2);
|
||||
MultiU16X8toH16(timer, tmp_step_rate, gain);
|
||||
timer = (unsigned short)pgm_read_word_near(table_address) - timer;
|
||||
const uint8_t tmp_step_rate = (step_rate & 0x00FF);
|
||||
const uint16_t table_address = (uint16_t)&speed_lookuptable_fast[(uint8_t)(step_rate >> 8)][0],
|
||||
gain = (uint16_t)pgm_read_word_near(table_address + 2);
|
||||
timer = MultiU16X8toH16(tmp_step_rate, gain);
|
||||
timer = (uint16_t)pgm_read_word_near(table_address) - timer;
|
||||
}
|
||||
else { // lower step rates
|
||||
unsigned short table_address = (unsigned short)&speed_lookuptable_slow[0][0];
|
||||
uint16_t table_address = (uint16_t)&speed_lookuptable_slow[0][0];
|
||||
table_address += ((step_rate) >> 1) & 0xFFFC;
|
||||
timer = (unsigned short)pgm_read_word_near(table_address);
|
||||
timer -= (((unsigned short)pgm_read_word_near(table_address + 2) * (unsigned char)(step_rate & 0x0007)) >> 3);
|
||||
timer = (uint16_t)pgm_read_word_near(table_address)
|
||||
- (((uint16_t)pgm_read_word_near(table_address + 2) * (uint8_t)(step_rate & 0x0007)) >> 3);
|
||||
}
|
||||
if (timer < 100) { // (20kHz - this should never happen)
|
||||
timer = 100;
|
||||
SERIAL_PROTOCOL(MSG_STEPPER_TOO_HIGH);
|
||||
SERIAL_PROTOCOLLN(step_rate);
|
||||
SERIAL_ECHOLNPAIR(MSG_STEPPER_TOO_HIGH, step_rate);
|
||||
}
|
||||
|
||||
return timer;
|
||||
}
|
||||
|
||||
|
||||
@@ -179,6 +179,10 @@
|
||||
// Following values from Trinamic's spreadsheet with values for a NEMA17 (42BYGHW609)
|
||||
// https://www.trinamic.com/products/integrated-circuits/details/tmc2130/
|
||||
void tmc2130_init(TMC2130Stepper &st, const uint16_t mA, const uint16_t microsteps, const uint32_t thrs, const float spmm) {
|
||||
#if DISABLED(STEALTHCHOP) || DISABLED(HYBRID_THRESHOLD)
|
||||
UNUSED(thrs);
|
||||
UNUSED(spmm);
|
||||
#endif
|
||||
st.begin();
|
||||
st.setCurrent(mA, R_SENSE, HOLD_MULTIPLIER);
|
||||
st.microsteps(microsteps);
|
||||
@@ -196,9 +200,6 @@
|
||||
st.stealthChop(1);
|
||||
#if ENABLED(HYBRID_THRESHOLD)
|
||||
st.stealth_max_speed(12650000UL*microsteps/(256*thrs*spmm));
|
||||
#else
|
||||
UNUSED(thrs);
|
||||
UNUSED(spmm);
|
||||
#endif
|
||||
#elif ENABLED(SENSORLESS_HOMING)
|
||||
st.coolstep_min_speed(1024UL * 1024UL - 1UL);
|
||||
|
||||
@@ -447,44 +447,48 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
* Extruder indirection for the single E axis
|
||||
*/
|
||||
#if ENABLED(SWITCHING_EXTRUDER)
|
||||
#if EXTRUDERS == 2
|
||||
#if EXTRUDERS > 4
|
||||
#define E_STEP_WRITE(v) do{ if (current_block->active_extruder < 2) { E0_STEP_WRITE(v); } else if (current_block->active_extruder < 4) { E1_STEP_WRITE(v); } else { E2_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); break; case 4: E2_DIR_WRITE(!INVERT_E2_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 4: E2_DIR_WRITE( INVERT_E2_DIR); } }while(0)
|
||||
#elif EXTRUDERS > 3
|
||||
#define E_STEP_WRITE(v) do{ if (current_block->active_extruder < 2) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
|
||||
#elif EXTRUDERS > 2
|
||||
#define E_STEP_WRITE(v) do{ if (current_block->active_extruder < 2) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE( INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
|
||||
#else
|
||||
#define E_STEP_WRITE(v) E0_STEP_WRITE(v)
|
||||
#define NORM_E_DIR() do{ E0_DIR_WRITE(current_block->active_extruder ? INVERT_E0_DIR : !INVERT_E0_DIR); }while(0)
|
||||
#define REV_E_DIR() do{ E0_DIR_WRITE(current_block->active_extruder ? !INVERT_E0_DIR : INVERT_E0_DIR); }while(0)
|
||||
#elif EXTRUDERS > 4
|
||||
#define E_STEP_WRITE(v) do{ if (current_block->active_extruder < 2) { E0_STEP_WRITE(v); } else if (current_block->active_extruder < 4) { E1_STEP_WRITE(v); } else { E2_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(INVERT_E1_DIR); break; case 4: E2_DIR_WRITE(!INVERT_E2_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 4: E2_DIR_WRITE(INVERT_E2_DIR); } }while(0)
|
||||
#elif EXTRUDERS > 2
|
||||
#define E_STEP_WRITE(v) do{ if (current_block->active_extruder < 2) { E0_STEP_WRITE(v); } else if (current_block->active_extruder < 4) { E1_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(INVERT_E1_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 2: E1_DIR_WRITE(INVERT_E1_DIR); break; case 3: E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ E0_DIR_WRITE(current_block->active_extruder ? !INVERT_E0_DIR : INVERT_E0_DIR); }while(0)
|
||||
#endif
|
||||
#elif ENABLED(MK2_MULTIPLEXER) // Even-numbered steppers are reversed
|
||||
#define E_STEP_WRITE(v) E0_STEP_WRITE(v)
|
||||
#define NORM_E_DIR() do{ E0_DIR_WRITE(TEST(current_block->active_extruder, 0) ? !INVERT_E0_DIR: INVERT_E0_DIR); }while(0)
|
||||
#define REV_E_DIR() do{ E0_DIR_WRITE(TEST(current_block->active_extruder, 0) ? INVERT_E0_DIR: !INVERT_E0_DIR); }while(0)
|
||||
#define REV_E_DIR() do{ E0_DIR_WRITE(TEST(current_block->active_extruder, 0) ? INVERT_E0_DIR: !INVERT_E0_DIR); }while(0)
|
||||
#elif EXTRUDERS > 4
|
||||
#define E_STEP_WRITE(v) do{ switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); break; case 4: E4_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); break; case 4: E4_DIR_WRITE(!INVERT_E4_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(INVERT_E3_DIR); break; case 4: E4_DIR_WRITE(INVERT_E4_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); break; case 4: E4_DIR_WRITE( INVERT_E4_DIR); } }while(0)
|
||||
#elif EXTRUDERS > 3
|
||||
#define E_STEP_WRITE(v) do{ switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); break; case 3: E3_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(!INVERT_E3_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(INVERT_E2_DIR); break; case 3: E3_DIR_WRITE(INVERT_E3_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); break; case 3: E3_DIR_WRITE( INVERT_E3_DIR); } }while(0)
|
||||
#elif EXTRUDERS > 2
|
||||
#define E_STEP_WRITE(v) do{ switch (current_block->active_extruder) { case 0: E0_STEP_WRITE(v); break; case 1: E1_STEP_WRITE(v); break; case 2: E2_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(!INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(!INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(!INVERT_E2_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE(INVERT_E0_DIR); break; case 1: E1_DIR_WRITE(INVERT_E1_DIR); break; case 2: E2_DIR_WRITE(INVERT_E2_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ switch (current_block->active_extruder) { case 0: E0_DIR_WRITE( INVERT_E0_DIR); break; case 1: E1_DIR_WRITE( INVERT_E1_DIR); break; case 2: E2_DIR_WRITE( INVERT_E2_DIR); } }while(0)
|
||||
#elif EXTRUDERS > 1
|
||||
#if ENABLED(DUAL_X_CARRIAGE) || ENABLED(DUAL_NOZZLE_DUPLICATION_MODE)
|
||||
#define E_STEP_WRITE(v) do{ if (extruder_duplication_enabled) { E0_STEP_WRITE(v); E1_STEP_WRITE(v); } else if (current_block->active_extruder == 0) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ if (extruder_duplication_enabled) { E0_DIR_WRITE(!INVERT_E0_DIR); E1_DIR_WRITE(!INVERT_E1_DIR); } else if (current_block->active_extruder == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ if (extruder_duplication_enabled) { E0_DIR_WRITE(INVERT_E0_DIR); E1_DIR_WRITE(INVERT_E1_DIR); } else if (current_block->active_extruder == 0) { E0_DIR_WRITE(INVERT_E0_DIR); } else { E1_DIR_WRITE(INVERT_E1_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ if (extruder_duplication_enabled) { E0_DIR_WRITE( INVERT_E0_DIR); E1_DIR_WRITE( INVERT_E1_DIR); } else if (current_block->active_extruder == 0) { E0_DIR_WRITE( INVERT_E0_DIR); } else { E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
|
||||
#else
|
||||
#define E_STEP_WRITE(v) do{ if (current_block->active_extruder == 0) { E0_STEP_WRITE(v); } else { E1_STEP_WRITE(v); } }while(0)
|
||||
#define NORM_E_DIR() do{ if (current_block->active_extruder == 0) { E0_DIR_WRITE(!INVERT_E0_DIR); } else { E1_DIR_WRITE(!INVERT_E1_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ if (current_block->active_extruder == 0) { E0_DIR_WRITE(INVERT_E0_DIR); } else { E1_DIR_WRITE(INVERT_E1_DIR); } }while(0)
|
||||
#define REV_E_DIR() do{ if (current_block->active_extruder == 0) { E0_DIR_WRITE( INVERT_E0_DIR); } else { E1_DIR_WRITE( INVERT_E1_DIR); } }while(0)
|
||||
#endif
|
||||
#elif ENABLED(MIXING_EXTRUDER)
|
||||
#define E_STEP_WRITE(v) NOOP /* not used for mixing extruders! */
|
||||
@@ -508,7 +512,7 @@ void reset_stepper_drivers(); // Called by settings.load / settings.reset
|
||||
#else
|
||||
#define E_STEP_WRITE(v) E0_STEP_WRITE(v)
|
||||
#define NORM_E_DIR() E0_DIR_WRITE(!INVERT_E0_DIR)
|
||||
#define REV_E_DIR() E0_DIR_WRITE(INVERT_E0_DIR)
|
||||
#define REV_E_DIR() E0_DIR_WRITE( INVERT_E0_DIR)
|
||||
#endif
|
||||
|
||||
#endif // STEPPER_INDIRECTION_H
|
||||
|
||||
+167
-206
@@ -31,6 +31,8 @@
|
||||
#include "planner.h"
|
||||
#include "language.h"
|
||||
#include "printcounter.h"
|
||||
#include "delay.h"
|
||||
#include "endstops.h"
|
||||
|
||||
#if ENABLED(HEATER_0_USES_MAX6675)
|
||||
#include "MarlinSPI.h"
|
||||
@@ -40,10 +42,6 @@
|
||||
#include "stepper.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
#include "endstops.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(USE_WATCHDOG)
|
||||
#include "watchdog.h"
|
||||
#endif
|
||||
@@ -52,12 +50,14 @@
|
||||
#include "emergency_parser.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
|
||||
static void* heater_ttbl_map[2] = { (void*)HEATER_0_TEMPTABLE, (void*)HEATER_1_TEMPTABLE };
|
||||
static uint8_t heater_ttbllen_map[2] = { HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN };
|
||||
#else
|
||||
static void* heater_ttbl_map[HOTENDS] = ARRAY_BY_HOTENDS((void*)HEATER_0_TEMPTABLE, (void*)HEATER_1_TEMPTABLE, (void*)HEATER_2_TEMPTABLE, (void*)HEATER_3_TEMPTABLE, (void*)HEATER_4_TEMPTABLE);
|
||||
static uint8_t heater_ttbllen_map[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN, HEATER_3_TEMPTABLE_LEN, HEATER_4_TEMPTABLE_LEN);
|
||||
#if HOTEND_USES_THERMISTOR
|
||||
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
|
||||
static void* heater_ttbl_map[2] = { (void*)HEATER_0_TEMPTABLE, (void*)HEATER_1_TEMPTABLE };
|
||||
static uint8_t heater_ttbllen_map[2] = { HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN };
|
||||
#else
|
||||
static void* heater_ttbl_map[HOTENDS] = ARRAY_BY_HOTENDS((void*)HEATER_0_TEMPTABLE, (void*)HEATER_1_TEMPTABLE, (void*)HEATER_2_TEMPTABLE, (void*)HEATER_3_TEMPTABLE, (void*)HEATER_4_TEMPTABLE);
|
||||
static uint8_t heater_ttbllen_map[HOTENDS] = ARRAY_BY_HOTENDS(HEATER_0_TEMPTABLE_LEN, HEATER_1_TEMPTABLE_LEN, HEATER_2_TEMPTABLE_LEN, HEATER_3_TEMPTABLE_LEN, HEATER_4_TEMPTABLE_LEN);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Temperature thermalManager;
|
||||
@@ -235,6 +235,10 @@ uint8_t Temperature::soft_pwm_amount[HOTENDS];
|
||||
uint8_t Temperature::ADCKey_count = 0;
|
||||
#endif
|
||||
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
int16_t Temperature::lpq_len; // Initialized in configuration_store
|
||||
#endif
|
||||
|
||||
#if HAS_PID_HEATING
|
||||
|
||||
/**
|
||||
@@ -664,14 +668,14 @@ float Temperature::get_pid_output(const int8_t e) {
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
cTerm[HOTEND_INDEX] = 0;
|
||||
if (_HOTEND_TEST) {
|
||||
long e_position = stepper.position(E_AXIS);
|
||||
const long e_position = stepper.position(E_AXIS);
|
||||
if (e_position > last_e_position) {
|
||||
lpq[lpq_ptr] = e_position - last_e_position;
|
||||
last_e_position = e_position;
|
||||
}
|
||||
else {
|
||||
else
|
||||
lpq[lpq_ptr] = 0;
|
||||
}
|
||||
|
||||
if (++lpq_ptr >= lpq_len) lpq_ptr = 0;
|
||||
cTerm[HOTEND_INDEX] = (lpq[lpq_ptr] * planner.steps_to_mm[E_AXIS]) * PID_PARAM(Kc, HOTEND_INDEX);
|
||||
pid_output += cTerm[HOTEND_INDEX];
|
||||
@@ -785,8 +789,8 @@ void Temperature::manage_heater() {
|
||||
updateTemperaturesFromRawValues(); // also resets the watchdog
|
||||
|
||||
#if ENABLED(HEATER_0_USES_MAX6675)
|
||||
if (current_temperature[0] > min(HEATER_0_MAXTEMP, MAX6675_TMAX - 1.0)) max_temp_error(0);
|
||||
if (current_temperature[0] < max(HEATER_0_MINTEMP, MAX6675_TMIN + .01)) min_temp_error(0);
|
||||
if (current_temperature[0] > MIN(HEATER_0_MAXTEMP, MAX6675_TMAX - 1.0)) max_temp_error(0);
|
||||
if (current_temperature[0] < MAX(HEATER_0_MINTEMP, MAX6675_TMIN + .01)) min_temp_error(0);
|
||||
#endif
|
||||
|
||||
#if WATCH_HOTENDS || WATCH_THE_BED || DISABLED(PIDTEMPBED) || HAS_AUTO_FAN || HEATER_IDLE_HANDLER
|
||||
@@ -819,7 +823,7 @@ void Temperature::manage_heater() {
|
||||
|
||||
#if ENABLED(TEMP_SENSOR_1_AS_REDUNDANT)
|
||||
// Make sure measured temperatures are close together
|
||||
if (FABS(current_temperature[0] - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF)
|
||||
if (ABS(current_temperature[0] - redundant_temperature) > MAX_REDUNDANT_TEMP_SENSOR_DIFF)
|
||||
_temp_error(0, PSTR(MSG_REDUNDANCY), PSTR(MSG_ERR_REDUNDANT_TEMP));
|
||||
#endif
|
||||
|
||||
@@ -911,7 +915,21 @@ void Temperature::manage_heater() {
|
||||
#endif // HAS_HEATED_BED
|
||||
}
|
||||
|
||||
#define PGM_RD_W(x) (short)pgm_read_word(&x)
|
||||
#define TEMP_AD595(RAW) ((RAW) * 5.0 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET)
|
||||
#define TEMP_AD8495(RAW) ((RAW) * 6.6 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD8495_GAIN) + TEMP_SENSOR_AD8495_OFFSET)
|
||||
|
||||
#define SCAN_THERMISTOR_TABLE(TBL,LEN) do{ \
|
||||
for (uint8_t i = 1; i < LEN; i++) { \
|
||||
const short entry10 = (short)pgm_read_word(&TBL[i][0]); \
|
||||
if (entry10 > raw) { \
|
||||
const short entry00 = (short)pgm_read_word(&TBL[i-1][0]), \
|
||||
entry01 = (short)pgm_read_word(&TBL[i-1][1]), \
|
||||
entry11 = (short)pgm_read_word(&TBL[i][1]); \
|
||||
return entry01 + (raw - entry00) * float(entry11 - entry01) / float(entry10 - entry00); \
|
||||
} \
|
||||
} \
|
||||
return (short)pgm_read_word(&TBL[LEN-1][1]); \
|
||||
}while(0)
|
||||
|
||||
// Derived from RepRap FiveD extruder::getTemperature()
|
||||
// For hot end temperature measurement.
|
||||
@@ -929,68 +947,73 @@ float Temperature::analog2temp(const int raw, const uint8_t e) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
#if ENABLED(HEATER_0_USES_MAX6675)
|
||||
if (e == 0) return 0.25 * raw;
|
||||
#endif
|
||||
|
||||
// Thermistor with conversion table?
|
||||
if (heater_ttbl_map[e] != NULL) {
|
||||
short(*tt)[][2] = (short(*)[][2])(heater_ttbl_map[e]);
|
||||
for (uint8_t i = 1; i < heater_ttbllen_map[e]; i++) {
|
||||
const short entry10 = PGM_RD_W((*tt)[i][0]);
|
||||
if (entry10 > raw) {
|
||||
const short entry00 = PGM_RD_W((*tt)[i - 1][0]),
|
||||
entry01 = PGM_RD_W((*tt)[i - 1][1]),
|
||||
entry11 = PGM_RD_W((*tt)[i][1]);
|
||||
return entry01 + (raw - entry00) * float(entry11 - entry01) / float(entry10 - entry00);
|
||||
}
|
||||
}
|
||||
return PGM_RD_W((*tt)[heater_ttbllen_map[e] - 1][1]); // Overflow: Return last value in the table
|
||||
switch (e) {
|
||||
case 0:
|
||||
#if ENABLED(HEATER_0_USES_MAX6675)
|
||||
return raw * 0.25;
|
||||
#elif ENABLED(HEATER_0_USES_AD595)
|
||||
return TEMP_AD595(raw);
|
||||
#elif ENABLED(HEATER_0_USES_AD8495)
|
||||
return TEMP_AD8495(raw);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case 1:
|
||||
#if ENABLED(HEATER_1_USES_AD595)
|
||||
return TEMP_AD595(raw);
|
||||
#elif ENABLED(HEATER_1_USES_AD8495)
|
||||
return TEMP_AD8495(raw);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case 2:
|
||||
#if ENABLED(HEATER_2_USES_AD595)
|
||||
return TEMP_AD595(raw);
|
||||
#elif ENABLED(HEATER_2_USES_AD8495)
|
||||
return TEMP_AD8495(raw);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case 3:
|
||||
#if ENABLED(HEATER_3_USES_AD595)
|
||||
return TEMP_AD595(raw);
|
||||
#elif ENABLED(HEATER_3_USES_AD8495)
|
||||
return TEMP_AD8495(raw);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
case 4:
|
||||
#if ENABLED(HEATER_4_USES_AD595)
|
||||
return TEMP_AD595(raw);
|
||||
#elif ENABLED(HEATER_4_USES_AD8495)
|
||||
return TEMP_AD8495(raw);
|
||||
#else
|
||||
break;
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Thermocouple with amplifier ADC interface
|
||||
return (raw *
|
||||
#if HEATER_USES_AD8495
|
||||
660.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD8495_GAIN) + TEMP_SENSOR_AD8495_OFFSET
|
||||
#elif HEATER_USES_AD595
|
||||
5.0 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
);
|
||||
#if HOTEND_USES_THERMISTOR
|
||||
// Thermistor with conversion table?
|
||||
const short(*tt)[][2] = (short(*)[][2])(heater_ttbl_map[e]);
|
||||
SCAN_THERMISTOR_TABLE((*tt), heater_ttbllen_map[e]);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if HAS_HEATED_BED
|
||||
// Derived from RepRap FiveD extruder::getTemperature()
|
||||
// For bed temperature measurement.
|
||||
float Temperature::analog2tempBed(const int raw) {
|
||||
#if ENABLED(BED_USES_THERMISTOR)
|
||||
|
||||
// Thermistor with conversion table
|
||||
for (uint8_t i = 1; i < BEDTEMPTABLE_LEN; i++) {
|
||||
const short entry10 = PGM_RD_W(BEDTEMPTABLE[i][0]);
|
||||
if (entry10 > raw) {
|
||||
const short entry00 = PGM_RD_W(BEDTEMPTABLE[i - 1][0]),
|
||||
entry01 = PGM_RD_W(BEDTEMPTABLE[i - 1][1]),
|
||||
entry11 = PGM_RD_W(BEDTEMPTABLE[i][1]);
|
||||
return entry01 + (raw - entry00) * float(entry11 - entry01) / float(entry10 - entry00);
|
||||
}
|
||||
}
|
||||
return PGM_RD_W(BEDTEMPTABLE[BEDTEMPTABLE_LEN - 1][1]); // Overflow: Return last value in the table
|
||||
|
||||
#if ENABLED(HEATER_BED_USES_THERMISTOR)
|
||||
SCAN_THERMISTOR_TABLE(BEDTEMPTABLE, BEDTEMPTABLE_LEN);
|
||||
#elif ENABLED(HEATER_BED_USES_AD595)
|
||||
return TEMP_AD595(raw);
|
||||
#elif ENABLED(HEATER_BED_USES_AD8495)
|
||||
return TEMP_AD8495(raw);
|
||||
#else
|
||||
|
||||
// Thermocouple with amplifier ADC interface
|
||||
return (raw *
|
||||
#if ENABLED(CHAMBER_USES_AD595)
|
||||
5.0 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET
|
||||
#elif ENABLED(CHAMBER_USES_AD8495)
|
||||
660.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD8495_GAIN) + TEMP_SENSOR_AD8495_OFFSET
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif // HAS_HEATED_BED
|
||||
@@ -999,33 +1022,14 @@ float Temperature::analog2temp(const int raw, const uint8_t e) {
|
||||
// Derived from RepRap FiveD extruder::getTemperature()
|
||||
// For chamber temperature measurement.
|
||||
float Temperature::analog2tempChamber(const int raw) {
|
||||
#if ENABLED(CHAMBER_USES_THERMISTOR)
|
||||
|
||||
// Thermistor with conversion table
|
||||
for (uint8_t i = 1; i < CHAMBERTEMPTABLE_LEN; i++) {
|
||||
const short entry10 = PGM_RD_W(CHAMBERTEMPTABLE[i][0]);
|
||||
if (entry10 > raw) {
|
||||
const short entry00 = PGM_RD_W(CHAMBERTEMPTABLE[i - 1][0]),
|
||||
entry01 = PGM_RD_W(CHAMBERTEMPTABLE[i - 1][1]),
|
||||
entry11 = PGM_RD_W(CHAMBERTEMPTABLE[i][1]);
|
||||
return entry01 + (raw - entry00) * float(entry11 - entry01) / float(entry10 - entry00);
|
||||
}
|
||||
}
|
||||
return PGM_RD_W(CHAMBERTEMPTABLE[CHAMBERTEMPTABLE_LEN - 1][1]); // Overflow: Return last value in the table
|
||||
|
||||
#if ENABLED(HEATER_CHAMBER_USES_THERMISTOR)
|
||||
SCAN_THERMISTOR_TABLE(CHAMBERTEMPTABLE, CHAMBERTEMPTABLE_LEN);
|
||||
#elif ENABLED(HEATER_CHAMBER_USES_AD595)
|
||||
return TEMP_AD595(raw);
|
||||
#elif ENABLED(HEATER_CHAMBER_USES_AD8495)
|
||||
return TEMP_AD8495(raw);
|
||||
#else
|
||||
|
||||
// Thermocouple with amplifier ADC interface
|
||||
return (raw *
|
||||
#if ENABLED(BED_USES_AD595)
|
||||
5.0 * 100.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD595_GAIN) + TEMP_SENSOR_AD595_OFFSET
|
||||
#elif ENABLED(BED_USES_AD8495)
|
||||
660.0 / 1024.0 / (OVERSAMPLENR) * (TEMP_SENSOR_AD8495_GAIN) + TEMP_SENSOR_AD8495_OFFSET
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
);
|
||||
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif // HAS_TEMP_CHAMBER
|
||||
@@ -1040,8 +1044,7 @@ void Temperature::updateTemperaturesFromRawValues() {
|
||||
#if ENABLED(HEATER_0_USES_MAX6675)
|
||||
current_temperature_raw[0] = read_max6675();
|
||||
#endif
|
||||
HOTEND_LOOP()
|
||||
current_temperature[e] = Temperature::analog2temp(current_temperature_raw[e], e);
|
||||
HOTEND_LOOP() current_temperature[e] = Temperature::analog2temp(current_temperature_raw[e], e);
|
||||
#if HAS_HEATED_BED
|
||||
current_temperature_bed = Temperature::analog2tempBed(current_temperature_bed_raw);
|
||||
#endif
|
||||
@@ -1060,9 +1063,7 @@ void Temperature::updateTemperaturesFromRawValues() {
|
||||
watchdog_reset();
|
||||
#endif
|
||||
|
||||
CRITICAL_SECTION_START;
|
||||
temp_meas_ready = false;
|
||||
CRITICAL_SECTION_END;
|
||||
}
|
||||
|
||||
|
||||
@@ -1082,7 +1083,7 @@ void Temperature::updateTemperaturesFromRawValues() {
|
||||
* a return value of 1.
|
||||
*/
|
||||
int8_t Temperature::widthFil_to_size_ratio() {
|
||||
if (FABS(filament_width_nominal - filament_width_meas) <= FILWIDTH_ERROR_MARGIN)
|
||||
if (ABS(filament_width_nominal - filament_width_meas) <= FILWIDTH_ERROR_MARGIN)
|
||||
return int(100.0 * filament_width_nominal / filament_width_meas) - 100;
|
||||
return 0;
|
||||
}
|
||||
@@ -1105,7 +1106,9 @@ void Temperature::updateTemperaturesFromRawValues() {
|
||||
*/
|
||||
void Temperature::init() {
|
||||
|
||||
#if MB(RUMBA) && (TEMP_SENSOR_0 == -1 || TEMP_SENSOR_1 == -1 || TEMP_SENSOR_2 == -1 || TEMP_SENSOR_BED == -1 || TEMP_SENSOR_CHAMBER == -1)
|
||||
#if MB(RUMBA) && ( \
|
||||
ENABLED(HEATER_0_USES_AD595) || ENABLED(HEATER_1_USES_AD595) || ENABLED(HEATER_2_USES_AD595) || ENABLED(HEATER_3_USES_AD595) || ENABLED(HEATER_4_USES_AD595) || ENABLED(HEATER_BED_USES_AD595) || ENABLED(HEATER_CHAMBER_USES_AD595) \
|
||||
|| ENABLED(HEATER_0_USES_AD8495) || ENABLED(HEATER_1_USES_AD8495) || ENABLED(HEATER_2_USES_AD8495) || ENABLED(HEATER_3_USES_AD8495) || ENABLED(HEATER_4_USES_AD8495) || ENABLED(HEATER_BED_USES_AD8495) || ENABLED(HEATER_CHAMBER_USES_AD8495))
|
||||
// Disable RUMBA JTAG in case the thermocouple extension is plugged on top of JTAG connector
|
||||
MCUCR = _BV(JTD);
|
||||
MCUCR = _BV(JTD);
|
||||
@@ -1171,43 +1174,38 @@ void Temperature::init() {
|
||||
|
||||
#endif // HEATER_0_USES_MAX6675
|
||||
|
||||
#ifdef DIDR2
|
||||
#define ANALOG_SELECT(pin) do{ if (pin < 8) SBI(DIDR0, pin); else SBI(DIDR2, pin & 0x07); }while(0)
|
||||
#else
|
||||
#define ANALOG_SELECT(pin) do{ SBI(DIDR0, pin); }while(0)
|
||||
#endif
|
||||
HAL_adc_init();
|
||||
|
||||
// Set analog inputs
|
||||
ADCSRA = _BV(ADEN) | _BV(ADSC) | _BV(ADIF) | 0x07;
|
||||
DIDR0 = 0;
|
||||
#ifdef DIDR2
|
||||
DIDR2 = 0;
|
||||
#endif
|
||||
#if HAS_TEMP_ADC_0
|
||||
ANALOG_SELECT(TEMP_0_PIN);
|
||||
HAL_ANALOG_SELECT(TEMP_0_PIN);
|
||||
#endif
|
||||
#if HAS_TEMP_ADC_1
|
||||
ANALOG_SELECT(TEMP_1_PIN);
|
||||
HAL_ANALOG_SELECT(TEMP_1_PIN);
|
||||
#endif
|
||||
#if HAS_TEMP_ADC_2
|
||||
ANALOG_SELECT(TEMP_2_PIN);
|
||||
HAL_ANALOG_SELECT(TEMP_2_PIN);
|
||||
#endif
|
||||
#if HAS_TEMP_ADC_3
|
||||
ANALOG_SELECT(TEMP_3_PIN);
|
||||
HAL_ANALOG_SELECT(TEMP_3_PIN);
|
||||
#endif
|
||||
#if HAS_TEMP_ADC_4
|
||||
ANALOG_SELECT(TEMP_4_PIN);
|
||||
HAL_ANALOG_SELECT(TEMP_4_PIN);
|
||||
#endif
|
||||
#if HAS_HEATED_BED
|
||||
ANALOG_SELECT(TEMP_BED_PIN);
|
||||
HAL_ANALOG_SELECT(TEMP_BED_PIN);
|
||||
#endif
|
||||
#if HAS_TEMP_CHAMBER
|
||||
ANALOG_SELECT(TEMP_CHAMBER_PIN);
|
||||
HAL_ANALOG_SELECT(TEMP_CHAMBER_PIN);
|
||||
#endif
|
||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||
ANALOG_SELECT(FILWIDTH_PIN);
|
||||
HAL_ANALOG_SELECT(FILWIDTH_PIN);
|
||||
#endif
|
||||
|
||||
// Use timer0 for temperature measurement
|
||||
// Interleave temperature interrupt with millies interrupt
|
||||
OCR0B = 128;
|
||||
ENABLE_TEMPERATURE_INTERRUPT();
|
||||
|
||||
#if HAS_AUTO_FAN_0
|
||||
#if E0_AUTO_FAN_PIN == FAN1_PIN
|
||||
SET_OUTPUT(E0_AUTO_FAN_PIN);
|
||||
@@ -1269,11 +1267,6 @@ void Temperature::init() {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Use timer0 for temperature measurement
|
||||
// Interleave temperature interrupt with millies interrupt
|
||||
OCR0B = 128;
|
||||
ENABLE_TEMPERATURE_INTERRUPT();
|
||||
|
||||
// Wait for temperature measurement to settle
|
||||
delay(250);
|
||||
|
||||
@@ -1618,7 +1611,7 @@ void Temperature::disable_all_heaters() {
|
||||
|
||||
WRITE(MAX6675_SS, 0); // enable TT_MAX6675
|
||||
|
||||
DELAY_100NS; // Ensure 100ns delay
|
||||
DELAY_NS(100); // Ensure 100ns delay
|
||||
|
||||
// Read a big-endian temperature value
|
||||
max6675_temp = 0;
|
||||
@@ -1702,71 +1695,71 @@ void Temperature::set_current_temp_raw() {
|
||||
*
|
||||
*/
|
||||
void endstop_monitor() {
|
||||
static uint16_t old_endstop_bits_local = 0;
|
||||
static uint16_t old_live_state_local = 0;
|
||||
static uint8_t local_LED_status = 0;
|
||||
uint16_t current_endstop_bits_local = 0;
|
||||
uint16_t live_state_local = 0;
|
||||
#if HAS_X_MIN
|
||||
if (READ(X_MIN_PIN)) SBI(current_endstop_bits_local, X_MIN);
|
||||
if (READ(X_MIN_PIN)) SBI(live_state_local, X_MIN);
|
||||
#endif
|
||||
#if HAS_X_MAX
|
||||
if (READ(X_MAX_PIN)) SBI(current_endstop_bits_local, X_MAX);
|
||||
if (READ(X_MAX_PIN)) SBI(live_state_local, X_MAX);
|
||||
#endif
|
||||
#if HAS_Y_MIN
|
||||
if (READ(Y_MIN_PIN)) SBI(current_endstop_bits_local, Y_MIN);
|
||||
if (READ(Y_MIN_PIN)) SBI(live_state_local, Y_MIN);
|
||||
#endif
|
||||
#if HAS_Y_MAX
|
||||
if (READ(Y_MAX_PIN)) SBI(current_endstop_bits_local, Y_MAX);
|
||||
if (READ(Y_MAX_PIN)) SBI(live_state_local, Y_MAX);
|
||||
#endif
|
||||
#if HAS_Z_MIN
|
||||
if (READ(Z_MIN_PIN)) SBI(current_endstop_bits_local, Z_MIN);
|
||||
if (READ(Z_MIN_PIN)) SBI(live_state_local, Z_MIN);
|
||||
#endif
|
||||
#if HAS_Z_MAX
|
||||
if (READ(Z_MAX_PIN)) SBI(current_endstop_bits_local, Z_MAX);
|
||||
if (READ(Z_MAX_PIN)) SBI(live_state_local, Z_MAX);
|
||||
#endif
|
||||
#if HAS_Z_MIN_PROBE_PIN
|
||||
if (READ(Z_MIN_PROBE_PIN)) SBI(current_endstop_bits_local, Z_MIN_PROBE);
|
||||
if (READ(Z_MIN_PROBE_PIN)) SBI(live_state_local, Z_MIN_PROBE);
|
||||
#endif
|
||||
#if HAS_Z2_MIN
|
||||
if (READ(Z2_MIN_PIN)) SBI(current_endstop_bits_local, Z2_MIN);
|
||||
if (READ(Z2_MIN_PIN)) SBI(live_state_local, Z2_MIN);
|
||||
#endif
|
||||
#if HAS_Z2_MAX
|
||||
if (READ(Z2_MAX_PIN)) SBI(current_endstop_bits_local, Z2_MAX);
|
||||
if (READ(Z2_MAX_PIN)) SBI(live_state_local, Z2_MAX);
|
||||
#endif
|
||||
|
||||
uint16_t endstop_change = current_endstop_bits_local ^ old_endstop_bits_local;
|
||||
uint16_t endstop_change = live_state_local ^ old_live_state_local;
|
||||
|
||||
if (endstop_change) {
|
||||
#if HAS_X_MIN
|
||||
if (TEST(endstop_change, X_MIN)) SERIAL_PROTOCOLPAIR(" X_MIN:", !!TEST(current_endstop_bits_local, X_MIN));
|
||||
if (TEST(endstop_change, X_MIN)) SERIAL_PROTOCOLPAIR(" X_MIN:", !!TEST(live_state_local, X_MIN));
|
||||
#endif
|
||||
#if HAS_X_MAX
|
||||
if (TEST(endstop_change, X_MAX)) SERIAL_PROTOCOLPAIR(" X_MAX:", !!TEST(current_endstop_bits_local, X_MAX));
|
||||
if (TEST(endstop_change, X_MAX)) SERIAL_PROTOCOLPAIR(" X_MAX:", !!TEST(live_state_local, X_MAX));
|
||||
#endif
|
||||
#if HAS_Y_MIN
|
||||
if (TEST(endstop_change, Y_MIN)) SERIAL_PROTOCOLPAIR(" Y_MIN:", !!TEST(current_endstop_bits_local, Y_MIN));
|
||||
if (TEST(endstop_change, Y_MIN)) SERIAL_PROTOCOLPAIR(" Y_MIN:", !!TEST(live_state_local, Y_MIN));
|
||||
#endif
|
||||
#if HAS_Y_MAX
|
||||
if (TEST(endstop_change, Y_MAX)) SERIAL_PROTOCOLPAIR(" Y_MAX:", !!TEST(current_endstop_bits_local, Y_MAX));
|
||||
if (TEST(endstop_change, Y_MAX)) SERIAL_PROTOCOLPAIR(" Y_MAX:", !!TEST(live_state_local, Y_MAX));
|
||||
#endif
|
||||
#if HAS_Z_MIN
|
||||
if (TEST(endstop_change, Z_MIN)) SERIAL_PROTOCOLPAIR(" Z_MIN:", !!TEST(current_endstop_bits_local, Z_MIN));
|
||||
if (TEST(endstop_change, Z_MIN)) SERIAL_PROTOCOLPAIR(" Z_MIN:", !!TEST(live_state_local, Z_MIN));
|
||||
#endif
|
||||
#if HAS_Z_MAX
|
||||
if (TEST(endstop_change, Z_MAX)) SERIAL_PROTOCOLPAIR(" Z_MAX:", !!TEST(current_endstop_bits_local, Z_MAX));
|
||||
if (TEST(endstop_change, Z_MAX)) SERIAL_PROTOCOLPAIR(" Z_MAX:", !!TEST(live_state_local, Z_MAX));
|
||||
#endif
|
||||
#if HAS_Z_MIN_PROBE_PIN
|
||||
if (TEST(endstop_change, Z_MIN_PROBE)) SERIAL_PROTOCOLPAIR(" PROBE:", !!TEST(current_endstop_bits_local, Z_MIN_PROBE));
|
||||
if (TEST(endstop_change, Z_MIN_PROBE)) SERIAL_PROTOCOLPAIR(" PROBE:", !!TEST(live_state_local, Z_MIN_PROBE));
|
||||
#endif
|
||||
#if HAS_Z2_MIN
|
||||
if (TEST(endstop_change, Z2_MIN)) SERIAL_PROTOCOLPAIR(" Z2_MIN:", !!TEST(current_endstop_bits_local, Z2_MIN));
|
||||
if (TEST(endstop_change, Z2_MIN)) SERIAL_PROTOCOLPAIR(" Z2_MIN:", !!TEST(live_state_local, Z2_MIN));
|
||||
#endif
|
||||
#if HAS_Z2_MAX
|
||||
if (TEST(endstop_change, Z2_MAX)) SERIAL_PROTOCOLPAIR(" Z2_MAX:", !!TEST(current_endstop_bits_local, Z2_MAX));
|
||||
if (TEST(endstop_change, Z2_MAX)) SERIAL_PROTOCOLPAIR(" Z2_MAX:", !!TEST(live_state_local, Z2_MAX));
|
||||
#endif
|
||||
SERIAL_PROTOCOLPGM("\n\n");
|
||||
analogWrite(LED_PIN, local_LED_status);
|
||||
local_LED_status ^= 255;
|
||||
old_endstop_bits_local = current_endstop_bits_local;
|
||||
old_live_state_local = live_state_local;
|
||||
}
|
||||
}
|
||||
#endif // PINS_DEBUGGING
|
||||
@@ -1784,24 +1777,14 @@ void Temperature::set_current_temp_raw() {
|
||||
* - Step the babysteps value for each axis towards 0
|
||||
* - For PINS_DEBUGGING, monitor and report endstop pins
|
||||
* - For ENDSTOP_INTERRUPTS_FEATURE check endstops if flagged
|
||||
* - Call planner.tick to count down its "ignore" time
|
||||
*/
|
||||
ISR(TIMER0_COMPB_vect) {
|
||||
/**
|
||||
* AVR has no hardware interrupt preemption, so emulate priorization
|
||||
* and preemption of this ISR by all others by disabling the timer
|
||||
* interrupt generation capability and reenabling global interrupts.
|
||||
* Any interrupt can then interrupt this handler and preempt it.
|
||||
* This ISR becomes the lowest priority one so the UART, Endstops
|
||||
* and Stepper ISRs can all preempt it.
|
||||
*/
|
||||
DISABLE_TEMPERATURE_INTERRUPT();
|
||||
sei();
|
||||
HAL_TEMP_TIMER_ISR {
|
||||
HAL_timer_isr_prologue(TEMP_TIMER_NUM);
|
||||
|
||||
Temperature::isr();
|
||||
|
||||
// Disable global interrupts and reenable this ISR
|
||||
cli();
|
||||
ENABLE_TEMPERATURE_INTERRUPT();
|
||||
HAL_timer_isr_epilogue(TEMP_TIMER_NUM);
|
||||
}
|
||||
|
||||
void Temperature::isr() {
|
||||
@@ -2099,13 +2082,6 @@ void Temperature::isr() {
|
||||
* This gives each ADC 0.9765ms to charge up.
|
||||
*/
|
||||
|
||||
#define SET_ADMUX_ADCSRA(pin) ADMUX = _BV(REFS0) | (pin & 0x07); SBI(ADCSRA, ADSC)
|
||||
#ifdef MUX5
|
||||
#define START_ADC(pin) if (pin > 7) ADCSRB = _BV(MUX5); else ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
|
||||
#else
|
||||
#define START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
|
||||
#endif
|
||||
|
||||
switch (adc_sensor_state) {
|
||||
|
||||
case SensorsReady: {
|
||||
@@ -2125,25 +2101,25 @@ void Temperature::isr() {
|
||||
|
||||
#if HAS_TEMP_ADC_0
|
||||
case PrepareTemp_0:
|
||||
START_ADC(TEMP_0_PIN);
|
||||
HAL_START_ADC(TEMP_0_PIN);
|
||||
break;
|
||||
case MeasureTemp_0:
|
||||
raw_temp_value[0] += ADC;
|
||||
raw_temp_value[0] += HAL_READ_ADC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAS_HEATED_BED
|
||||
case PrepareTemp_BED:
|
||||
START_ADC(TEMP_BED_PIN);
|
||||
HAL_START_ADC(TEMP_BED_PIN);
|
||||
break;
|
||||
case MeasureTemp_BED:
|
||||
raw_temp_bed_value += ADC;
|
||||
raw_temp_bed_value += HAL_READ_ADC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_CHAMBER
|
||||
case PrepareTemp_CHAMBER:
|
||||
START_ADC(TEMP_CHAMBER_PIN);
|
||||
HAL_START_ADC(TEMP_CHAMBER_PIN);
|
||||
break;
|
||||
case MeasureTemp_CHAMBER:
|
||||
raw_temp_chamber_value += ADC;
|
||||
@@ -2152,55 +2128,55 @@ void Temperature::isr() {
|
||||
|
||||
#if HAS_TEMP_ADC_1
|
||||
case PrepareTemp_1:
|
||||
START_ADC(TEMP_1_PIN);
|
||||
HAL_START_ADC(TEMP_1_PIN);
|
||||
break;
|
||||
case MeasureTemp_1:
|
||||
raw_temp_value[1] += ADC;
|
||||
raw_temp_value[1] += HAL_READ_ADC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_ADC_2
|
||||
case PrepareTemp_2:
|
||||
START_ADC(TEMP_2_PIN);
|
||||
HAL_START_ADC(TEMP_2_PIN);
|
||||
break;
|
||||
case MeasureTemp_2:
|
||||
raw_temp_value[2] += ADC;
|
||||
raw_temp_value[2] += HAL_READ_ADC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_ADC_3
|
||||
case PrepareTemp_3:
|
||||
START_ADC(TEMP_3_PIN);
|
||||
HAL_START_ADC(TEMP_3_PIN);
|
||||
break;
|
||||
case MeasureTemp_3:
|
||||
raw_temp_value[3] += ADC;
|
||||
raw_temp_value[3] += HAL_READ_ADC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_ADC_4
|
||||
case PrepareTemp_4:
|
||||
START_ADC(TEMP_4_PIN);
|
||||
HAL_START_ADC(TEMP_4_PIN);
|
||||
break;
|
||||
case MeasureTemp_4:
|
||||
raw_temp_value[4] += ADC;
|
||||
raw_temp_value[4] += HAL_READ_ADC;
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if ENABLED(FILAMENT_WIDTH_SENSOR)
|
||||
case Prepare_FILWIDTH:
|
||||
START_ADC(FILWIDTH_PIN);
|
||||
HAL_START_ADC(FILWIDTH_PIN);
|
||||
break;
|
||||
case Measure_FILWIDTH:
|
||||
if (ADC > 102) { // Make sure ADC is reading > 0.5 volts, otherwise don't read.
|
||||
if (HAL_READ_ADC > 102) { // Make sure ADC is reading > 0.5 volts, otherwise don't read.
|
||||
raw_filwidth_value -= (raw_filwidth_value >> 7); // Subtract 1/128th of the raw_filwidth_value
|
||||
raw_filwidth_value += ((unsigned long)ADC << 7); // Add new ADC reading, scaled by 128
|
||||
raw_filwidth_value += ((unsigned long)HAL_READ_ADC << 7); // Add new ADC reading, scaled by 128
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
#if ENABLED(ADC_KEYPAD)
|
||||
case Prepare_ADC_KEY:
|
||||
START_ADC(ADC_KEYPAD_PIN);
|
||||
HAL_START_ADC(ADC_KEYPAD_PIN);
|
||||
break;
|
||||
case Measure_ADC_KEY:
|
||||
if (ADCKey_count < 16) {
|
||||
@@ -2322,26 +2298,11 @@ void Temperature::isr() {
|
||||
}
|
||||
#endif // BABYSTEPPING
|
||||
|
||||
#if ENABLED(PINS_DEBUGGING)
|
||||
extern bool endstop_monitor_flag;
|
||||
// run the endstop monitor at 15Hz
|
||||
static uint8_t endstop_monitor_count = 16; // offset this check from the others
|
||||
if (endstop_monitor_flag) {
|
||||
endstop_monitor_count += _BV(1); // 15 Hz
|
||||
endstop_monitor_count &= 0x7F;
|
||||
if (!endstop_monitor_count) endstop_monitor(); // report changes in endstop status
|
||||
}
|
||||
#endif
|
||||
// Poll endstops state, if required
|
||||
endstops.poll();
|
||||
|
||||
#if ENABLED(ENDSTOP_INTERRUPTS_FEATURE)
|
||||
|
||||
extern volatile uint8_t e_hit;
|
||||
|
||||
if (e_hit && ENDSTOPS_ENABLED) {
|
||||
endstops.update(); // call endstop update routine
|
||||
e_hit--;
|
||||
}
|
||||
#endif
|
||||
// Periodically call the planner timer
|
||||
planner.tick();
|
||||
}
|
||||
|
||||
#if HAS_TEMP_SENSOR
|
||||
|
||||
@@ -106,7 +106,7 @@ enum ADCSensorState : char {
|
||||
// get all oversampled sensor readings
|
||||
#define MIN_ADC_ISR_LOOPS 10
|
||||
|
||||
#define ACTUAL_ADC_SAMPLES max(int(MIN_ADC_ISR_LOOPS), int(SensorsReady))
|
||||
#define ACTUAL_ADC_SAMPLES MAX(int(MIN_ADC_ISR_LOOPS), int(SensorsReady))
|
||||
|
||||
#if HAS_PID_HEATING
|
||||
#define PID_K2 (1.0-PID_K1)
|
||||
@@ -304,6 +304,10 @@ class Temperature {
|
||||
static uint8_t ADCKey_count;
|
||||
#endif
|
||||
|
||||
#if ENABLED(PID_EXTRUSION_SCALING)
|
||||
static int16_t lpq_len;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Instance Methods
|
||||
*/
|
||||
@@ -445,7 +449,7 @@ class Temperature {
|
||||
#endif
|
||||
target_temperature_bed =
|
||||
#ifdef BED_MAXTEMP
|
||||
min(celsius, BED_MAXTEMP)
|
||||
MIN(celsius, BED_MAXTEMP)
|
||||
#else
|
||||
celsius
|
||||
#endif
|
||||
@@ -468,7 +472,7 @@ class Temperature {
|
||||
#endif
|
||||
|
||||
FORCE_INLINE static bool wait_for_heating(const uint8_t e) {
|
||||
return degTargetHotend(e) > TEMP_HYSTERESIS && abs(degHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS;
|
||||
return degTargetHotend(e) > TEMP_HYSTERESIS && ABS(degHotend(e) - degTargetHotend(e)) > TEMP_HYSTERESIS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -132,7 +132,7 @@
|
||||
#define _TT_NAME(_N) temptable_ ## _N
|
||||
#define TT_NAME(_N) _TT_NAME(_N)
|
||||
|
||||
#ifdef THERMISTORHEATER_0
|
||||
#if THERMISTORHEATER_0
|
||||
#define HEATER_0_TEMPTABLE TT_NAME(THERMISTORHEATER_0)
|
||||
#define HEATER_0_TEMPTABLE_LEN COUNT(HEATER_0_TEMPTABLE)
|
||||
#elif defined(HEATER_0_USES_THERMISTOR)
|
||||
@@ -142,7 +142,7 @@
|
||||
#define HEATER_0_TEMPTABLE_LEN 0
|
||||
#endif
|
||||
|
||||
#ifdef THERMISTORHEATER_1
|
||||
#if THERMISTORHEATER_1
|
||||
#define HEATER_1_TEMPTABLE TT_NAME(THERMISTORHEATER_1)
|
||||
#define HEATER_1_TEMPTABLE_LEN COUNT(HEATER_1_TEMPTABLE)
|
||||
#elif defined(HEATER_1_USES_THERMISTOR)
|
||||
@@ -152,7 +152,7 @@
|
||||
#define HEATER_1_TEMPTABLE_LEN 0
|
||||
#endif
|
||||
|
||||
#ifdef THERMISTORHEATER_2
|
||||
#if THERMISTORHEATER_2
|
||||
#define HEATER_2_TEMPTABLE TT_NAME(THERMISTORHEATER_2)
|
||||
#define HEATER_2_TEMPTABLE_LEN COUNT(HEATER_2_TEMPTABLE)
|
||||
#elif defined(HEATER_2_USES_THERMISTOR)
|
||||
@@ -162,7 +162,7 @@
|
||||
#define HEATER_2_TEMPTABLE_LEN 0
|
||||
#endif
|
||||
|
||||
#ifdef THERMISTORHEATER_3
|
||||
#if THERMISTORHEATER_3
|
||||
#define HEATER_3_TEMPTABLE TT_NAME(THERMISTORHEATER_3)
|
||||
#define HEATER_3_TEMPTABLE_LEN COUNT(HEATER_3_TEMPTABLE)
|
||||
#elif defined(HEATER_3_USES_THERMISTOR)
|
||||
@@ -172,7 +172,7 @@
|
||||
#define HEATER_3_TEMPTABLE_LEN 0
|
||||
#endif
|
||||
|
||||
#ifdef THERMISTORHEATER_4
|
||||
#if THERMISTORHEATER_4
|
||||
#define HEATER_4_TEMPTABLE TT_NAME(THERMISTORHEATER_4)
|
||||
#define HEATER_4_TEMPTABLE_LEN COUNT(HEATER_4_TEMPTABLE)
|
||||
#elif defined(HEATER_4_USES_THERMISTOR)
|
||||
@@ -186,7 +186,7 @@
|
||||
#define BEDTEMPTABLE TT_NAME(THERMISTORBED)
|
||||
#define BEDTEMPTABLE_LEN COUNT(BEDTEMPTABLE)
|
||||
#else
|
||||
#ifdef BED_USES_THERMISTOR
|
||||
#ifdef HEATER_BED_USES_THERMISTOR
|
||||
#error "No bed thermistor table specified"
|
||||
#endif
|
||||
#endif
|
||||
@@ -195,7 +195,7 @@
|
||||
#define CHAMBERTEMPTABLE TT_NAME(THERMISTORCHAMBER)
|
||||
#define CHAMBERTEMPTABLE_LEN COUNT(CHAMBERTEMPTABLE)
|
||||
#else
|
||||
#ifdef CHAMBER_USES_THERMISTOR
|
||||
#ifdef HEATER_CHAMBER_USES_THERMISTOR
|
||||
#error "No chamber thermistor table specified"
|
||||
#endif
|
||||
#endif
|
||||
@@ -249,7 +249,7 @@
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_BED_RAW_HI_TEMP
|
||||
#ifdef BED_USES_THERMISTOR
|
||||
#ifdef HEATER_BED_USES_THERMISTOR
|
||||
#define HEATER_BED_RAW_HI_TEMP 0
|
||||
#define HEATER_BED_RAW_LO_TEMP 16383
|
||||
#else
|
||||
@@ -258,7 +258,7 @@
|
||||
#endif
|
||||
#endif
|
||||
#ifndef HEATER_CHAMBER_RAW_HI_TEMP
|
||||
#ifdef CHAMBER_USES_THERMISTOR
|
||||
#ifdef HEATER_CHAMBER_USES_THERMISTOR
|
||||
#define HEATER_CHAMBER_RAW_HI_TEMP 0
|
||||
#define HEATER_CHAMBER_RAW_LO_TEMP 16383
|
||||
#else
|
||||
|
||||
+3
-3
@@ -53,7 +53,7 @@ void tmc_get_current(TMC &st, const TMC_AxisEnum axis) {
|
||||
_tmc_say_current(axis, st.getCurrent());
|
||||
}
|
||||
template<typename TMC>
|
||||
void tmc_set_current(TMC &st, const TMC_AxisEnum axis, const int mA) {
|
||||
void tmc_set_current(TMC &st, const int mA) {
|
||||
st.setCurrent(mA, R_SENSE, HOLD_MULTIPLIER);
|
||||
}
|
||||
template<typename TMC>
|
||||
@@ -70,7 +70,7 @@ void tmc_get_pwmthrs(TMC &st, const TMC_AxisEnum axis, const uint16_t spmm) {
|
||||
_tmc_say_pwmthrs(axis, _tmc_thrs(st.microsteps(), st.TPWMTHRS(), spmm));
|
||||
}
|
||||
template<typename TMC>
|
||||
void tmc_set_pwmthrs(TMC &st, const TMC_AxisEnum axis, const int32_t thrs, const uint32_t spmm) {
|
||||
void tmc_set_pwmthrs(TMC &st, const int32_t thrs, const uint32_t spmm) {
|
||||
st.TPWMTHRS(_tmc_thrs(st.microsteps(), thrs, spmm));
|
||||
}
|
||||
template<typename TMC>
|
||||
@@ -78,7 +78,7 @@ void tmc_get_sgt(TMC &st, const TMC_AxisEnum axis) {
|
||||
_tmc_say_sgt(axis, st.sgt());
|
||||
}
|
||||
template<typename TMC>
|
||||
void tmc_set_sgt(TMC &st, const TMC_AxisEnum axis, const int8_t sgt_val) {
|
||||
void tmc_set_sgt(TMC &st, const int8_t sgt_val) {
|
||||
st.sgt(sgt_val);
|
||||
}
|
||||
|
||||
|
||||
+10
-17
@@ -61,7 +61,6 @@ extern uint8_t ubl_cnt;
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if ENABLED(ULTRA_LCD)
|
||||
extern char lcd_status_message[];
|
||||
void lcd_quick_feedback(const bool clear_buttons);
|
||||
#endif
|
||||
|
||||
@@ -235,7 +234,7 @@ class unified_bed_leveling {
|
||||
const float xratio = (rx0 - mesh_index_to_xpos(x1_i)) * (1.0 / (MESH_X_DIST)),
|
||||
z1 = z_values[x1_i][yi];
|
||||
|
||||
return z1 + xratio * (z_values[min(x1_i, GRID_MAX_POINTS_X - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
|
||||
return z1 + xratio * (z_values[MIN(x1_i, GRID_MAX_POINTS_X - 2) + 1][yi] - z1); // Don't allow x1_i+1 to be past the end of the array
|
||||
// If it is, it is clamped to the last element of the
|
||||
// z_values[][] array and no correction is applied.
|
||||
}
|
||||
@@ -269,7 +268,7 @@ class unified_bed_leveling {
|
||||
const float yratio = (ry0 - mesh_index_to_ypos(y1_i)) * (1.0 / (MESH_Y_DIST)),
|
||||
z1 = z_values[xi][y1_i];
|
||||
|
||||
return z1 + yratio * (z_values[xi][min(y1_i, GRID_MAX_POINTS_Y - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
|
||||
return z1 + yratio * (z_values[xi][MIN(y1_i, GRID_MAX_POINTS_Y - 2) + 1] - z1); // Don't allow y1_i+1 to be past the end of the array
|
||||
// If it is, it is clamped to the last element of the
|
||||
// z_values[][] array and no correction is applied.
|
||||
}
|
||||
@@ -295,11 +294,11 @@ class unified_bed_leveling {
|
||||
|
||||
const float z1 = calc_z0(rx0,
|
||||
mesh_index_to_xpos(cx), z_values[cx][cy],
|
||||
mesh_index_to_xpos(cx + 1), z_values[min(cx, GRID_MAX_POINTS_X - 2) + 1][cy]);
|
||||
mesh_index_to_xpos(cx + 1), z_values[MIN(cx, GRID_MAX_POINTS_X - 2) + 1][cy]);
|
||||
|
||||
const float z2 = calc_z0(rx0,
|
||||
mesh_index_to_xpos(cx), z_values[cx][min(cy, GRID_MAX_POINTS_Y - 2) + 1],
|
||||
mesh_index_to_xpos(cx + 1), z_values[min(cx, GRID_MAX_POINTS_X - 2) + 1][min(cy, GRID_MAX_POINTS_Y - 2) + 1]);
|
||||
mesh_index_to_xpos(cx), z_values[cx][MIN(cy, GRID_MAX_POINTS_Y - 2) + 1],
|
||||
mesh_index_to_xpos(cx + 1), z_values[MIN(cx, GRID_MAX_POINTS_X - 2) + 1][MIN(cy, GRID_MAX_POINTS_Y - 2) + 1]);
|
||||
|
||||
float z0 = calc_z0(ry0,
|
||||
mesh_index_to_ypos(cy), z1,
|
||||
@@ -356,17 +355,11 @@ class unified_bed_leveling {
|
||||
static void line_to_destination_cartesian(const float &fr, const uint8_t e);
|
||||
#endif
|
||||
|
||||
#define _CMPZ(a,b) (z_values[a][b] == z_values[a][b+1])
|
||||
#define CMPZ(a) (_CMPZ(a, 0) && _CMPZ(a, 1))
|
||||
#define ZZER(a) (z_values[a][0] == 0)
|
||||
|
||||
FORCE_INLINE bool mesh_is_valid() {
|
||||
return !(
|
||||
( CMPZ(0) && CMPZ(1) && CMPZ(2) // adjacent z values all equal?
|
||||
&& ZZER(0) && ZZER(1) && ZZER(2) // all zero at the edge?
|
||||
)
|
||||
|| isnan(z_values[0][0])
|
||||
);
|
||||
inline static bool mesh_is_valid() {
|
||||
for (uint8_t x = 0; x < GRID_MAX_POINTS_X; x++)
|
||||
for (uint8_t y = 0; y < GRID_MAX_POINTS_Y; y++)
|
||||
if (isnan(z_values[x][y])) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // class unified_bed_leveling
|
||||
|
||||
+10
-10
@@ -446,7 +446,7 @@
|
||||
|
||||
if (parser.seen('B')) {
|
||||
g29_card_thickness = parser.has_value() ? parser.value_float() : measure_business_card_thickness((float) Z_CLEARANCE_BETWEEN_PROBES);
|
||||
if (FABS(g29_card_thickness) > 1.5) {
|
||||
if (ABS(g29_card_thickness) > 1.5) {
|
||||
SERIAL_PROTOCOLLNPGM("?Error in Business Card measurement.");
|
||||
return;
|
||||
}
|
||||
@@ -791,8 +791,8 @@
|
||||
save_ubl_active_state_and_disable(); // Disable bed level correction for probing
|
||||
|
||||
do_blocking_move_to(0.5 * (MESH_MAX_X - (MESH_MIN_X)), 0.5 * (MESH_MAX_Y - (MESH_MIN_Y)), in_height);
|
||||
//, min(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]) / 2.0);
|
||||
stepper.synchronize();
|
||||
//, MIN(planner.max_feedrate_mm_s[X_AXIS], planner.max_feedrate_mm_s[Y_AXIS]) / 2.0);
|
||||
planner.synchronize();
|
||||
|
||||
SERIAL_PROTOCOLPGM("Place shim under nozzle");
|
||||
LCD_MESSAGEPGM(MSG_UBL_BC_INSERT);
|
||||
@@ -801,7 +801,7 @@
|
||||
|
||||
const float z1 = measure_point_with_encoder();
|
||||
do_blocking_move_to_z(current_position[Z_AXIS] + SIZE_OF_LITTLE_RAISE);
|
||||
stepper.synchronize();
|
||||
planner.synchronize();
|
||||
|
||||
SERIAL_PROTOCOLPGM("Remove shim");
|
||||
LCD_MESSAGEPGM(MSG_UBL_BC_REMOVE);
|
||||
@@ -811,7 +811,7 @@
|
||||
|
||||
do_blocking_move_to_z(current_position[Z_AXIS] + Z_CLEARANCE_BETWEEN_PROBES);
|
||||
|
||||
const float thickness = abs(z1 - z2);
|
||||
const float thickness = ABS(z1 - z2);
|
||||
|
||||
if (g29_verbose_level > 1) {
|
||||
SERIAL_PROTOCOLPGM("Business Card is ");
|
||||
@@ -1494,10 +1494,10 @@
|
||||
#include "vector_3.h"
|
||||
|
||||
void unified_bed_leveling::tilt_mesh_based_on_probed_grid(const bool do_3_pt_leveling) {
|
||||
constexpr int16_t x_min = max(MIN_PROBE_X, MESH_MIN_X),
|
||||
x_max = min(MAX_PROBE_X, MESH_MAX_X),
|
||||
y_min = max(MIN_PROBE_Y, MESH_MIN_Y),
|
||||
y_max = min(MAX_PROBE_Y, MESH_MAX_Y);
|
||||
constexpr int16_t x_min = MAX(MIN_PROBE_X, MESH_MIN_X),
|
||||
x_max = MIN(MAX_PROBE_X, MESH_MAX_X),
|
||||
y_min = MAX(MIN_PROBE_Y, MESH_MIN_Y),
|
||||
y_max = MIN(MAX_PROBE_Y, MESH_MAX_Y);
|
||||
|
||||
bool abort_flag = false;
|
||||
|
||||
@@ -1765,7 +1765,7 @@
|
||||
|
||||
SERIAL_ECHOPGM("Extrapolating mesh...");
|
||||
|
||||
const float weight_scaled = weight_factor * max(MESH_X_DIST, MESH_Y_DIST);
|
||||
const float weight_scaled = weight_factor * MAX(MESH_X_DIST, MESH_Y_DIST);
|
||||
|
||||
for (uint8_t jx = 0; jx < GRID_MAX_POINTS_X; jx++)
|
||||
for (uint8_t jy = 0; jy < GRID_MAX_POINTS_Y; jy++)
|
||||
|
||||
+13
-10
@@ -257,7 +257,8 @@
|
||||
z_position = end[Z_AXIS];
|
||||
}
|
||||
|
||||
planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder);
|
||||
if (!planner.buffer_segment(rx, ry, z_position + z0, e_position, feed_rate, extruder))
|
||||
break;
|
||||
} //else printf("FIRST MOVE PRUNED ");
|
||||
}
|
||||
|
||||
@@ -314,7 +315,8 @@
|
||||
e_position = end[E_AXIS];
|
||||
z_position = end[Z_AXIS];
|
||||
}
|
||||
planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder);
|
||||
if (!planner.buffer_segment(rx, next_mesh_line_y, z_position + z0, e_position, feed_rate, extruder))
|
||||
break;
|
||||
current_yi += dyi;
|
||||
yi_cnt--;
|
||||
}
|
||||
@@ -337,7 +339,8 @@
|
||||
z_position = end[Z_AXIS];
|
||||
}
|
||||
|
||||
planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder);
|
||||
if (!planner.buffer_segment(next_mesh_line_x, ry, z_position + z0, e_position, feed_rate, extruder))
|
||||
break;
|
||||
current_xi += dxi;
|
||||
xi_cnt--;
|
||||
}
|
||||
@@ -366,7 +369,7 @@
|
||||
inline void _O2 ubl_buffer_segment_raw(const float (&in_raw)[XYZE], const float &fr) {
|
||||
|
||||
#if ENABLED(SKEW_CORRECTION)
|
||||
float raw[XYZE] = { in_raw[X_AXIS], in_raw[Y_AXIS], in_raw[Z_AXIS], in_raw[E_AXIS] };
|
||||
float raw[XYZE] = { in_raw[X_AXIS], in_raw[Y_AXIS], in_raw[Z_AXIS] };
|
||||
planner.skew(raw[X_AXIS], raw[Y_AXIS], raw[Z_AXIS]);
|
||||
#else
|
||||
const float (&raw)[XYZE] = in_raw;
|
||||
@@ -382,11 +385,11 @@
|
||||
inverse_kinematics(raw); // this writes delta[ABC] from raw[XYZE]
|
||||
// should move the feedrate scaling to scara inverse_kinematics
|
||||
|
||||
const float adiff = FABS(delta[A_AXIS] - scara_oldA),
|
||||
bdiff = FABS(delta[B_AXIS] - scara_oldB);
|
||||
const float adiff = ABS(delta[A_AXIS] - scara_oldA),
|
||||
bdiff = ABS(delta[B_AXIS] - scara_oldB);
|
||||
scara_oldA = delta[A_AXIS];
|
||||
scara_oldB = delta[B_AXIS];
|
||||
float s_feedrate = max(adiff, bdiff) * scara_feed_factor;
|
||||
float s_feedrate = MAX(adiff, bdiff) * scara_feed_factor;
|
||||
|
||||
planner.buffer_segment(delta[A_AXIS], delta[B_AXIS], delta[C_AXIS], in_raw[E_AXIS], s_feedrate, active_extruder);
|
||||
|
||||
@@ -438,13 +441,13 @@
|
||||
uint16_t segments = lroundf(cartesian_xy_mm * (1.0 / (DELTA_SEGMENT_MIN_LENGTH))); // cartesian fixed segment length
|
||||
#endif
|
||||
|
||||
NOLESS(segments, 1); // must have at least one segment
|
||||
NOLESS(segments, 1U); // must have at least one segment
|
||||
const float inv_segments = 1.0 / segments; // divide once, multiply thereafter
|
||||
|
||||
#if IS_SCARA // scale the feed rate from mm/s to degrees/s
|
||||
scara_feed_factor = cartesian_xy_mm * inv_segments * feedrate;
|
||||
scara_oldA = stepper.get_axis_position_degrees(A_AXIS);
|
||||
scara_oldB = stepper.get_axis_position_degrees(B_AXIS);
|
||||
scara_oldA = planner.get_axis_position_degrees(A_AXIS);
|
||||
scara_oldB = planner.get_axis_position_degrees(B_AXIS);
|
||||
#endif
|
||||
|
||||
const float diff[XYZE] = {
|
||||
|
||||
+77
-105
@@ -71,7 +71,7 @@
|
||||
#else
|
||||
#define MAX_MESSAGE_LENGTH CHARSIZE * 2 * (LCD_WIDTH)
|
||||
#endif
|
||||
uint8_t status_scroll_pos = 0;
|
||||
uint8_t status_scroll_offset = 0;
|
||||
#else
|
||||
#define MAX_MESSAGE_LENGTH CHARSIZE * (LCD_WIDTH)
|
||||
#endif
|
||||
@@ -95,8 +95,7 @@ uint8_t lcd_status_update_delay = 1, // First update one loop delayed
|
||||
#if ENABLED(DOGLCD)
|
||||
#include "ultralcd_impl_DOGM.h"
|
||||
#include <U8glib.h>
|
||||
bool drawing_screen, // = false
|
||||
first_page;
|
||||
bool drawing_screen, first_page; // = false
|
||||
#else
|
||||
#include "ultralcd_impl_HD44780.h"
|
||||
constexpr bool first_page = true;
|
||||
@@ -493,6 +492,11 @@ uint16_t max_display_update_time = 0;
|
||||
void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder/*=0*/) {
|
||||
if (currentScreen != screen) {
|
||||
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
// Shadow for editing the fade height
|
||||
new_z_fade_height = planner.z_fade_height;
|
||||
#endif
|
||||
|
||||
#if ENABLED(DOUBLECLICK_FOR_Z_BABYSTEPPING) && ENABLED(BABYSTEPPING)
|
||||
static millis_t doubleclick_expire_ms = 0;
|
||||
// Going to lcd_main_menu from status screen? Remember first click time.
|
||||
@@ -501,7 +505,7 @@ uint16_t max_display_update_time = 0;
|
||||
if (currentScreen == lcd_status_screen)
|
||||
doubleclick_expire_ms = millis() + DOUBLECLICK_MAX_INTERVAL;
|
||||
}
|
||||
else if (screen == lcd_status_screen && currentScreen == lcd_main_menu && PENDING(millis(), doubleclick_expire_ms))
|
||||
else if (screen == lcd_status_screen && currentScreen == lcd_main_menu && PENDING(millis(), doubleclick_expire_ms) && (planner.movesplanned() || IS_SD_PRINTING))
|
||||
screen =
|
||||
#if ENABLED(BABYSTEP_ZPROBE_OFFSET)
|
||||
lcd_babystep_zoffset
|
||||
@@ -559,7 +563,7 @@ uint16_t max_display_update_time = 0;
|
||||
no_reentry = true;
|
||||
const screenFunc_t old_screen = currentScreen;
|
||||
lcd_goto_screen(_lcd_synchronize);
|
||||
stepper.synchronize(); // idle() is called until moves complete
|
||||
planner.synchronize(); // idle() is called until moves complete
|
||||
no_reentry = false;
|
||||
lcd_goto_screen(old_screen);
|
||||
}
|
||||
@@ -618,7 +622,7 @@ uint16_t max_display_update_time = 0;
|
||||
screen_changed = false;
|
||||
}
|
||||
if (screen_items > 0 && encoderLine >= screen_items - limit) {
|
||||
encoderLine = max(0, screen_items - limit);
|
||||
encoderLine = MAX(0, screen_items - limit);
|
||||
encoderPosition = encoderLine * (ENCODER_STEPS_PER_MENU_ITEM);
|
||||
}
|
||||
if (is_menu) {
|
||||
@@ -1067,13 +1071,6 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
*
|
||||
*/
|
||||
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
void _lcd_goto_tune_menu() {
|
||||
lcd_goto_screen(lcd_tune_menu);
|
||||
new_z_fade_height = planner.z_fade_height;
|
||||
}
|
||||
#endif
|
||||
|
||||
void lcd_main_menu() {
|
||||
START_MENU();
|
||||
MENU_BACK(MSG_WATCH);
|
||||
@@ -1100,18 +1097,11 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
MENU_ITEM_EDIT_CALLBACK(bool, MSG_CASE_LIGHT, (bool*)&case_light_on, update_case_light);
|
||||
#endif
|
||||
|
||||
if (planner.movesplanned() || IS_SD_PRINTING) {
|
||||
MENU_ITEM(submenu, MSG_TUNE,
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
_lcd_goto_tune_menu
|
||||
#else
|
||||
lcd_tune_menu
|
||||
#endif
|
||||
);
|
||||
}
|
||||
else {
|
||||
if (planner.movesplanned() || IS_SD_PRINTING)
|
||||
MENU_ITEM(submenu, MSG_TUNE, lcd_tune_menu);
|
||||
else
|
||||
MENU_ITEM(submenu, MSG_PREPARE, lcd_prepare_menu);
|
||||
}
|
||||
|
||||
MENU_ITEM(submenu, MSG_CONTROL, lcd_control_menu);
|
||||
|
||||
#if ENABLED(SDSUPPORT)
|
||||
@@ -1353,7 +1343,6 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
// First Fan Speed title in "Tune" and "Control>Temperature" menus
|
||||
#if FAN_COUNT > 0 && HAS_FAN0
|
||||
#if FAN_COUNT > 1
|
||||
@@ -1577,7 +1566,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
*
|
||||
*/
|
||||
void _lcd_preheat(const int16_t endnum, const int16_t temph, const int16_t tempb, const int16_t fan) {
|
||||
if (temph > 0) thermalManager.setTargetHotend(min(heater_maxtemp[endnum], temph), endnum);
|
||||
if (temph > 0) thermalManager.setTargetHotend(MIN(heater_maxtemp[endnum], temph), endnum);
|
||||
#if HAS_HEATED_BED
|
||||
if (tempb >= 0) thermalManager.setTargetBed(tempb);
|
||||
#else
|
||||
@@ -1682,7 +1671,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
void lcd_preheat_m2_bedonly() { _lcd_preheat(0, 0, lcd_preheat_bed_temp[1], lcd_preheat_fan_speed[1]); }
|
||||
#endif
|
||||
|
||||
#if HAS_TEMP_HOTEND && (TEMP_SENSOR_1 != 0 || TEMP_SENSOR_2 != 0 || TEMP_SENSOR_3 != 0 || TEMP_SENSOR_4 != 0 || HAS_HEATED_BED)
|
||||
#if HAS_TEMP_HOTEND || HAS_HEATED_BED
|
||||
|
||||
void lcd_preheat_m1_menu() {
|
||||
START_MENU();
|
||||
@@ -1694,7 +1683,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
#else
|
||||
MENU_ITEM(function, MSG_PREHEAT_1, lcd_preheat_m1_e0_only);
|
||||
#endif
|
||||
#else
|
||||
#elif HOTENDS > 1
|
||||
#if HAS_HEATED_BED
|
||||
MENU_ITEM(function, MSG_PREHEAT_1_N MSG_H1, lcd_preheat_m1_e0);
|
||||
MENU_ITEM(function, MSG_PREHEAT_1_END " " MSG_E1, lcd_preheat_m1_e0_only);
|
||||
@@ -1746,7 +1735,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
#else
|
||||
MENU_ITEM(function, MSG_PREHEAT_2, lcd_preheat_m2_e0_only);
|
||||
#endif
|
||||
#else
|
||||
#elif HOTENDS > 1
|
||||
#if HAS_HEATED_BED
|
||||
MENU_ITEM(function, MSG_PREHEAT_2_N MSG_H1, lcd_preheat_m2_e0);
|
||||
MENU_ITEM(function, MSG_PREHEAT_2_END " " MSG_E1, lcd_preheat_m2_e0_only);
|
||||
@@ -1788,7 +1777,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
END_MENU();
|
||||
}
|
||||
|
||||
#endif // TEMP_SENSOR_0 && (TEMP_SENSOR_1 || TEMP_SENSOR_2 || TEMP_SENSOR_3 || TEMP_SENSOR_4 || TEMP_SENSOR_BED)
|
||||
#endif // HAS_TEMP_HOTEND || HAS_HEATED_BED
|
||||
|
||||
void lcd_cooldown() {
|
||||
#if FAN_COUNT > 0
|
||||
@@ -2055,13 +2044,6 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
|
||||
void _lcd_ubl_level_bed();
|
||||
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
void _lcd_goto_ubl_level_bed() {
|
||||
lcd_goto_screen(_lcd_ubl_level_bed);
|
||||
new_z_fade_height = planner.z_fade_height;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int16_t ubl_storage_slot = 0,
|
||||
custom_hotend_temp = 190,
|
||||
side_points = 3,
|
||||
@@ -2116,7 +2098,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
char UBL_LCD_GCODE[16];
|
||||
const int ind = ubl_height_amount > 0 ? 9 : 10;
|
||||
strcpy_P(UBL_LCD_GCODE, PSTR("G29 P6 C -"));
|
||||
sprintf_P(&UBL_LCD_GCODE[ind], PSTR(".%i"), abs(ubl_height_amount));
|
||||
sprintf_P(&UBL_LCD_GCODE[ind], PSTR(".%i"), ABS(ubl_height_amount));
|
||||
lcd_enqueue_command(UBL_LCD_GCODE);
|
||||
}
|
||||
|
||||
@@ -2416,12 +2398,10 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
|
||||
void _lcd_do_nothing() {}
|
||||
void _lcd_hard_stop() {
|
||||
stepper.quick_stop();
|
||||
const screenFunc_t old_screen = currentScreen;
|
||||
currentScreen = _lcd_do_nothing;
|
||||
while (planner.movesplanned()) idle();
|
||||
planner.quick_stop();
|
||||
currentScreen = old_screen;
|
||||
stepper.cleaning_buffer_counter = 0;
|
||||
set_current_from_steppers_for_axis(ALL_AXES);
|
||||
sync_plan_position();
|
||||
}
|
||||
@@ -2438,7 +2418,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
if (encoderPosition) {
|
||||
step_scaler += (int32_t)encoderPosition;
|
||||
x_plot += step_scaler / (ENCODER_STEPS_PER_MENU_ITEM);
|
||||
if (abs(step_scaler) >= ENCODER_STEPS_PER_MENU_ITEM) step_scaler = 0;
|
||||
if (ABS(step_scaler) >= ENCODER_STEPS_PER_MENU_ITEM) step_scaler = 0;
|
||||
encoderPosition = 0;
|
||||
lcdDrawUpdate = LCDVIEW_REDRAW_NOW;
|
||||
}
|
||||
@@ -2660,13 +2640,6 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
END_MENU();
|
||||
}
|
||||
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
void _lcd_goto_bed_leveling() {
|
||||
lcd_goto_screen(lcd_bed_leveling);
|
||||
new_z_fade_height = planner.z_fade_height;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LCD_BED_LEVELING
|
||||
|
||||
/**
|
||||
@@ -2706,29 +2679,14 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
//
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
|
||||
MENU_ITEM(submenu, MSG_UBL_LEVEL_BED, (
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
_lcd_goto_ubl_level_bed
|
||||
#else
|
||||
_lcd_ubl_level_bed
|
||||
#endif
|
||||
)
|
||||
);
|
||||
MENU_ITEM(submenu, MSG_UBL_LEVEL_BED, _lcd_ubl_level_bed);
|
||||
|
||||
#elif ENABLED(LCD_BED_LEVELING)
|
||||
|
||||
#if ENABLED(PROBE_MANUALLY)
|
||||
if (!g29_in_progress)
|
||||
#endif
|
||||
|
||||
MENU_ITEM(submenu, MSG_BED_LEVELING, (
|
||||
#if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
|
||||
_lcd_goto_bed_leveling
|
||||
#else
|
||||
lcd_bed_leveling
|
||||
#endif
|
||||
)
|
||||
);
|
||||
MENU_ITEM(submenu, MSG_BED_LEVELING, lcd_bed_leveling);
|
||||
|
||||
#elif PLANNER_LEVELING && DISABLED(SLIM_LCD_MENUS)
|
||||
|
||||
@@ -2850,7 +2808,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
do_blocking_move_to_xy(rx, ry);
|
||||
|
||||
lcd_synchronize();
|
||||
move_menu_scale = max(PROBE_MANUALLY_STEP, MIN_STEPS_PER_SEGMENT / float(DEFAULT_XYZ_STEPS_PER_UNIT));
|
||||
move_menu_scale = MAX(PROBE_MANUALLY_STEP, MIN_STEPS_PER_SEGMENT / float(DEFAULT_XYZ_STEPS_PER_UNIT));
|
||||
lcd_goto_screen(lcd_move_z);
|
||||
}
|
||||
|
||||
@@ -3265,7 +3223,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
else
|
||||
MENU_ITEM(gcode, MSG_AUTO_HOME, PSTR("G28"));
|
||||
|
||||
#if ENABLED(SWITCHING_EXTRUDER)
|
||||
#if ENABLED(SWITCHING_EXTRUDER) || ENABLED(SWITCHING_NOZZLE)
|
||||
|
||||
#if EXTRUDERS == 4
|
||||
switch (active_extruder) {
|
||||
@@ -3330,7 +3288,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
lcd_completion_feedback();
|
||||
}
|
||||
|
||||
#if ENABLED(EEPROM_SETTINGS)
|
||||
#if ENABLED(EEPROM_SETTINGS) && DISABLED(SLIM_LCD_MENUS)
|
||||
|
||||
static void lcd_init_eeprom() {
|
||||
lcd_completion_feedback(settings.init_eeprom());
|
||||
@@ -3539,7 +3497,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
//
|
||||
// Autotemp, Min, Max, Fact
|
||||
//
|
||||
#if ENABLED(AUTOTEMP) && (HAS_TEMP_HOTEND)
|
||||
#if ENABLED(AUTOTEMP) && HAS_TEMP_HOTEND
|
||||
MENU_ITEM_EDIT(bool, MSG_AUTOTEMP, &planner.autotemp_enabled);
|
||||
MENU_ITEM_EDIT(float3, MSG_MIN, &planner.autotemp_min, 0, HEATER_0_MAXTEMP - 15);
|
||||
MENU_ITEM_EDIT(float3, MSG_MAX, &planner.autotemp_max, 0, HEATER_0_MAXTEMP - 15);
|
||||
@@ -3625,8 +3583,8 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
#define MINTEMP_ALL MIN3(HEATER_0_MINTEMP, HEATER_1_MINTEMP, HEATER_2_MINTEMP)
|
||||
#define MAXTEMP_ALL MAX3(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP, HEATER_2_MAXTEMP)
|
||||
#elif HOTENDS > 1
|
||||
#define MINTEMP_ALL min(HEATER_0_MINTEMP, HEATER_1_MINTEMP)
|
||||
#define MAXTEMP_ALL max(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP)
|
||||
#define MINTEMP_ALL MIN(HEATER_0_MINTEMP, HEATER_1_MINTEMP)
|
||||
#define MAXTEMP_ALL MAX(HEATER_0_MAXTEMP, HEATER_1_MAXTEMP)
|
||||
#else
|
||||
#define MINTEMP_ALL HEATER_0_MINTEMP
|
||||
#define MAXTEMP_ALL HEATER_0_MAXTEMP
|
||||
@@ -3854,7 +3812,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
|
||||
// M540 S - Abort on endstop hit when SD printing
|
||||
#if ENABLED(ABORT_ON_ENDSTOP_HIT_FEATURE_ENABLED)
|
||||
MENU_ITEM_EDIT(bool, MSG_ENDSTOP_ABORT, &stepper.abort_on_endstop_hit);
|
||||
MENU_ITEM_EDIT(bool, MSG_ENDSTOP_ABORT, &planner.abort_on_endstop_hit);
|
||||
#endif
|
||||
|
||||
END_MENU();
|
||||
@@ -4867,7 +4825,7 @@ void lcd_quick_feedback(const bool clear_buttons) {
|
||||
callbackFunc = callback; \
|
||||
liveEdit = live; \
|
||||
} \
|
||||
typedef void _name
|
||||
typedef void _name##_void
|
||||
|
||||
DEFINE_MENU_EDIT_TYPE(int16_t, int3, itostr3, 1);
|
||||
DEFINE_MENU_EDIT_TYPE(uint8_t, int8, i8tostr3, 1);
|
||||
@@ -5081,7 +5039,7 @@ void lcd_init() {
|
||||
int16_t lcd_strlen(const char* s) {
|
||||
int16_t i = 0, j = 0;
|
||||
while (s[i]) {
|
||||
if (PRINTABLE(s[i])) j++;
|
||||
if (START_OF_UTF8_CHAR(s[i])) j++;
|
||||
i++;
|
||||
}
|
||||
return j;
|
||||
@@ -5090,7 +5048,7 @@ int16_t lcd_strlen(const char* s) {
|
||||
int16_t lcd_strlen_P(const char* s) {
|
||||
int16_t j = 0;
|
||||
while (pgm_read_byte(s)) {
|
||||
if (PRINTABLE(pgm_read_byte(s))) j++;
|
||||
if (START_OF_UTF8_CHAR(pgm_read_byte(s))) j++;
|
||||
s++;
|
||||
}
|
||||
return j;
|
||||
@@ -5247,7 +5205,7 @@ void lcd_update() {
|
||||
|
||||
#endif
|
||||
|
||||
const bool encoderPastThreshold = (abs(encoderDiff) >= ENCODER_PULSES_PER_STEP);
|
||||
const bool encoderPastThreshold = (ABS(encoderDiff) >= ENCODER_PULSES_PER_STEP);
|
||||
if (encoderPastThreshold || lcd_clicked) {
|
||||
if (encoderPastThreshold) {
|
||||
int32_t encoderMultiplier = 1;
|
||||
@@ -5255,7 +5213,7 @@ void lcd_update() {
|
||||
#if ENABLED(ENCODER_RATE_MULTIPLIER)
|
||||
|
||||
if (encoderRateMultiplierEnabled) {
|
||||
int32_t encoderMovementSteps = abs(encoderDiff) / ENCODER_PULSES_PER_STEP;
|
||||
int32_t encoderMovementSteps = ABS(encoderDiff) / ENCODER_PULSES_PER_STEP;
|
||||
|
||||
if (lastEncoderMovementMillis) {
|
||||
// Note that the rate is always calculated between two passes through the
|
||||
@@ -5418,30 +5376,8 @@ void lcd_update() {
|
||||
} // ELAPSED(ms, next_lcd_update_ms)
|
||||
}
|
||||
|
||||
inline void pad_message_string() {
|
||||
uint8_t i = 0, j = 0;
|
||||
char c;
|
||||
lcd_status_message[MAX_MESSAGE_LENGTH] = '\0';
|
||||
while ((c = lcd_status_message[i]) && j < LCD_WIDTH) {
|
||||
if (PRINTABLE(c)) j++;
|
||||
i++;
|
||||
}
|
||||
if (true
|
||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||
&& j < LCD_WIDTH
|
||||
#endif
|
||||
) {
|
||||
// pad with spaces to fill up the line
|
||||
while (j++ < LCD_WIDTH) lcd_status_message[i++] = ' ';
|
||||
// chop off at the edge
|
||||
lcd_status_message[i] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_finishstatus(const bool persist=false) {
|
||||
|
||||
pad_message_string();
|
||||
|
||||
#if !(ENABLED(LCD_PROGRESS_BAR) && (PROGRESS_MSG_EXPIRE > 0))
|
||||
UNUSED(persist);
|
||||
#endif
|
||||
@@ -5459,7 +5395,7 @@ void lcd_finishstatus(const bool persist=false) {
|
||||
#endif
|
||||
|
||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||
status_scroll_pos = 0;
|
||||
status_scroll_offset = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -5471,7 +5407,26 @@ bool lcd_hasstatus() { return (lcd_status_message[0] != '\0'); }
|
||||
|
||||
void lcd_setstatus(const char * const message, const bool persist) {
|
||||
if (lcd_status_message_level > 0) return;
|
||||
strncpy(lcd_status_message, message, MAX_MESSAGE_LENGTH);
|
||||
|
||||
// Here we have a problem. The message is encoded in UTF8, so
|
||||
// arbitrarily cutting it will be a problem. We MUST be sure
|
||||
// that there is no cutting in the middle of a multibyte character!
|
||||
|
||||
// Get a pointer to the null terminator
|
||||
const char* pend = message + strlen(message);
|
||||
|
||||
// If length of supplied UTF8 string is greater than
|
||||
// our buffer size, start cutting whole UTF8 chars
|
||||
while ((pend - message) > MAX_MESSAGE_LENGTH) {
|
||||
--pend;
|
||||
while (!START_OF_UTF8_CHAR(*pend)) --pend;
|
||||
};
|
||||
|
||||
// At this point, we have the proper cut point. Use it
|
||||
uint8_t maxLen = pend - message;
|
||||
strncpy(lcd_status_message, message, maxLen);
|
||||
lcd_status_message[maxLen] = '\0';
|
||||
|
||||
lcd_finishstatus(persist);
|
||||
}
|
||||
|
||||
@@ -5479,7 +5434,26 @@ void lcd_setstatusPGM(const char * const message, int8_t level) {
|
||||
if (level < 0) level = lcd_status_message_level = 0;
|
||||
if (level < lcd_status_message_level) return;
|
||||
lcd_status_message_level = level;
|
||||
strncpy_P(lcd_status_message, message, MAX_MESSAGE_LENGTH);
|
||||
|
||||
// Here we have a problem. The message is encoded in UTF8, so
|
||||
// arbitrarily cutting it will be a problem. We MUST be sure
|
||||
// that there is no cutting in the middle of a multibyte character!
|
||||
|
||||
// Get a pointer to the null terminator
|
||||
const char* pend = message + strlen_P(message);
|
||||
|
||||
// If length of supplied UTF8 string is greater than
|
||||
// our buffer size, start cutting whole UTF8 chars
|
||||
while ((pend - message) > MAX_MESSAGE_LENGTH) {
|
||||
--pend;
|
||||
while (!START_OF_UTF8_CHAR(pgm_read_byte(pend))) --pend;
|
||||
};
|
||||
|
||||
// At this point, we have the proper cut point. Use it
|
||||
uint8_t maxLen = pend - message;
|
||||
strncpy_P(lcd_status_message, message, maxLen);
|
||||
lcd_status_message[maxLen] = '\0';
|
||||
|
||||
lcd_finishstatus(level > 0);
|
||||
}
|
||||
|
||||
@@ -5553,11 +5527,9 @@ void lcd_reset_alert_level() { lcd_status_message_level = 0; }
|
||||
#if BUTTON_EXISTS(EN1)
|
||||
if (BUTTON_PRESSED(EN1)) newbutton |= EN_A;
|
||||
#endif
|
||||
|
||||
#if BUTTON_EXISTS(EN2)
|
||||
if (BUTTON_PRESSED(EN2)) newbutton |= EN_B;
|
||||
#endif
|
||||
|
||||
#if BUTTON_EXISTS(ENC)
|
||||
if (BUTTON_PRESSED(ENC)) newbutton |= EN_C;
|
||||
#endif
|
||||
|
||||
+47
-42
@@ -87,7 +87,7 @@
|
||||
#define BUTTON_EXISTS(BN) (defined(BTN_## BN) && BTN_## BN >= 0)
|
||||
#define BUTTON_PRESSED(BN) !READ(BTN_## BN)
|
||||
|
||||
#if ENABLED(ULTIPANEL)
|
||||
#if ENABLED(ULTIPANEL) // LCD with a click-wheel input
|
||||
|
||||
extern bool defer_return_to_status;
|
||||
|
||||
@@ -111,27 +111,6 @@
|
||||
|
||||
void lcd_goto_screen(screenFunc_t screen, const uint32_t encoder=0);
|
||||
|
||||
// Encoder click is directly connected
|
||||
|
||||
#define BLEN_A 0
|
||||
#define BLEN_B 1
|
||||
|
||||
#define EN_A (_BV(BLEN_A))
|
||||
#define EN_B (_BV(BLEN_B))
|
||||
|
||||
#if BUTTON_EXISTS(ENC)
|
||||
#define BLEN_C 2
|
||||
#define EN_C (_BV(BLEN_C))
|
||||
#endif
|
||||
|
||||
#if BUTTON_EXISTS(BACK)
|
||||
#define BLEN_D 3
|
||||
#define EN_D _BV(BLEN_D)
|
||||
#define LCD_BACK_CLICKED (buttons & EN_D)
|
||||
#endif
|
||||
|
||||
extern volatile uint8_t buttons; // The last-checked buttons in a bit array.
|
||||
void lcd_buttons_update();
|
||||
void lcd_completion_feedback(const bool good=true);
|
||||
|
||||
#if ENABLED(ADVANCED_PAUSE_FEATURE)
|
||||
@@ -139,7 +118,7 @@
|
||||
void lcd_advanced_pause_show_message(const AdvancedPauseMessage message,
|
||||
const AdvancedPauseMode mode=ADVANCED_PAUSE_MODE_PAUSE_PRINT,
|
||||
const uint8_t extruder=active_extruder);
|
||||
#endif // ADVANCED_PAUSE_FEATURE
|
||||
#endif
|
||||
|
||||
#if ENABLED(G26_MESH_VALIDATION)
|
||||
void lcd_chirp();
|
||||
@@ -152,10 +131,6 @@
|
||||
float lcd_z_offset_edit();
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
inline void lcd_buttons_update() {}
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(FILAMENT_LCD_DISPLAY) && ENABLED(SDSUPPORT)
|
||||
@@ -203,12 +178,6 @@
|
||||
#define REPRAPWORLD_KEYPAD_MOVE_HOME (buttons_reprapworld_keypad & KEYPAD_HOME)
|
||||
#define REPRAPWORLD_KEYPAD_MOVE_MENU (buttons_reprapworld_keypad & KEYPAD_EN_C)
|
||||
|
||||
#if BUTTON_EXISTS(ENC)
|
||||
#define LCD_CLICKED ((buttons & EN_C) || REPRAPWORLD_KEYPAD_MOVE_MENU)
|
||||
#else
|
||||
#define LCD_CLICKED REPRAPWORLD_KEYPAD_MOVE_MENU
|
||||
#endif
|
||||
|
||||
#define REPRAPWORLD_KEYPAD_PRESSED (buttons_reprapworld_keypad & ( \
|
||||
EN_REPRAPWORLD_KEYPAD_F3 | \
|
||||
EN_REPRAPWORLD_KEYPAD_F2 | \
|
||||
@@ -220,14 +189,6 @@
|
||||
EN_REPRAPWORLD_KEYPAD_LEFT) \
|
||||
)
|
||||
|
||||
#elif ENABLED(NEWPANEL)
|
||||
|
||||
#define LCD_CLICKED (buttons & EN_C)
|
||||
|
||||
#else
|
||||
|
||||
#define LCD_CLICKED false
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL) || ENABLED(G26_MESH_VALIDATION)
|
||||
@@ -240,7 +201,6 @@
|
||||
constexpr bool lcd_wait_for_move = false;
|
||||
|
||||
inline void lcd_refresh() {}
|
||||
inline void lcd_buttons_update() {}
|
||||
inline bool lcd_hasstatus() { return false; }
|
||||
inline void lcd_setstatus(const char* const message, const bool persist=false) { UNUSED(message); UNUSED(persist); }
|
||||
inline void lcd_setstatusPGM(const char* const message, const int8_t level=0) { UNUSED(message); UNUSED(level); }
|
||||
@@ -250,6 +210,51 @@
|
||||
|
||||
#endif // ULTRA_LCD
|
||||
|
||||
#if ENABLED(ULTIPANEL)
|
||||
|
||||
#if ENABLED(NEWPANEL) // Uses digital switches, not a shift register
|
||||
|
||||
// Wheel spin pins where BA is 00, 10, 11, 01 (1 bit always changes)
|
||||
#define BLEN_A 0
|
||||
#define BLEN_B 1
|
||||
|
||||
#define EN_A _BV(BLEN_A)
|
||||
#define EN_B _BV(BLEN_B)
|
||||
|
||||
#if BUTTON_EXISTS(ENC)
|
||||
#define BLEN_C 2
|
||||
#define EN_C _BV(BLEN_C)
|
||||
#endif
|
||||
|
||||
#if BUTTON_EXISTS(BACK)
|
||||
#define BLEN_D 3
|
||||
#define EN_D _BV(BLEN_D)
|
||||
#define LCD_BACK_CLICKED (buttons & EN_D)
|
||||
#endif
|
||||
|
||||
#endif // NEWPANEL
|
||||
|
||||
extern volatile uint8_t buttons; // The last-checked buttons in a bit array.
|
||||
void lcd_buttons_update();
|
||||
|
||||
#else
|
||||
|
||||
inline void lcd_buttons_update() {}
|
||||
|
||||
#endif
|
||||
|
||||
#if ENABLED(REPRAPWORLD_KEYPAD)
|
||||
#ifdef EN_C
|
||||
#define LCD_CLICKED ((buttons & EN_C) || REPRAPWORLD_KEYPAD_MOVE_MENU)
|
||||
#else
|
||||
#define LCD_CLICKED REPRAPWORLD_KEYPAD_MOVE_MENU
|
||||
#endif
|
||||
#elif defined(EN_C)
|
||||
#define LCD_CLICKED (buttons & EN_C)
|
||||
#else
|
||||
#define LCD_CLICKED false
|
||||
#endif
|
||||
|
||||
#define LCD_MESSAGEPGM(x) lcd_setstatusPGM(PSTR(x))
|
||||
#define LCD_ALERTMESSAGEPGM(x) lcd_setalertstatusPGM(PSTR(x))
|
||||
|
||||
|
||||
+16
-16
@@ -33,31 +33,23 @@
|
||||
* License: http://opensource.org/licenses/BSD-3-Clause
|
||||
*/
|
||||
|
||||
/**
|
||||
* Implementation of the LCD display routines for a DOGM128 graphic display.
|
||||
* These are common LCD 128x64 pixel graphic displays.
|
||||
*/
|
||||
|
||||
#ifndef ULTRALCD_IMPL_DOGM_H
|
||||
#define ULTRALCD_IMPL_DOGM_H
|
||||
|
||||
#include "MarlinConfig.h"
|
||||
|
||||
/**
|
||||
* Implementation of the LCD display routines for a DOGM128 graphic display.
|
||||
* These are common LCD 128x64 pixel graphic displays.
|
||||
*/
|
||||
#include <U8glib.h>
|
||||
|
||||
#include "ultralcd.h"
|
||||
|
||||
#if ENABLED(U8GLIB_ST7920)
|
||||
#include "ultralcd_st7920_u8glib_rrd.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(U8GLIB_ST7565_64128N)
|
||||
#include "ultralcd_st7565_u8glib_VIKI.h"
|
||||
#endif
|
||||
|
||||
#include "dogm_bitmaps.h"
|
||||
#include "utility.h"
|
||||
#include "duration_t.h"
|
||||
|
||||
#include <U8glib.h>
|
||||
|
||||
#if ENABLED(AUTO_BED_LEVELING_UBL)
|
||||
#include "ubl.h"
|
||||
#endif
|
||||
@@ -68,6 +60,14 @@
|
||||
#undef USE_SMALL_INFOFONT
|
||||
#endif
|
||||
|
||||
#if ENABLED(U8GLIB_ST7920)
|
||||
#include "ultralcd_st7920_u8glib_rrd.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(U8GLIB_ST7565_64128N)
|
||||
#include "ultralcd_st7565_u8glib_VIKI.h"
|
||||
#endif
|
||||
|
||||
#if ENABLED(USE_SMALL_INFOFONT)
|
||||
#include "dogm_font_data_6x9_marlin.h"
|
||||
#define FONT_STATUSMENU_NAME u8g_font_6x9
|
||||
@@ -603,7 +603,7 @@ void lcd_implementation_clear() { } // Automatically cleared by Picture Loop
|
||||
name_hash = ((name_hash << 1) | (name_hash >> 7)) ^ filename[l]; // rotate, xor
|
||||
if (filename_scroll_hash != name_hash) { // If the hash changed...
|
||||
filename_scroll_hash = name_hash; // Save the new hash
|
||||
filename_scroll_max = max(0, lcd_strlen(longFilename) - maxlen); // Update the scroll limit
|
||||
filename_scroll_max = MAX(0, lcd_strlen(longFilename) - maxlen); // Update the scroll limit
|
||||
filename_scroll_pos = 0; // Reset scroll to the start
|
||||
lcd_status_update_delay = 8; // Don't scroll right away
|
||||
}
|
||||
|
||||
+131
-60
@@ -67,19 +67,19 @@ extern volatile uint8_t buttons; //an extended version of the last checked butt
|
||||
#define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
|
||||
|
||||
// button and encoder bit positions within 'buttons'
|
||||
#define B_LE (BUTTON_LEFT<<B_I2C_BTN_OFFSET) // The remaining normalized buttons are all read via I2C
|
||||
#define B_UP (BUTTON_UP<<B_I2C_BTN_OFFSET)
|
||||
#define B_MI (BUTTON_SELECT<<B_I2C_BTN_OFFSET)
|
||||
#define B_DW (BUTTON_DOWN<<B_I2C_BTN_OFFSET)
|
||||
#define B_RI (BUTTON_RIGHT<<B_I2C_BTN_OFFSET)
|
||||
#define B_LE (BUTTON_LEFT << B_I2C_BTN_OFFSET) // The remaining normalized buttons are all read via I2C
|
||||
#define B_UP (BUTTON_UP << B_I2C_BTN_OFFSET)
|
||||
#define B_MI (BUTTON_SELECT << B_I2C_BTN_OFFSET)
|
||||
#define B_DW (BUTTON_DOWN << B_I2C_BTN_OFFSET)
|
||||
#define B_RI (BUTTON_RIGHT << B_I2C_BTN_OFFSET)
|
||||
|
||||
#undef LCD_CLICKED
|
||||
#if BUTTON_EXISTS(ENC)
|
||||
// the pause/stop/restart button is connected to BTN_ENC when used
|
||||
#define B_ST (EN_C) // Map the pause/stop/resume button into its normalized functional name
|
||||
#define LCD_CLICKED (buttons&(B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop.
|
||||
#define LCD_CLICKED (buttons & (B_MI|B_RI|B_ST)) // pause/stop button also acts as click until we implement proper pause/stop.
|
||||
#else
|
||||
#define LCD_CLICKED (buttons&(B_MI|B_RI))
|
||||
#define LCD_CLICKED (buttons & (B_MI|B_RI))
|
||||
#endif
|
||||
|
||||
// I2C buttons take too long to read inside an interrupt context and so we read them during lcd_update
|
||||
@@ -91,7 +91,7 @@ extern volatile uint8_t buttons; //an extended version of the last checked butt
|
||||
|
||||
#define B_I2C_BTN_OFFSET 3 // (the first three bit positions reserved for EN_A, EN_B, EN_C)
|
||||
|
||||
#define B_MI (PANELOLU2_ENCODER_C<<B_I2C_BTN_OFFSET) // requires LiquidTWI2 library v1.2.3 or later
|
||||
#define B_MI (PANELOLU2_ENCODER_C << B_I2C_BTN_OFFSET) // requires LiquidTWI2 library v1.2.3 or later
|
||||
|
||||
#undef LCD_CLICKED
|
||||
#define LCD_CLICKED (buttons & B_MI)
|
||||
@@ -467,9 +467,7 @@ static void lcd_implementation_init(
|
||||
}
|
||||
|
||||
void lcd_implementation_clear() { lcd.clear(); }
|
||||
|
||||
void lcd_print(const char c) { charset_mapper(c); }
|
||||
|
||||
void lcd_print(const char *str) { while (*str) lcd.print(*str++); }
|
||||
void lcd_printPGM(const char *str) { while (const char c = pgm_read_byte(str)) lcd.print(c), ++str; }
|
||||
|
||||
@@ -493,13 +491,42 @@ void lcd_printPGM_utf(const char *str, uint8_t n=LCD_WIDTH) {
|
||||
|
||||
// Scroll the PSTR 'text' in a 'len' wide field for 'time' milliseconds at position col,line
|
||||
void lcd_scroll(const int16_t col, const int16_t line, const char* const text, const int16_t len, const int16_t time) {
|
||||
char tmp[LCD_WIDTH + 1] = {0};
|
||||
int16_t n = max(lcd_strlen_P(text) - len, 0);
|
||||
for (int16_t i = 0; i <= n; i++) {
|
||||
strncpy_P(tmp, text + i, min(len, LCD_WIDTH));
|
||||
uint8_t slen = lcd_strlen_P(text);
|
||||
if (slen < len) {
|
||||
// Fits into,
|
||||
lcd.setCursor(col, line);
|
||||
lcd_print(tmp);
|
||||
delay(time / max(n, 1));
|
||||
lcd_printPGM_utf(text, len);
|
||||
while (slen < len) {
|
||||
lcd.write(' ');
|
||||
++slen;
|
||||
}
|
||||
safe_delay(time);
|
||||
}
|
||||
else {
|
||||
const char* p = text;
|
||||
int dly = time / MAX(slen, 1);
|
||||
for (uint8_t i = 0; i <= slen; i++) {
|
||||
|
||||
// Go to the correct place
|
||||
lcd.setCursor(col, line);
|
||||
|
||||
// Print the text
|
||||
lcd_printPGM_utf(p, len);
|
||||
|
||||
// Fill with spaces
|
||||
uint8_t ix = slen - i;
|
||||
while (ix < len) {
|
||||
lcd.write(' ');
|
||||
++ix;
|
||||
}
|
||||
|
||||
// Delay
|
||||
safe_delay(dly);
|
||||
|
||||
// Advance to the next UTF8 valid position
|
||||
p++;
|
||||
while (!START_OF_UTF8_CHAR(pgm_read_byte(p))) p++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -599,19 +626,25 @@ void lcd_kill_screen() {
|
||||
lcd_printPGM_utf(PSTR(MSG_PLEASE_RESET));
|
||||
}
|
||||
|
||||
FORCE_INLINE void _draw_axis_label(const AxisEnum axis, const char* const pstr, const bool blink) {
|
||||
//
|
||||
// Before homing, blink '123' <-> '???'.
|
||||
// Homed but unknown... '123' <-> ' '.
|
||||
// Homed and known, display constantly.
|
||||
//
|
||||
FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink) {
|
||||
lcd_print('X' + uint8_t(axis));
|
||||
if (blink)
|
||||
lcd_printPGM(pstr);
|
||||
lcd.print(value);
|
||||
else {
|
||||
if (!axis_homed[axis])
|
||||
lcd.write('?');
|
||||
while (const char c = *value++) lcd_print(c <= '.' ? c : '?');
|
||||
else {
|
||||
#if DISABLED(HOME_AFTER_DEACTIVATE) && DISABLED(DISABLE_REDUCED_ACCURACY_WARNING)
|
||||
if (!axis_known_position[axis])
|
||||
lcd.write(' ');
|
||||
lcd_printPGM(axis == Z_AXIS ? PSTR(" ") : PSTR(" "));
|
||||
else
|
||||
#endif
|
||||
lcd_printPGM(pstr);
|
||||
lcd.print(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -719,7 +752,7 @@ static void lcd_implementation_status_screen() {
|
||||
//
|
||||
// Hotend 1 or Bed Temperature
|
||||
//
|
||||
#if HOTENDS > 1 || TEMP_SENSOR_BED
|
||||
#if HOTENDS > 1 || HAS_HEATED_BED
|
||||
|
||||
lcd.setCursor(8, 0);
|
||||
#if HOTENDS > 1
|
||||
@@ -730,7 +763,7 @@ static void lcd_implementation_status_screen() {
|
||||
_draw_heater_status(-1, -1, blink);
|
||||
#endif
|
||||
|
||||
#endif // HOTENDS > 1 || TEMP_SENSOR_BED
|
||||
#endif // HOTENDS > 1 || HAS_HEATED_BED
|
||||
|
||||
#else // LCD_WIDTH >= 20
|
||||
|
||||
@@ -742,7 +775,7 @@ static void lcd_implementation_status_screen() {
|
||||
//
|
||||
// Hotend 1 or Bed Temperature
|
||||
//
|
||||
#if HOTENDS > 1 || TEMP_SENSOR_BED
|
||||
#if HOTENDS > 1 || HAS_HEATED_BED
|
||||
lcd.setCursor(10, 0);
|
||||
#if HOTENDS > 1
|
||||
_draw_heater_status(1, LCD_STR_THERMOMETER[0], blink);
|
||||
@@ -755,7 +788,7 @@ static void lcd_implementation_status_screen() {
|
||||
), blink);
|
||||
#endif
|
||||
|
||||
#endif // HOTENDS > 1 || TEMP_SENSOR_BED != 0
|
||||
#endif // HOTENDS > 1 || HAS_HEATED_BED
|
||||
|
||||
#endif // LCD_WIDTH >= 20
|
||||
|
||||
@@ -784,7 +817,7 @@ static void lcd_implementation_status_screen() {
|
||||
// If the first line has two extruder temps,
|
||||
// show more temperatures on the next line
|
||||
|
||||
#if HOTENDS > 2 || (HOTENDS > 1 && TEMP_SENSOR_BED)
|
||||
#if HOTENDS > 2 || (HOTENDS > 1 && HAS_HEATED_BED)
|
||||
|
||||
#if HOTENDS > 2
|
||||
_draw_heater_status(2, LCD_STR_THERMOMETER[0], blink);
|
||||
@@ -798,28 +831,22 @@ static void lcd_implementation_status_screen() {
|
||||
LCD_BEDTEMP_CHAR
|
||||
), blink);
|
||||
|
||||
#else // HOTENDS <= 2 && (HOTENDS <= 1 || !TEMP_SENSOR_BED)
|
||||
// Before homing the axis letters are blinking 'X' <-> '?'.
|
||||
// When axis is homed but axis_known_position is false the axis letters are blinking 'X' <-> ' '.
|
||||
// When everything is ok you see a constant 'X'.
|
||||
#else // HOTENDS <= 2 && (HOTENDS <= 1 || !HAS_HEATED_BED)
|
||||
|
||||
_draw_axis_label(X_AXIS, PSTR(MSG_X), blink);
|
||||
lcd.print(ftostr4sign(LOGICAL_X_POSITION(current_position[X_AXIS])));
|
||||
_draw_axis_value(X_AXIS, ftostr4sign(LOGICAL_X_POSITION(current_position[X_AXIS])), blink);
|
||||
|
||||
lcd.write(' ');
|
||||
|
||||
_draw_axis_label(Y_AXIS, PSTR(MSG_Y), blink);
|
||||
lcd.print(ftostr4sign(LOGICAL_Y_POSITION(current_position[Y_AXIS])));
|
||||
_draw_axis_value(Y_AXIS, ftostr4sign(LOGICAL_Y_POSITION(current_position[Y_AXIS])), blink);
|
||||
|
||||
#endif // HOTENDS <= 2 && (HOTENDS <= 1 || !TEMP_SENSOR_BED)
|
||||
#endif // HOTENDS <= 2 && (HOTENDS <= 1 || !HAS_HEATED_BED)
|
||||
|
||||
#endif // LCD_WIDTH >= 20
|
||||
|
||||
lcd.setCursor(LCD_WIDTH - 8, 1);
|
||||
_draw_axis_label(Z_AXIS, PSTR(MSG_Z), blink);
|
||||
lcd.print(ftostr52sp(LOGICAL_Z_POSITION(current_position[Z_AXIS])));
|
||||
_draw_axis_value(Z_AXIS, ftostr52sp(LOGICAL_Z_POSITION(current_position[Z_AXIS])), blink);
|
||||
|
||||
#if HAS_LEVELING && !TEMP_SENSOR_BED
|
||||
#if HAS_LEVELING && !HAS_HEATED_BED
|
||||
lcd.write(planner.leveling_active || blink ? '_' : ' ');
|
||||
#endif
|
||||
|
||||
@@ -897,38 +924,82 @@ static void lcd_implementation_status_screen() {
|
||||
|
||||
#if ENABLED(STATUS_MESSAGE_SCROLLING)
|
||||
static bool last_blink = false;
|
||||
const uint8_t slen = lcd_strlen(lcd_status_message);
|
||||
const char *stat = lcd_status_message + status_scroll_pos;
|
||||
if (slen <= LCD_WIDTH)
|
||||
lcd_print_utf(stat); // The string isn't scrolling
|
||||
|
||||
// Get the UTF8 character count of the string
|
||||
uint8_t slen = lcd_strlen(lcd_status_message);
|
||||
|
||||
// If the string fits into the LCD, just print it and do not scroll it
|
||||
if (slen <= LCD_WIDTH) {
|
||||
|
||||
// The string isn't scrolling and may not fill the screen
|
||||
lcd_print_utf(lcd_status_message);
|
||||
|
||||
// Fill the rest with spaces
|
||||
while (slen < LCD_WIDTH) {
|
||||
lcd.write(' ');
|
||||
++slen;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (status_scroll_pos <= slen - LCD_WIDTH)
|
||||
lcd_print_utf(stat); // The string fills the screen
|
||||
// String is larger than the available space in screen.
|
||||
|
||||
// Get a pointer to the next valid UTF8 character
|
||||
const char *stat = lcd_status_message + status_scroll_offset;
|
||||
|
||||
// Get the string remaining length
|
||||
const uint8_t rlen = lcd_strlen(stat);
|
||||
|
||||
// If we have enough characters to display
|
||||
if (rlen >= LCD_WIDTH) {
|
||||
// The remaining string fills the screen - Print it
|
||||
lcd_print_utf(stat, LCD_WIDTH);
|
||||
}
|
||||
else {
|
||||
uint8_t chars = LCD_WIDTH;
|
||||
if (status_scroll_pos < slen) { // First string still visible
|
||||
lcd_print_utf(stat); // The string leaves space
|
||||
chars -= slen - status_scroll_pos; // Amount of space left
|
||||
}
|
||||
lcd.write('.'); // Always at 1+ spaces left, draw a dot
|
||||
if (--chars) {
|
||||
if (status_scroll_pos < slen + 1) // Draw a second dot if there's space
|
||||
--chars, lcd.write('.');
|
||||
if (chars) lcd_print_utf(lcd_status_message, chars); // Print a second copy of the message
|
||||
|
||||
// The remaining string does not completely fill the screen
|
||||
lcd_print_utf(stat, LCD_WIDTH); // The string leaves space
|
||||
uint8_t chars = LCD_WIDTH - rlen; // Amount of space left in characters
|
||||
|
||||
lcd.write('.'); // Always at 1+ spaces left, draw a dot
|
||||
if (--chars) { // Draw a second dot if there's space
|
||||
lcd.write('.');
|
||||
if (--chars)
|
||||
lcd_print_utf(lcd_status_message, chars); // Print a second copy of the message
|
||||
}
|
||||
}
|
||||
if (last_blink != blink) {
|
||||
last_blink = blink;
|
||||
// Skip any non-printing bytes
|
||||
if (status_scroll_pos < slen) while (!PRINTABLE(lcd_status_message[status_scroll_pos])) status_scroll_pos++;
|
||||
if (++status_scroll_pos >= slen + 2) status_scroll_pos = 0;
|
||||
|
||||
// Adjust by complete UTF8 characters
|
||||
if (status_scroll_offset < slen) {
|
||||
status_scroll_offset++;
|
||||
while (!START_OF_UTF8_CHAR(lcd_status_message[status_scroll_offset]))
|
||||
status_scroll_offset++;
|
||||
}
|
||||
else
|
||||
status_scroll_offset = 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
lcd_print_utf(lcd_status_message);
|
||||
UNUSED(blink);
|
||||
|
||||
// Get the UTF8 character count of the string
|
||||
uint8_t slen = lcd_strlen(lcd_status_message);
|
||||
|
||||
// Just print the string to the LCD
|
||||
lcd_print_utf(lcd_status_message, LCD_WIDTH);
|
||||
|
||||
// Fill the rest with spaces if there are missing spaces
|
||||
while (slen < LCD_WIDTH) {
|
||||
lcd.write(' ');
|
||||
++slen;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if ENABLED(ULTIPANEL)
|
||||
|
||||
#if ENABLED(ADVANCED_PAUSE_FEATURE)
|
||||
@@ -1034,7 +1105,7 @@ static void lcd_implementation_status_screen() {
|
||||
name_hash = ((name_hash << 1) | (name_hash >> 7)) ^ filename[l]; // rotate, xor
|
||||
if (filename_scroll_hash != name_hash) { // If the hash changed...
|
||||
filename_scroll_hash = name_hash; // Save the new hash
|
||||
filename_scroll_max = max(0, lcd_strlen(longFilename) - n); // Update the scroll limit
|
||||
filename_scroll_max = MAX(0, lcd_strlen(longFilename) - n); // Update the scroll limit
|
||||
filename_scroll_pos = 0; // Reset scroll to the start
|
||||
lcd_status_update_delay = 8; // Don't scroll right away
|
||||
}
|
||||
@@ -1347,7 +1418,7 @@ static void lcd_implementation_status_screen() {
|
||||
//dump_custom_char("at entry:", &new_char);
|
||||
|
||||
clear_custom_char(&new_char);
|
||||
const uint8_t ypix = min(upper_left.y_pixel_offset + pixels_per_y_mesh_pnt, ULTRA_Y_PIXELS_PER_CHAR);
|
||||
const uint8_t ypix = MIN(upper_left.y_pixel_offset + pixels_per_y_mesh_pnt, ULTRA_Y_PIXELS_PER_CHAR);
|
||||
for (j = upper_left.y_pixel_offset; j < ypix; j++) {
|
||||
i = upper_left.x_pixel_mask;
|
||||
for (k = 0; k < pixels_per_x_mesh_pnt; k++) {
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define ULCDST7565_H
|
||||
|
||||
#include <U8glib.h>
|
||||
#include "delay.h"
|
||||
|
||||
#define ST7565_CLK_PIN DOGLCD_SCK
|
||||
#define ST7565_DAT_PIN DOGLCD_MOSI
|
||||
@@ -38,9 +39,9 @@
|
||||
#pragma GCC optimize (3)
|
||||
|
||||
// If you want you can define your own set of delays in Configuration.h
|
||||
//#define ST7565_DELAY_1 DELAY_0_NOP
|
||||
//#define ST7565_DELAY_2 DELAY_0_NOP
|
||||
//#define ST7565_DELAY_3 DELAY_0_NOP
|
||||
//#define ST7565_DELAY_1 DELAY_NS(0)
|
||||
//#define ST7565_DELAY_2 DELAY_NS(0)
|
||||
//#define ST7565_DELAY_3 DELAY_NS(0)
|
||||
|
||||
/*
|
||||
#define ST7565_DELAY_1 u8g_10MicroDelay()
|
||||
@@ -49,25 +50,25 @@
|
||||
*/
|
||||
|
||||
#if F_CPU >= 20000000
|
||||
#define CPU_ST7565_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_2 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_3 DELAY_1_NOP
|
||||
#define CPU_ST7565_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7565_DELAY_2 DELAY_NS(0)
|
||||
#define CPU_ST7565_DELAY_3 DELAY_NS(63)
|
||||
#elif MB(3DRAG) || MB(K8200) || MB(K8400)
|
||||
#define CPU_ST7565_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_2 DELAY_3_NOP
|
||||
#define CPU_ST7565_DELAY_3 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7565_DELAY_2 DELAY_NS(188)
|
||||
#define CPU_ST7565_DELAY_3 DELAY_NS(0)
|
||||
#elif MB(MINIRAMBO)
|
||||
#define CPU_ST7565_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_2 DELAY_4_NOP
|
||||
#define CPU_ST7565_DELAY_3 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7565_DELAY_2 DELAY_NS(250)
|
||||
#define CPU_ST7565_DELAY_3 DELAY_NS(0)
|
||||
#elif MB(RAMBO)
|
||||
#define CPU_ST7565_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_2 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_3 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7565_DELAY_2 DELAY_NS(0)
|
||||
#define CPU_ST7565_DELAY_3 DELAY_NS(0)
|
||||
#elif F_CPU == 16000000
|
||||
#define CPU_ST7565_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_2 DELAY_0_NOP
|
||||
#define CPU_ST7565_DELAY_3 DELAY_1_NOP
|
||||
#define CPU_ST7565_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7565_DELAY_2 DELAY_NS(0)
|
||||
#define CPU_ST7565_DELAY_3 DELAY_NS(63)
|
||||
#else
|
||||
#error "No valid condition for delays in 'ultralcd_st7565_u8glib_VIKI.h'"
|
||||
#endif
|
||||
@@ -115,8 +116,8 @@
|
||||
|
||||
#endif // !HARDWARE_SPI
|
||||
|
||||
#if defined(DOGM_SPI_DELAY_US) && DOGM_SPI_DELAY_US > 0
|
||||
#define U8G_DELAY() delayMicroseconds(DOGM_SPI_DELAY_US)
|
||||
#if DOGM_SPI_DELAY_US > 0
|
||||
#define U8G_DELAY() DELAY_US(DOGM_SPI_DELAY_US)
|
||||
#else
|
||||
#define U8G_DELAY() u8g_10MicroDelay()
|
||||
#endif
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#define ULCDST7920_H
|
||||
|
||||
#include <U8glib.h>
|
||||
#include "delay.h"
|
||||
|
||||
#define ST7920_CLK_PIN LCD_PINS_D4
|
||||
#define ST7920_DAT_PIN LCD_PINS_ENABLE
|
||||
@@ -40,30 +41,30 @@
|
||||
#pragma GCC optimize (3)
|
||||
|
||||
// If you want you can define your own set of delays in Configuration.h
|
||||
//#define ST7920_DELAY_1 DELAY_0_NOP
|
||||
//#define ST7920_DELAY_2 DELAY_0_NOP
|
||||
//#define ST7920_DELAY_3 DELAY_0_NOP
|
||||
//#define ST7920_DELAY_1 DELAY_NS(0)
|
||||
//#define ST7920_DELAY_2 DELAY_NS(0)
|
||||
//#define ST7920_DELAY_3 DELAY_NS(0)
|
||||
|
||||
#if F_CPU >= 20000000
|
||||
#define CPU_ST7920_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_2 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_3 DELAY_1_NOP
|
||||
#define CPU_ST7920_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7920_DELAY_2 DELAY_NS(0)
|
||||
#define CPU_ST7920_DELAY_3 DELAY_NS(50)
|
||||
#elif MB(3DRAG) || MB(K8200) || MB(K8400) || MB(SILVER_GATE)
|
||||
#define CPU_ST7920_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_2 DELAY_3_NOP
|
||||
#define CPU_ST7920_DELAY_3 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7920_DELAY_2 DELAY_NS(188)
|
||||
#define CPU_ST7920_DELAY_3 DELAY_NS(0)
|
||||
#elif MB(MINIRAMBO)
|
||||
#define CPU_ST7920_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_2 DELAY_4_NOP
|
||||
#define CPU_ST7920_DELAY_3 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7920_DELAY_2 DELAY_NS(250)
|
||||
#define CPU_ST7920_DELAY_3 DELAY_NS(0)
|
||||
#elif MB(RAMBO)
|
||||
#define CPU_ST7920_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_2 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_3 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7920_DELAY_2 DELAY_NS(0)
|
||||
#define CPU_ST7920_DELAY_3 DELAY_NS(0)
|
||||
#elif F_CPU == 16000000
|
||||
#define CPU_ST7920_DELAY_1 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_2 DELAY_0_NOP
|
||||
#define CPU_ST7920_DELAY_3 DELAY_1_NOP
|
||||
#define CPU_ST7920_DELAY_1 DELAY_NS(0)
|
||||
#define CPU_ST7920_DELAY_2 DELAY_NS(0)
|
||||
#define CPU_ST7920_DELAY_3 DELAY_NS(63)
|
||||
#else
|
||||
#error "No valid condition for delays in 'ultralcd_st7920_u8glib_rrd.h'"
|
||||
#endif
|
||||
@@ -95,8 +96,8 @@ static void ST7920_SWSPI_SND_8BIT(uint8_t val) {
|
||||
ST7920_SND_BIT; // 8
|
||||
}
|
||||
|
||||
#if defined(DOGM_SPI_DELAY_US) && DOGM_SPI_DELAY_US > 0
|
||||
#define U8G_DELAY() delayMicroseconds(DOGM_SPI_DELAY_US)
|
||||
#if DOGM_SPI_DELAY_US > 0
|
||||
#define U8G_DELAY() DELAY_US(DOGM_SPI_DELAY_US)
|
||||
#else
|
||||
#define U8G_DELAY() u8g_10MicroDelay()
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -144,7 +144,7 @@
|
||||
#endif // DISPLAY_CHARSET_HD44780
|
||||
#endif // SIMULATE_ROMFONT
|
||||
|
||||
#define PRINTABLE(C) (((C) & 0xC0u) != 0x80u)
|
||||
#define START_OF_UTF8_CHAR(C) (((C) & 0xC0u) != 0x80u)
|
||||
|
||||
#if ENABLED(MAPPER_C2C3)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user