Bump to bugfix brack as of 20180526

This commit is contained in:
InsanityAutomation
2018-05-31 10:53:24 -04:00
parent 81cd4c66cc
commit 8285f1541e
72 changed files with 5948 additions and 4819 deletions
+432 -432
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -30,7 +30,7 @@
/*
* Enables a filament sensor plugged into the laser pin. Disables the laser
*/
#define FilamentSensor
//#define FilamentSensor
/**
* Configuration.h
*
+148 -74
View File
@@ -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
View File
@@ -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_
+26 -26
View File
@@ -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
View File
@@ -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
View File
@@ -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
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+4 -3
View File
@@ -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);
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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_
-5
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;
+19 -18
View 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();
}
+4 -3
View File
@@ -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)
+77
View File
@@ -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
+1 -1
View File
@@ -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() {
+1 -1
View File
@@ -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
+4 -1
View File
@@ -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
+9 -16
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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,
-1
View File
@@ -28,7 +28,6 @@
#include <stdint.h>
typedef int8_t pin_t;
#ifndef _FASTIO_ARDUINO_H_
#define _FASTIO_ARDUINO_H_
+1 -1
View File
@@ -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;
+4 -4
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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"
+7 -7
View File
@@ -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
+3 -3
View File
@@ -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)
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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
+6 -8
View File
@@ -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
+3 -3
View File
@@ -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
+3 -3
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+192 -90
View File
@@ -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;
+7 -5
View File
@@ -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
}
}
+4 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
+55 -20
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+95 -150
View File
@@ -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;
}
+4 -3
View File
@@ -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);
+21 -17
View File
@@ -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
View File
@@ -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
+7 -3
View File
@@ -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;
}
/**
+9 -9
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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++) {
+21 -20
View File
@@ -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
+21 -20
View File
@@ -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
View File
@@ -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)