Merge remote-tracking branch 'upstream/bugfix-2.0.x' into 2.0.x

This commit is contained in:
Scott Lahteine
2020-08-27 22:17:50 -05:00
454 changed files with 23706 additions and 5258 deletions

View File

@ -177,7 +177,7 @@
#endif
/**
* Prusa Multi-Material Unit v2
* Průša Multi-Material Unit v2
*
* Requires NOZZLE_PARK_FEATURE to park print head in case MMU unit fails.
* Requires EXTRUDERS = 5
@ -235,8 +235,8 @@
#elif ENABLED(MAGNETIC_PARKING_EXTRUDER)
#define MPE_FAST_SPEED 9000 // (mm/m) Speed for travel before last distance point
#define MPE_SLOW_SPEED 4500 // (mm/m) Speed for last distance travel to park and couple
#define MPE_FAST_SPEED 9000 // (mm/min) Speed for travel before last distance point
#define MPE_SLOW_SPEED 4500 // (mm/min) Speed for last distance travel to park and couple
#define MPE_TRAVEL_DISTANCE 10 // (mm) Last distance point
#define MPE_COMPENSATION 0 // Offset Compensation -1 , 0 , 1 (multiplier) only for coupling
@ -284,8 +284,8 @@
#if ENABLED(PRIME_BEFORE_REMOVE)
#define SWITCHING_TOOLHEAD_PRIME_MM 20 // (mm) Extruder prime length
#define SWITCHING_TOOLHEAD_RETRACT_MM 10 // (mm) Retract after priming length
#define SWITCHING_TOOLHEAD_PRIME_FEEDRATE 300 // (mm/m) Extruder prime feedrate
#define SWITCHING_TOOLHEAD_RETRACT_FEEDRATE 2400 // (mm/m) Extruder retract feedrate
#define SWITCHING_TOOLHEAD_PRIME_FEEDRATE 300 // (mm/min) Extruder prime feedrate
#define SWITCHING_TOOLHEAD_RETRACT_FEEDRATE 2400 // (mm/min) Extruder retract feedrate
#endif
#elif ENABLED(ELECTROMAGNETIC_SWITCHING_TOOLHEAD)
#define SWITCHING_TOOLHEAD_Z_HOP 2 // (mm) Z raise for switching
@ -330,7 +330,7 @@
//#define PSU_NAME "Power Supply"
#if ENABLED(PSU_CONTROL)
#define PSU_ACTIVE_HIGH false // Set 'false' for ATX, 'true' for X-Box
#define PSU_ACTIVE_STATE LOW // Set 'LOW' for ATX, 'HIGH' for X-Box
//#define PSU_DEFAULT_OFF // Keep power off until enabled directly with M80
//#define PSU_POWERUP_DELAY 250 // (ms) Delay for the PSU to warm up to full power
@ -373,7 +373,7 @@
* 4 : 10k thermistor !! do not use it for a hotend. It gives bad resolution at high temp. !!
* 5 : 100K thermistor - ATC Semitec 104GT-2/104NT-4-R025H42G (Used in ParCan, J-Head, and E3D) (4.7k pullup)
* 501 : 100K Zonestar (Tronxy X3A) Thermistor
* 502 : 100K Zonestar Thermistor used by hot bed in Zonestar Prusa P802M
* 502 : 100K Zonestar Thermistor used by hot bed in Zonestar Průša P802M
* 512 : 100k RPW-Ultra hotend thermistor (4.7k pullup)
* 6 : 100k EPCOS - Not as accurate as table 1 (created using a fluke thermocouple) (4.7k pullup)
* 7 : 100k Honeywell thermistor 135-104LAG-J01 (4.7k pullup)
@ -964,24 +964,34 @@
//
/**
* Z Probe to nozzle (X,Y) offset, relative to (0, 0).
* Nozzle-to-Probe offsets { X, Y, Z }
*
* In the following example the X and Y offsets are both positive:
* - Use a caliper or ruler to measure the distance from the tip of
* the Nozzle to the center-point of the Probe in the X and Y axes.
* - For the Z offset use your best known value and adjust at runtime.
* - Probe Offsets can be tuned at runtime with 'M851', LCD menus, babystepping, etc.
*
* #define NOZZLE_TO_PROBE_OFFSET { 10, 10, 0 }
* Assuming the typical work area orientation:
* - Probe to RIGHT of the Nozzle has a Positive X offset
* - Probe to LEFT of the Nozzle has a Negative X offset
* - Probe in BACK of the Nozzle has a Positive Y offset
* - Probe in FRONT of the Nozzle has a Negative Y offset
*
* Some examples:
* #define NOZZLE_TO_PROBE_OFFSET { 10, 10, -1 } // Example "1"
* #define NOZZLE_TO_PROBE_OFFSET {-10, 5, -1 } // Example "2"
* #define NOZZLE_TO_PROBE_OFFSET { 5, -5, -1 } // Example "3"
* #define NOZZLE_TO_PROBE_OFFSET {-15,-10, -1 } // Example "4"
*
* +-- BACK ---+
* | |
* L | (+) P | R <-- probe (20,20)
* E | | I
* F | (-) N (+) | G <-- nozzle (10,10)
* T | | H
* | (-) | T
* | |
* | [+] |
* L | 1 | R <-- Example "1" (right+, back+)
* E | 2 | I <-- Example "2" ( left-, back+)
* F |[-] N [+]| G <-- Nozzle
* T | 3 | H <-- Example "3" (right+, front-)
* | 4 | T <-- Example "4" ( left-, front-)
* | [-] |
* O-- FRONT --+
* (0,0)
*
* Specify a Probe position as { X, Y, Z }
*/
#define NOZZLE_TO_PROBE_OFFSET { 10, 10, 0 }
@ -989,13 +999,13 @@
// with NOZZLE_AS_PROBE this can be negative for a wider probing area.
#define PROBING_MARGIN 10
// X and Y axis travel speed (mm/m) between probes
#define XY_PROBE_SPEED 8000
// X and Y axis travel speed (mm/min) between probes
#define XY_PROBE_SPEED (133*60)
// Feedrate (mm/m) for the first approach when double-probing (MULTIPLE_PROBING == 2)
// Feedrate (mm/min) for the first approach when double-probing (MULTIPLE_PROBING == 2)
#define Z_PROBE_SPEED_FAST HOMING_FEEDRATE_Z
// Feedrate (mm/m) for the "accurate" probe of each point
// Feedrate (mm/min) for the "accurate" probe of each point
#define Z_PROBE_SPEED_SLOW (Z_PROBE_SPEED_FAST / 2)
/**
@ -1066,18 +1076,18 @@
#define Z_ENABLE_ON 0
#define E_ENABLE_ON 0 // For all extruders
// Disables axis stepper immediately when it's not being used.
// Disable axis steppers immediately when they're not being stepped.
// WARNING: When motors turn off there is a chance of losing position accuracy!
#define DISABLE_X false
#define DISABLE_Y false
#define DISABLE_Z false
// Warn on display about possibly reduced accuracy
// Turn off the display blinking that warns about possible accuracy reduction
//#define DISABLE_REDUCED_ACCURACY_WARNING
// @section extruder
#define DISABLE_E false // For all extruders
#define DISABLE_E false // Disable the extruder when not stepping
#define DISABLE_INACTIVE_EXTRUDER // Keep only the active extruder enabled
// @section machine
@ -1168,10 +1178,11 @@
*/
//#define FILAMENT_RUNOUT_SENSOR
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
#define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each.
#define FIL_RUNOUT_STATE LOW // Pin state indicating that filament is NOT present.
#define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins.
//#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins.
#define FIL_RUNOUT_ENABLED_DEFAULT true // Enable the sensor on startup. Override with M412 followed by M500.
#define NUM_RUNOUT_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_RUNOUT#_PIN for each.
#define FIL_RUNOUT_STATE LOW // Pin state indicating that filament is NOT present.
#define FIL_RUNOUT_PULLUP // Use internal pullup for filament runout pins.
//#define FIL_RUNOUT_PULLDOWN // Use internal pulldown for filament runout pins.
// Set one or more commands to execute on filament runout.
// (After 'M412 H' Marlin will ask the host to handle the process.)
@ -1388,7 +1399,7 @@
#define Z_SAFE_HOMING_Y_POINT Y_CENTER // Y point for Z homing
#endif
// Homing speeds (mm/m)
// Homing speeds (mm/min)
#define HOMING_FEEDRATE_XY (50*60)
#define HOMING_FEEDRATE_Z (4*60)
@ -1593,9 +1604,12 @@
// Move the nozzle to the initial position after cleaning
#define NOZZLE_CLEAN_GOBACK
// Enable for a purge/clean station that's always at the gantry height (thus no Z move)
// For a purge/clean station that's always at the gantry height (thus no Z move)
//#define NOZZLE_CLEAN_NO_Z
// For a purge/clean station mounted on the X axis
//#define NOZZLE_CLEAN_NO_Y
// Explicit wipe G-code script applies to a G12 with no arguments.
//#define WIPE_SEQUENCE_COMMANDS "G1 X-17 Y25 Z10 F4000\nG1 Z1\nM114\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 X-17 Y25\nG1 X-17 Y95\nG1 Z15\nM400\nG0 X-10.0 Y-9.0"
@ -1632,6 +1646,37 @@
*/
//#define PRINTCOUNTER
/**
* Password
*
* Set a numerical password for the printer which can be requested:
*
* - When the printer boots up
* - Upon opening the 'Print from Media' Menu
* - When SD printing is completed or aborted
*
* The following G-codes can be used:
*
* M510 - Lock Printer. Blocks all commands except M511.
* M511 - Unlock Printer.
* M512 - Set, Change and Remove Password.
*
* If you forget the password and get locked out you'll need to re-flash
* the firmware with the feature disabled, reset EEPROM, and (optionally)
* re-flash the firmware again with this feature enabled.
*/
//#define PASSWORD_FEATURE
#if ENABLED(PASSWORD_FEATURE)
#define PASSWORD_LENGTH 4 // (#) Number of digits (1-9). 3 or 4 is recommended
#define PASSWORD_ON_STARTUP
#define PASSWORD_UNLOCK_GCODE // Unlock with the M511 P<password> command. Disable to prevent brute-force attack.
#define PASSWORD_CHANGE_GCODE // Change the password with M512 P<old> S<new>.
//#define PASSWORD_ON_SD_PRINT_MENU // This does not prevent gcodes from running
//#define PASSWORD_AFTER_SD_PRINT_END
//#define PASSWORD_AFTER_SD_PRINT_ABORT
//#include "Configuration_Secure.h" // External file with PASSWORD_DEFAULT_VALUE
#endif
//=============================================================================
//============================= LCD and SD support ============================
//=============================================================================
@ -1644,7 +1689,7 @@
* Select the language to display on the LCD. These languages are available:
*
* en, an, bg, ca, cz, da, de, el, el_gr, es, eu, fi, fr, gl, hr, hu, it,
* jp_kana, ko_KR, nl, pl, pt, pt_br, ro ru, sk, tr, uk, vi, zh_CN, zh_TW, test
* jp_kana, ko_KR, nl, pl, pt, pt_br, ro, ru, sk, tr, uk, vi, zh_CN, zh_TW, test
*
* :{ 'en':'English', 'an':'Aragonese', 'bg':'Bulgarian', 'ca':'Catalan', 'cz':'Czech', 'da':'Danish', 'de':'German', 'el':'Greek', 'el_gr':'Greek (Greece)', 'es':'Spanish', 'eu':'Basque-Euskera', 'fi':'Finnish', 'fr':'French', 'gl':'Galician', 'hr':'Croatian', 'hu':'Hungarian', 'it':'Italian', 'jp_kana':'Japanese', 'ko_KR':'Korean (South Korea)', 'nl':'Dutch', 'pl':'Polish', 'pt':'Portuguese', 'pt_br':'Portuguese (Brazilian)', 'ro':'Romanian', 'ru':'Russian', 'sk':'Slovak', 'tr':'Turkish', 'uk':'Ukrainian', 'vi':'Vietnamese', 'zh_CN':'Chinese (Simplified)', 'zh_TW':'Chinese (Traditional)', 'test':'TEST' }
*/
@ -1675,9 +1720,9 @@
#define DISPLAY_CHARSET_HD44780 JAPANESE
/**
* Info Screen Style (0:Classic, 1:Prusa)
* Info Screen Style (0:Classic, 1:Průša)
*
* :[0:'Classic', 1:'Prusa']
* :[0:'Classic', 1:'Průša']
*/
#define LCD_INFO_SCREEN_STYLE 0
@ -2017,7 +2062,7 @@
//#define FYSETC_MINI_12864_X_X // Type C/D/E/F. No tunable RGB Backlight by default
//#define FYSETC_MINI_12864_1_2 // Type C/D/E/F. Simple RGB Backlight (always on)
//#define FYSETC_MINI_12864_2_0 // Type A/B. Discreet RGB Backlight
//#define FYSETC_MINI_12864_2_1 // Type A/B. Neopixel RGB Backlight
//#define FYSETC_MINI_12864_2_1 // Type A/B. NeoPixel RGB Backlight
//#define FYSETC_GENERIC_12864_1_1 // Larger display with basic ON/OFF backlight.
//
@ -2079,7 +2124,7 @@
//#define OLED_PANEL_TINYBOY2
//
// MKS OLED 1.3" 128 × 64 FULL GRAPHICS CONTROLLER
// MKS OLED 1.3" 128×64 FULL GRAPHICS CONTROLLER
// https://reprap.org/wiki/MKS_12864OLED
//
// Tiny, but very sharp OLED display
@ -2087,6 +2132,13 @@
//#define MKS_12864OLED // Uses the SH1106 controller (default)
//#define MKS_12864OLED_SSD1306 // Uses the SSD1306 controller
//
// Zonestar OLED 128×64 FULL GRAPHICS CONTROLLER
//
//#define ZONESTAR_12864LCD // Graphical (DOGM) with ST7920 controller
//#define ZONESTAR_12864OLED // 1.3" OLED with SH1106 controller (default)
//#define ZONESTAR_12864OLED_SSD1306 // 0.96" OLED with SSD1306 controller
//
// Einstart S OLED SSD1306
//
@ -2098,7 +2150,7 @@
//#define OVERLORD_OLED
//
// FYSETC OLED 2.42" 128 × 64 FULL GRAPHICS CONTROLLER with WS2812 RGB
// FYSETC OLED 2.42" 128×64 FULL GRAPHICS CONTROLLER with WS2812 RGB
// Where to find : https://www.aliexpress.com/item/4000345255731.html
//#define FYSETC_242_OLED_12864 // Uses the SSD1309 controller
@ -2126,6 +2178,16 @@
//
//#define TOUCH_UI_FTDI_EVE
//
// Touch-screen LCD for Anycubic printers
//
//#define ANYCUBIC_LCD_I3MEGA
//#define ANYCUBIC_LCD_CHIRON
#if EITHER(ANYCUBIC_LCD_I3MEGA, ANYCUBIC_LCD_CHIRON)
#define ANYCUBIC_LCD_SERIAL_PORT 3
//#define ANYCUBIC_LCD_DEBUG
#endif
//
// Third-party or vendor-customized controller interfaces.
// Sources should be installed in 'src/lcd/extensible_ui'.
@ -2140,6 +2202,28 @@
//=============================== Graphical TFTs ==============================
//=============================================================================
//
// TFT display with optional touch screen
// Color Marlin UI with standard menu system
//
//#define TFT_320x240
//#define TFT_320x240_SPI
//#define TFT_480x320
//#define TFT_480x320_SPI
//
// Skip autodetect and force specific TFT driver
// Mandatory for SPI screens with no MISO line
// Available drivers are: ST7735, ST7789, ST7796, R61505, ILI9328, ILI9341, ILI9488
//
//#define TFT_DRIVER AUTO
//
// SPI display (MKS Robin Nano V2.0, MKS Gen L V2.0)
// Upscaled 128x64 Marlin UI
//
//#define SPI_GRAPHICAL_TFT
//
// FSMC display (MKS Robin, Alfawise U20, JGAurora A5S, REXYZ A1, etc.)
// Upscaled 128x64 Marlin UI
@ -2156,12 +2240,6 @@
//#define TFT_LVGL_UI_FSMC // Robin nano v1.2 uses FSMC
//#define TFT_LVGL_UI_SPI // Robin nano v2.0 uses SPI
//
// Anycubic Mega TFT (AI3M)
//
//#define ANYCUBIC_TFT_MODEL
//#define ANYCUBIC_TFT_DEBUG
//=============================================================================
//============================ Other Controllers ============================
//=============================================================================
@ -2174,20 +2252,22 @@
//
// ADS7843/XPT2046 ADC Touchscreen such as ILI9341 2.8
//
//#define TOUCH_BUTTONS
#if ENABLED(TOUCH_BUTTONS)
//#define TOUCH_SCREEN
#if ENABLED(TOUCH_SCREEN)
#define BUTTON_DELAY_EDIT 50 // (ms) Button repeat delay for edit screens
#define BUTTON_DELAY_MENU 250 // (ms) Button repeat delay for menus
#define XPT2046_X_CALIBRATION 12316
#define XPT2046_Y_CALIBRATION -8981
#define XPT2046_X_OFFSET -43
#define XPT2046_Y_OFFSET 257
#define TOUCH_SCREEN_CALIBRATION
//#define XPT2046_X_CALIBRATION 12316
//#define XPT2046_Y_CALIBRATION -8981
//#define XPT2046_X_OFFSET -43
//#define XPT2046_Y_OFFSET 257
#endif
//
// RepRapWorld REPRAPWORLD_KEYPAD v1.1
// https://reprapworld.com/?products_details&products_id=202&cPath=1591_1626
// https://reprapworld.com/products/electronics/ramps/keypad_v1_0_fully_assembled/
//
//#define REPRAPWORLD_KEYPAD
//#define REPRAPWORLD_KEYPAD_MOVE_STEP 10.0 // (mm) Distance to move per key-press
@ -2198,6 +2278,10 @@
// @section extras
// Set number of user-controlled fans. Disable to use all board-defined fans.
// :[1,2,3,4,5,6,7,8]
//#define NUM_M106_FANS 1
// Increase the FAN PWM frequency. Removes the PWM noise but increases heating in the FET/Arduino
//#define FAST_PWM_FAN
@ -2248,13 +2332,13 @@
* Adds the M150 command to set the LED (or LED strip) color.
* If pins are PWM capable (e.g., 4, 5, 6, 11) then a range of
* luminance values can be set from 0 to 255.
* For Neopixel LED an overall brightness parameter is also available.
* For NeoPixel LED an overall brightness parameter is also available.
*
* *** CAUTION ***
* LED Strips require a MOSFET Chip between PWM lines and LEDs,
* as the Arduino cannot handle the current the LEDs will require.
* Failure to follow this precaution can destroy your Arduino!
* NOTE: A separate 5V power supply is required! The Neopixel LED needs
* NOTE: A separate 5V power supply is required! The NeoPixel LED needs
* more current than the Arduino 5V linear regulator can produce.
* *** CAUTION ***
*
@ -2271,19 +2355,29 @@
//#define RGB_LED_W_PIN -1
#endif
// Support for Adafruit Neopixel LED driver
// Support for Adafruit NeoPixel LED driver
//#define NEOPIXEL_LED
#if ENABLED(NEOPIXEL_LED)
#define NEOPIXEL_TYPE NEO_GRBW // NEO_GRBW / NEO_GRB - four/three channel driver type (defined in Adafruit_NeoPixel.h)
#define NEOPIXEL_PIN 4 // LED driving pin
//#define NEOPIXEL2_TYPE NEOPIXEL_TYPE
//#define NEOPIXEL2_PIN 5
#define NEOPIXEL_PIXELS 30 // Number of LEDs in the strip, larger of 2 strips if 2 neopixel strips are used
#define NEOPIXEL_PIXELS 30 // Number of LEDs in the strip. (Longest strip when NEOPIXEL2_SEPARATE is disabled.)
#define NEOPIXEL_IS_SEQUENTIAL // Sequential display for temperature change - LED by LED. Disable to change all LEDs at once.
#define NEOPIXEL_BRIGHTNESS 127 // Initial brightness (0-255)
//#define NEOPIXEL_STARTUP_TEST // Cycle through colors at startup
// Use a single Neopixel LED for static (background) lighting
// Support for second Adafruit NeoPixel LED driver controlled with M150 S1 ...
//#define NEOPIXEL2_SEPARATE
#if ENABLED(NEOPIXEL2_SEPARATE)
#define NEOPIXEL2_PIXELS 15 // Number of LEDs in the second strip
#define NEOPIXEL2_BRIGHTNESS 127 // Initial brightness (0-255)
#define NEOPIXEL2_STARTUP_TEST // Cycle through colors at startup
#else
//#define NEOPIXEL2_INSERIES // Default behavior is NeoPixel 2 in parallel
#endif
// Use a single NeoPixel LED for static (background) lighting
//#define NEOPIXEL_BKGD_LED_INDEX 0 // Index of the LED to use
//#define NEOPIXEL_BKGD_COLOR { 255, 255, 255, 0 } // R, G, B, W
#endif

View File

@ -339,7 +339,7 @@
#if ENABLED(EXTRUDER_RUNOUT_PREVENT)
#define EXTRUDER_RUNOUT_MINTEMP 190
#define EXTRUDER_RUNOUT_SECONDS 30
#define EXTRUDER_RUNOUT_SPEED 1500 // (mm/m)
#define EXTRUDER_RUNOUT_SPEED 1500 // (mm/min)
#define EXTRUDER_RUNOUT_EXTRUDE 5 // (mm)
#endif
@ -488,7 +488,7 @@
//#define CASE_LIGHT_MAX_PWM 128 // Limit pwm
//#define CASE_LIGHT_MENU // Add Case Light options to the LCD menu
//#define CASE_LIGHT_NO_BRIGHTNESS // Disable brightness control. Enable for non-PWM lighting.
//#define CASE_LIGHT_USE_NEOPIXEL // Use Neopixel LED as case light, requires NEOPIXEL_LED.
//#define CASE_LIGHT_USE_NEOPIXEL // Use NeoPixel LED as case light, requires NEOPIXEL_LED.
#if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
#define CASE_LIGHT_NEOPIXEL_COLOR { 255, 255, 255, 255 } // { Red, Green, Blue, White }
#endif
@ -680,7 +680,7 @@
* Danger: Don't activate 5V mode unless attached to a 5V-tolerant controller!
* V3.0 or 3.1: Set default mode to 5V mode at Marlin startup.
* If disabled, OD mode is the hard-coded default on 3.0
* On startup, Marlin will compare its eeprom to this vale. If the selected mode
* On startup, Marlin will compare its eeprom to this value. If the selected mode
* differs, a mode set eeprom write will be completed at initialization.
* Use the option below to force an eeprom write to a V3.1 probe regardless.
*/
@ -769,7 +769,7 @@
#endif
//
// Add the G35 command to read bed corners to help adjust screws.
// Add the G35 command to read bed corners to help adjust screws. Requires a bed probe.
//
//#define ASSISTED_TRAMMING
#if ENABLED(ASSISTED_TRAMMING)
@ -809,24 +809,30 @@
#define INVERT_Z_STEP_PIN false
#define INVERT_E_STEP_PIN false
// Default stepper release if idle. Set to 0 to deactivate.
// Steppers will shut down DEFAULT_STEPPER_DEACTIVE_TIME seconds after the last move when DISABLE_INACTIVE_? is true.
// Time can be set by M18 and M84.
/**
* Idle Stepper Shutdown
* Set DISABLE_INACTIVE_? 'true' to shut down axis steppers after an idle period.
* The Deactive Time can be overridden with M18 and M84. Set to 0 for No Timeout.
*/
#define DEFAULT_STEPPER_DEACTIVE_TIME 120
#define DISABLE_INACTIVE_X true
#define DISABLE_INACTIVE_Y true
#define DISABLE_INACTIVE_Z true // Set to false if the nozzle will fall down on your printed part when print has finished.
#define DISABLE_INACTIVE_Z true // Set 'false' if the nozzle could fall onto your printed part!
#define DISABLE_INACTIVE_E true
#define DEFAULT_MINIMUMFEEDRATE 0.0 // minimum feedrate
#define DEFAULT_MINTRAVELFEEDRATE 0.0
// If the Nozzle or Bed falls when the Z stepper is disabled, set its resting position here.
//#define Z_AFTER_DEACTIVATE Z_HOME_POS
//#define HOME_AFTER_DEACTIVATE // Require rehoming after steppers are deactivated
// Minimum time that a segment needs to take if the buffer is emptied
#define DEFAULT_MINSEGMENTTIME 20000 // (µs)
// Default Minimum Feedrates for printing and travel moves
#define DEFAULT_MINIMUMFEEDRATE 0.0 // (mm/s) Minimum feedrate. Set with M205 S.
#define DEFAULT_MINTRAVELFEEDRATE 0.0 // (mm/s) Minimum travel feedrate. Set with M205 T.
// Slow down the machine if the look ahead buffer is (by default) half full.
// Minimum time that a segment needs to take as the buffer gets emptied
#define DEFAULT_MINSEGMENTTIME 20000 // (µs) Set with M205 B.
// Slow down the machine if the lookahead buffer is (by default) half full.
// Increase the slowdown divisor for larger buffer sizes.
#define SLOWDOWN
#if ENABLED(SLOWDOWN)
@ -877,7 +883,7 @@
// increments while checking for the contact to be broken.
#define BACKLASH_MEASUREMENT_LIMIT 0.5 // (mm)
#define BACKLASH_MEASUREMENT_RESOLUTION 0.005 // (mm)
#define BACKLASH_MEASUREMENT_FEEDRATE Z_PROBE_SPEED_SLOW // (mm/m)
#define BACKLASH_MEASUREMENT_FEEDRATE Z_PROBE_SPEED_SLOW // (mm/min)
#endif
#endif
#endif
@ -903,9 +909,9 @@
#define CALIBRATION_MEASUREMENT_RESOLUTION 0.01 // mm
#define CALIBRATION_FEEDRATE_SLOW 60 // mm/m
#define CALIBRATION_FEEDRATE_FAST 1200 // mm/m
#define CALIBRATION_FEEDRATE_TRAVEL 3000 // mm/m
#define CALIBRATION_FEEDRATE_SLOW 60 // mm/min
#define CALIBRATION_FEEDRATE_FAST 1200 // mm/min
#define CALIBRATION_FEEDRATE_TRAVEL 3000 // mm/min
// The following parameters refer to the conical section of the nozzle tip.
#define CALIBRATION_NOZZLE_TIP_HEIGHT 1.0 // mm
@ -1019,7 +1025,7 @@
// @section lcd
#if EITHER(ULTIPANEL, EXTENSIBLE_UI)
#define MANUAL_FEEDRATE { 50*60, 50*60, 4*60, 60 } // Feedrates for manual moves along X, Y, Z, E from panel
#define MANUAL_FEEDRATE { 50*60, 50*60, 4*60, 2*60 } // (mm/min) Feedrates for manual moves along X, Y, Z, E from panel
#define SHORT_MANUAL_Z_MOVE 0.025 // (mm) Smallest manual Z move (< 0.1mm)
#if ENABLED(ULTIPANEL)
#define MANUAL_E_MOVES_RELATIVE // Display extruder move distance rather than "position"
@ -1059,6 +1065,7 @@
//#define LED_CONTROL_MENU
#if ENABLED(LED_CONTROL_MENU)
#define LED_COLOR_PRESETS // Enable the Preset Color menu option
//#define NEO2_COLOR_PRESETS // Enable a second NeoPixel Preset Color menu option
#if ENABLED(LED_COLOR_PRESETS)
#define LED_USER_PRESET_RED 255 // User defined RED value
#define LED_USER_PRESET_GREEN 128 // User defined GREEN value
@ -1067,6 +1074,14 @@
#define LED_USER_PRESET_BRIGHTNESS 255 // User defined intensity
//#define LED_USER_PRESET_STARTUP // Have the printer display the user preset color on startup
#endif
#if ENABLED(NEO2_COLOR_PRESETS)
#define NEO2_USER_PRESET_RED 255 // User defined RED value
#define NEO2_USER_PRESET_GREEN 128 // User defined GREEN value
#define NEO2_USER_PRESET_BLUE 0 // User defined BLUE value
#define NEO2_USER_PRESET_WHITE 255 // User defined WHITE value
#define NEO2_USER_PRESET_BRIGHTNESS 255 // User defined intensity
//#define NEO2_USER_PRESET_STARTUP // Have the printer display the user preset color on startup for the second strip
#endif
#endif
#endif // HAS_LCD_MENU
@ -1131,7 +1146,7 @@
//#define MENU_ADDAUTOSTART // Add a menu option to run auto#.g files
#define EVENT_GCODE_SD_STOP "G28XY" // G-code to run on Stop Print (e.g., "G28XY" or "G27")
#define EVENT_GCODE_SD_ABORT "G28XY" // G-code to run on SD Abort Print (e.g., "G28XY" or "G27")
#if ENABLED(PRINTER_EVENT_LEDS)
#define PE_LEDS_COMPLETED_TIME (30*60) // (seconds) Time to keep the LED "done" color before restoring normal illumination
@ -1509,9 +1524,10 @@
#endif
//
// FSMC Graphical TFT
// FSMC / SPI Graphical TFT
//
#if ENABLED(FSMC_GRAPHICAL_TFT)
#if TFT_SCALED_DOGLCD
//#define GRAPHICAL_TFT_ROTATE_180
//#define TFT_MARLINUI_COLOR 0xFFFF // White
//#define TFT_MARLINBG_COLOR 0x0000 // Black
//#define TFT_DISABLED_COLOR 0x0003 // Almost black
@ -1978,13 +1994,13 @@
// Load / Unload
#define TOOLCHANGE_FS_LENGTH 12 // (mm) Load / Unload length
#define TOOLCHANGE_FS_EXTRA_RESUME_LENGTH 0 // (mm) Extra length for better restart, fine tune by LCD/Gcode)
#define TOOLCHANGE_FS_RETRACT_SPEED (50*60) // (mm/m) (Unloading)
#define TOOLCHANGE_FS_UNRETRACT_SPEED (25*60) // (mm/m) (On SINGLENOZZLE or Bowden loading must be slowed down)
#define TOOLCHANGE_FS_RETRACT_SPEED (50*60) // (mm/min) (Unloading)
#define TOOLCHANGE_FS_UNRETRACT_SPEED (25*60) // (mm/min) (On SINGLENOZZLE or Bowden loading must be slowed down)
// Longer prime to clean out a SINGLENOZZLE
#define TOOLCHANGE_FS_EXTRA_PRIME 0 // (mm) Extra priming length
#define TOOLCHANGE_FS_PRIME_SPEED (4.6*60) // (mm/m) Extra priming feedrate
#define TOOLCHANGE_FS_WIPE_RETRACT 0 // (mm/m) Retract before cooling for less stringing, better wipe, etc.
#define TOOLCHANGE_FS_PRIME_SPEED (4.6*60) // (mm/min) Extra priming feedrate
#define TOOLCHANGE_FS_WIPE_RETRACT 0 // (mm/min) Retract before cooling for less stringing, better wipe, etc.
// Cool after prime to reduce stringing
#define TOOLCHANGE_FS_FAN -1 // Fan index or -1 to skip
@ -2020,7 +2036,7 @@
//#define TOOLCHANGE_PARK
#if ENABLED(TOOLCHANGE_PARK)
#define TOOLCHANGE_PARK_XY { X_MIN_POS + 10, Y_MIN_POS + 10 }
#define TOOLCHANGE_PARK_XY_FEEDRATE 6000 // (mm/m)
#define TOOLCHANGE_PARK_XY_FEEDRATE 6000 // (mm/min)
//#define TOOLCHANGE_PARK_X_ONLY // X axis only move
//#define TOOLCHANGE_PARK_Y_ONLY // Y axis only move
#endif
@ -2417,7 +2433,7 @@
* CHOPPER_DEFAULT_24V
* CHOPPER_DEFAULT_36V
* CHOPPER_09STEP_24V // 0.9 degree steppers (24V)
* CHOPPER_PRUSAMK3_24V // Imported parameters from the official Prusa firmware for MK3 (24V)
* CHOPPER_PRUSAMK3_24V // Imported parameters from the official Průša firmware for MK3 (24V)
* CHOPPER_MARLIN_119 // Old defaults from Marlin v1.1.9
*
* Define you own with
@ -2844,7 +2860,7 @@
//#define SPINDLE_FEATURE
//#define LASER_FEATURE
#if EITHER(SPINDLE_FEATURE, LASER_FEATURE)
#define SPINDLE_LASER_ACTIVE_HIGH false // Set to "true" if the on/off function is active HIGH
#define SPINDLE_LASER_ACTIVE_STATE LOW // Set to "HIGH" if the on/off function is active HIGH
#define SPINDLE_LASER_PWM true // Set to "true" if your controller supports setting the speed/power
#define SPINDLE_LASER_PWM_INVERT false // Set to "true" if the speed/power goes up when you want it to go slower
@ -3144,7 +3160,7 @@
//#define GCODE_MOTION_MODES // Remember the motion mode (G0 G1 G2 G3 G5 G38.X) and apply for X Y Z E F, etc.
// Enable and set a (default) feedrate for all G0 moves
//#define G0_FEEDRATE 3000 // (mm/m)
//#define G0_FEEDRATE 3000 // (mm/min)
#ifdef G0_FEEDRATE
//#define VARIABLE_G0_FEEDRATE // The G0 feedrate is set by F in G0 motion mode
#endif
@ -3389,7 +3405,7 @@
#endif
/**
* Prusa Multi-Material Unit v2
* Průša Multi-Material Unit v2
* Enable in Configuration.h
*/
#if ENABLED(PRUSA_MMU2)
@ -3413,7 +3429,7 @@
//#define MMU2_MENUS
#if ENABLED(MMU2_MENUS)
// Settings for filament load / unload from the LCD menu.
// This is for Prusa MK3-style extruders. Customize for your hardware.
// This is for Průša MK3-style extruders. Customize for your hardware.
#define MMU2_FILAMENTCHANGE_EJECT_FEED 80.0
#define MMU2_LOAD_TO_NOZZLE_SEQUENCE \
{ 7.2, 1145 }, \
@ -3439,7 +3455,7 @@
/**
* MMU Extruder Sensor
*
* Support for a Prusa (or other) IR Sensor to detect filament near the extruder
* Support for a Průša (or other) IR Sensor to detect filament near the extruder
* and make loading more reliable. Suitable for an extruder equipped with a filament
* sensor less than 38mm from the gears.
*
@ -3461,7 +3477,7 @@
#if ENABLED(PRUSA_MMU2_S_MODE)
#define MMU2_C0_RETRY 5 // Number of retries (total time = timeout*retries)
#define MMU2_CAN_LOAD_FEEDRATE 800 // (mm/m)
#define MMU2_CAN_LOAD_FEEDRATE 800 // (mm/min)
#define MMU2_CAN_LOAD_SEQUENCE \
{ 0.1, MMU2_CAN_LOAD_FEEDRATE }, \
{ 60.0, MMU2_CAN_LOAD_FEEDRATE }, \

View File

@ -120,6 +120,17 @@ typedef int8_t pin_t;
#define DGUS_SERIAL_GET_TX_BUFFER_FREE DGUS_SERIAL.get_tx_buffer_free
#endif
#ifdef ANYCUBIC_LCD_SERIAL_PORT
#if !WITHIN(ANYCUBIC_LCD_SERIAL_PORT, -1, 3)
#error "ANYCUBIC_LCD_SERIAL_PORT must be from -1 to 3. Please update your configuration."
#elif ANYCUBIC_LCD_SERIAL_PORT == SERIAL_PORT
#error "ANYCUBIC_LCD_SERIAL_PORT must be different than SERIAL_PORT. Please update your configuration."
#elif defined(SERIAL_PORT_2) && ANYCUBIC_LCD_SERIAL_PORT == SERIAL_PORT_2
#error "ANYCUBIC_LCD_SERIAL_PORT must be different than SERIAL_PORT_2. Please update your configuration."
#endif
#define ANYCUBIC_LCD_SERIAL anycubicLcdSerial
#endif
// ------------------------
// Public functions
// ------------------------

View File

@ -792,6 +792,24 @@
#endif
#ifdef ANYCUBIC_LCD_SERIAL_PORT
ISR(SERIAL_REGNAME(USART,ANYCUBIC_LCD_SERIAL_PORT,_RX_vect)) {
MarlinSerial<AnycubicLcdSerialCfg<ANYCUBIC_LCD_SERIAL_PORT>>::store_rxd_char();
}
ISR(SERIAL_REGNAME(USART,ANYCUBIC_LCD_SERIAL_PORT,_UDRE_vect)) {
MarlinSerial<AnycubicLcdSerialCfg<ANYCUBIC_LCD_SERIAL_PORT>>::_tx_udr_empty_irq();
}
// Preinstantiate
template class MarlinSerial<AnycubicLcdSerialCfg<ANYCUBIC_LCD_SERIAL_PORT>>;
// Instantiate
MarlinSerial<AnycubicLcdSerialCfg<ANYCUBIC_LCD_SERIAL_PORT>> anycubicLcdSerial;
#endif
// For AT90USB targets use the UART for BT interfacing
#if defined(USBCON) && ENABLED(BLUETOOTH)
HardwareSerial bluetoothSerial;

View File

@ -312,6 +312,23 @@
extern MarlinSerial<MarlinInternalSerialCfg<DGUS_SERIAL_PORT>> internalDgusSerial;
#endif
#ifdef ANYCUBIC_LCD_SERIAL_PORT
template <uint8_t serial>
struct AnycubicLcdSerialCfg {
static constexpr int PORT = serial;
static constexpr unsigned int RX_SIZE = 64;
static constexpr unsigned int TX_SIZE = 128;
static constexpr bool XONOFF = false;
static constexpr bool EMERGENCYPARSER = false;
static constexpr bool DROPPED_RX = false;
static constexpr bool RX_OVERRUNS = false;
static constexpr bool RX_FRAMING_ERRORS = false;
static constexpr bool MAX_RX_QUEUED = false;
};
extern MarlinSerial<AnycubicLcdSerialCfg<ANYCUBIC_LCD_SERIAL_PORT>> anycubicLcdSerial;
#endif
// Use the UART for Bluetooth in AT90USB configurations
#if defined(USBCON) && ENABLED(BLUETOOTH)
extern HardwareSerial bluetoothSerial;

View File

@ -59,10 +59,12 @@
// Say which 16 bit timers can be used and in what order
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
//#define _useTimer1
#define _useTimer3
#define _useTimer4
#if !HAS_MOTOR_CURRENT_PWM
#define _useTimer5 // Timer 5 is used for motor current PWM and can't be used for servos.
#if NUM_SERVOS > SERVOS_PER_TIMER
#define _useTimer3
#if !HAS_MOTOR_CURRENT_PWM && SERVOS > 2 * SERVOS_PER_TIMER
#define _useTimer5 // Timer 5 is used for motor current PWM and can't be used for servos.
#endif
#endif
#elif defined(__AVR_ATmega32U4__)
#define _useTimer3

View File

@ -20,3 +20,7 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/AVR."
#endif

View File

@ -36,9 +36,10 @@
* Sanity checks for Spindle / Laser PWM
*/
#if ENABLED(SPINDLE_LASER_PWM)
#include "../ServoTimers.h" // Needed to check timer availability (_useTimer3)
#if SPINDLE_LASER_PWM_PIN == 4 || WITHIN(SPINDLE_LASER_PWM_PIN, 11, 13)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by a system interrupt."
#elif NUM_SERVOS > 0 && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5)
#elif NUM_SERVOS > 0 && defined(_useTimer3) && (WITHIN(SPINDLE_LASER_PWM_PIN, 2, 3) || SPINDLE_LASER_PWM_PIN == 5)
#error "Counter/Timer for SPINDLE_LASER_PWM_PIN is used by the servo system."
#endif
#elif defined(SPINDLE_LASER_FREQUENCY)

View File

@ -15,6 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
/**

View File

@ -20,3 +20,7 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/DUE."
#endif

View File

@ -93,5 +93,5 @@
#define USB_VBOF_GPIO (PIO_PB10_IDX)
#define USB_VBOF_FLAGS (PIO_PERIPH_A | PIO_DEFAULT)
/*! Active level of the USB_VBOF output pin. */
#define USB_VBOF_ACTIVE_LEVEL LOW
#define USB_VBOF_ACTIVE_STATE LOW
/* ------------------------------------------------------------------------ */

View File

@ -20,3 +20,7 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/ESP32."
#endif

View File

@ -15,6 +15,7 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_ESP32

View File

@ -38,7 +38,7 @@
// String helper
#ifndef PGMSTR
#define PGMSTR(NAM,STR) constexpr char NAM[] = STR
#define PGMSTR(NAM,STR) const char NAM[] = STR
#endif
inline void watchdog_refresh() {

View File

@ -20,3 +20,7 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/LINUX."
#endif

View File

@ -30,7 +30,7 @@
*/
/**
* Hardware SPI and a software SPI implementations are included in this file.
* Hardware SPI and Software SPI implementations are included in this file.
* The hardware SPI runs faster and has higher throughput but is not compatible
* with some LCD interfaces/adapters.
*
@ -51,6 +51,10 @@
#include "../../inc/MarlinConfig.h"
#include <SPI.h>
// Hardware SPI and SPIClass
#include <lpc17xx_pinsel.h>
#include <lpc17xx_clkpwr.h>
// ------------------------
// Public functions
// ------------------------
@ -96,12 +100,6 @@
#else
// Hardware SPI
#include <lpc17xx_pinsel.h>
#include <lpc17xx_ssp.h>
#include <lpc17xx_clkpwr.h>
// decide which HW SPI device to use
#ifndef LPC_HW_SPI_DEV
#if (SCK_PIN == P0_07 && MISO_PIN == P0_08 && MOSI_PIN == P0_09)
@ -114,7 +112,7 @@
#endif
#endif
#endif
#if (LPC_HW_SPI_DEV == 0)
#if LPC_HW_SPI_DEV == 0
#define LPC_SSPn LPC_SSP0
#else
#define LPC_SSPn LPC_SSP1
@ -192,7 +190,7 @@
for (uint16_t i = 0; i < nbyte; i++) buf[i] = doio(0xFF);
}
static uint8_t spiTransfer(uint8_t b) {
uint8_t spiTransfer(uint8_t b) {
return doio(b);
}
@ -211,30 +209,236 @@
#endif // LPC_SOFTWARE_SPI
void SPIClass::begin() { spiBegin(); }
void SPIClass::beginTransaction(const SPISettings &cfg) {
uint8_t spiRate;
switch (cfg.spiRate()) {
case 8000000: spiRate = 0; break;
case 4000000: spiRate = 1; break;
case 2000000: spiRate = 2; break;
case 1000000: spiRate = 3; break;
case 500000: spiRate = 4; break;
case 250000: spiRate = 5; break;
case 125000: spiRate = 6; break;
default: spiRate = 2; break;
}
spiInit(spiRate);
/**
* @brief Wait until TXE (tx empty) flag is set and BSY (busy) flag unset.
*/
static inline void waitSpiTxEnd(LPC_SSP_TypeDef *spi_d) {
while (SSP_GetStatus(spi_d, SSP_STAT_TXFIFO_EMPTY) == RESET) { /* nada */ } // wait until TXE=1
while (SSP_GetStatus(spi_d, SSP_STAT_BUSY) == SET) { /* nada */ } // wait until BSY=0
}
uint8_t SPIClass::transfer(const uint8_t B) { return spiTransfer(B); }
SPIClass::SPIClass(uint8_t device) {
// Init things specific to each SPI device
// clock divider setup is a bit of hack, and needs to be improved at a later date.
PINSEL_CFG_Type PinCfg; // data structure to hold init values
#if BOARD_NR_SPI >= 1
_settings[0].spi_d = LPC_SSP0;
// _settings[0].clockDivider = determine_baud_rate(_settings[0].spi_d, _settings[0].clock);
PinCfg.Funcnum = 2;
PinCfg.OpenDrain = 0;
PinCfg.Pinmode = 0;
PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_SCK_PIN);
PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_SCK_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_OUTPUT(BOARD_SPI1_SCK_PIN);
PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MISO_PIN);
PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MISO_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_INPUT(BOARD_SPI1_MISO_PIN);
PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI1_MOSI_PIN);
PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI1_MOSI_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_OUTPUT(BOARD_SPI1_MOSI_PIN);
#endif
#if BOARD_NR_SPI >= 2
_settings[1].spi_d = LPC_SSP1;
// _settings[1].clockDivider = determine_baud_rate(_settings[1].spi_d, _settings[1].clock);
PinCfg.Funcnum = 2;
PinCfg.OpenDrain = 0;
PinCfg.Pinmode = 0;
PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_SCK_PIN);
PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_SCK_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_OUTPUT(BOARD_SPI2_SCK_PIN);
PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MISO_PIN);
PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MISO_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_INPUT(BOARD_SPI2_MISO_PIN);
PinCfg.Pinnum = LPC176x::pin_bit(BOARD_SPI2_MOSI_PIN);
PinCfg.Portnum = LPC176x::pin_port(BOARD_SPI2_MOSI_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_OUTPUT(BOARD_SPI2_MOSI_PIN);
#endif
setModule(device);
/* Initialize GPDMA controller */
//TODO: call once in the constructor? or each time?
GPDMA_Init();
}
void SPIClass::begin() {
updateSettings();
SSP_Cmd(_currentSetting->spi_d, ENABLE); // start SSP running
}
void SPIClass::beginTransaction(const SPISettings &cfg) {
setBitOrder(cfg.bitOrder);
setDataMode(cfg.dataMode);
setDataSize(cfg.dataSize);
//setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock));
begin();
}
uint8_t SPIClass::transfer(const uint16_t b) {
/* send and receive a single byte */
SSP_ReceiveData(_currentSetting->spi_d); // read any previous data
SSP_SendData(_currentSetting->spi_d, b);
waitSpiTxEnd(_currentSetting->spi_d); // wait for it to finish
return SSP_ReceiveData(_currentSetting->spi_d);
}
uint16_t SPIClass::transfer16(const uint16_t data) {
return (transfer((data >> 8) & 0xFF) << 8)
| (transfer(data & 0xFF) & 0xFF);
}
SPIClass SPI;
void SPIClass::end() {
// SSP_Cmd(_currentSetting->spi_d, DISABLE); // stop device or SSP_DeInit?
SSP_DeInit(_currentSetting->spi_d);
}
void SPIClass::send(uint8_t data) {
SSP_SendData(_currentSetting->spi_d, data);
}
void SPIClass::dmaSend(void *buf, uint16_t length, bool minc) {
//TODO: LPC dma can only write 0xFFF bytes at once.
GPDMA_Channel_CFG_Type GPDMACfg;
/* Configure GPDMA channel 0 -------------------------------------------------------------*/
/* DMA Channel 0 */
GPDMACfg.ChannelNum = 0;
// Source memory
GPDMACfg.SrcMemAddr = (uint32_t)buf;
// Destination memory - Not used
GPDMACfg.DstMemAddr = 0;
// Transfer size
GPDMACfg.TransferSize = (minc ? length : 1);
// Transfer width
GPDMACfg.TransferWidth = (_currentSetting->dataSize == DATA_SIZE_16BIT) ? GPDMA_WIDTH_HALFWORD : GPDMA_WIDTH_BYTE;
// Transfer type
GPDMACfg.TransferType = GPDMA_TRANSFERTYPE_M2P;
// Source connection - unused
GPDMACfg.SrcConn = 0;
// Destination connection
GPDMACfg.DstConn = (_currentSetting->spi_d == LPC_SSP0) ? GPDMA_CONN_SSP0_Tx : GPDMA_CONN_SSP1_Tx;
GPDMACfg.DMALLI = 0;
// Enable dma on SPI
SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, ENABLE);
// if minc=false, I'm repeating the same byte 'length' times, as I could not find yet how do GPDMA without memory increment
do {
// Setup channel with given parameter
GPDMA_Setup(&GPDMACfg);
// enabled dma
GPDMA_ChannelCmd(0, ENABLE);
// wait data transfer
while (!GPDMA_IntGetStatus(GPDMA_STAT_INTTC, 0) && !GPDMA_IntGetStatus(GPDMA_STAT_INTERR, 0)) { }
// clear err and int
GPDMA_ClearIntPending (GPDMA_STATCLR_INTTC, 0);
GPDMA_ClearIntPending (GPDMA_STATCLR_INTERR, 0);
// dma disable
GPDMA_ChannelCmd(0, DISABLE);
--length;
} while (!minc && length > 0);
waitSpiTxEnd(_currentSetting->spi_d);
SSP_DMACmd(_currentSetting->spi_d, SSP_DMA_TX, DISABLE);
}
uint16_t SPIClass::read() {
return SSP_ReceiveData(_currentSetting->spi_d);
}
void SPIClass::read(uint8_t *buf, uint32_t len) {
for (uint16_t i = 0; i < len; i++) buf[i] = transfer(0xFF);
}
void SPIClass::setClock(uint32_t clock) {
_currentSetting->clock = clock;
}
void SPIClass::setModule(uint8_t device) {
_currentSetting = &_settings[device - 1];// SPI channels are called 1 2 and 3 but the array is zero indexed
}
void SPIClass::setBitOrder(uint8_t bitOrder) {
_currentSetting->bitOrder = bitOrder;
}
void SPIClass::setDataMode(uint8_t dataMode) {
_currentSetting->dataSize = dataMode;
}
void SPIClass::setDataSize(uint32_t ds) {
_currentSetting->dataSize = ds;
}
/**
* Set up/tear down
*/
void SPIClass::updateSettings() {
//SSP_DeInit(_currentSetting->spi_d); //todo: need force de init?!
// divide PCLK by 2 for SSP0
CLKPWR_SetPCLKDiv(_currentSetting->spi_d == LPC_SSP0 ? CLKPWR_PCLKSEL_SSP0 : CLKPWR_PCLKSEL_SSP1, CLKPWR_PCLKSEL_CCLK_DIV_2);
SSP_CFG_Type HW_SPI_init; // data structure to hold init values
SSP_ConfigStructInit(&HW_SPI_init); // set values for SPI mode
HW_SPI_init.ClockRate = _currentSetting->clock;
HW_SPI_init.Databit = _currentSetting->dataSize;
/**
* SPI Mode CPOL CPHA Shift SCK-edge Capture SCK-edge
* 0 0 0 Falling Rising
* 1 0 1 Rising Falling
* 2 1 0 Rising Falling
* 3 1 1 Falling Rising
*/
switch (_currentSetting->dataMode) {
case SPI_MODE0:
HW_SPI_init.CPHA = SSP_CPHA_FIRST;
HW_SPI_init.CPOL = SSP_CPOL_HI;
break;
case SPI_MODE1:
HW_SPI_init.CPHA = SSP_CPHA_SECOND;
HW_SPI_init.CPOL = SSP_CPOL_HI;
break;
case SPI_MODE2:
HW_SPI_init.CPHA = SSP_CPHA_FIRST;
HW_SPI_init.CPOL = SSP_CPOL_LO;
break;
case SPI_MODE3:
HW_SPI_init.CPHA = SSP_CPHA_SECOND;
HW_SPI_init.CPOL = SSP_CPOL_LO;
break;
default:
break;
}
// TODO: handle bitOrder
SSP_Init(_currentSetting->spi_d, &HW_SPI_init); // puts the values into the proper bits in the SSP0 registers
}
#if MISO_PIN == BOARD_SPI1_MISO_PIN
SPIClass SPI(1);
#elif MISO_PIN == BOARD_SPI2_MISO_PIN
SPIClass SPI(2);
#endif
#endif // TARGET_LPC1768

View File

@ -20,3 +20,14 @@
*
*/
#pragma once
#if HAS_FSMC_TFT
#error "Sorry! FSMC TFT displays are not current available for HAL/LPC1768."
#endif
// This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046'
#if ENABLED(TOUCH_SCREEN) && !HAS_GRAPHICAL_TFT
#undef TOUCH_SCREEN
#undef TOUCH_SCREEN_CALIBRATION
#define HAS_TOUCH_XPT2046 1
#endif

View File

@ -24,25 +24,139 @@
#include "../../shared/HAL_SPI.h"
#include <stdint.h>
#include <lpc17xx_ssp.h>
#include <lpc17xx_gpdma.h>
#define MSBFIRST 1
#define SPI_MODE3 0
//#define MSBFIRST 1
#define SPI_MODE0 0
#define SPI_MODE1 1
#define SPI_MODE2 2
#define SPI_MODE3 3
#define DATA_SIZE_8BIT SSP_DATABIT_8
#define DATA_SIZE_16BIT SSP_DATABIT_16
#define SPI_CLOCK_DIV2 8333333 //(SCR: 2) desired: 8,000,000 actual: 8,333,333 +4.2% SPI_FULL_SPEED
#define SPI_CLOCK_DIV4 4166667 //(SCR: 5) desired: 4,000,000 actual: 4,166,667 +4.2% SPI_HALF_SPEED
#define SPI_CLOCK_DIV8 2083333 //(SCR: 11) desired: 2,000,000 actual: 2,083,333 +4.2% SPI_QUARTER_SPEED
#define SPI_CLOCK_DIV16 1000000 //(SCR: 24) desired: 1,000,000 actual: 1,000,000 SPI_EIGHTH_SPEED
#define SPI_CLOCK_DIV32 500000 //(SCR: 49) desired: 500,000 actual: 500,000 SPI_SPEED_5
#define SPI_CLOCK_DIV64 250000 //(SCR: 99) desired: 250,000 actual: 250,000 SPI_SPEED_6
#define SPI_CLOCK_DIV128 125000 //(SCR:199) desired: 125,000 actual: 125,000 Default from HAL.h
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
#define BOARD_NR_SPI 2
//#define BOARD_SPI1_NSS_PIN PA4 ?!
#define BOARD_SPI1_SCK_PIN P0_15
#define BOARD_SPI1_MISO_PIN P0_17
#define BOARD_SPI1_MOSI_PIN P0_18
//#define BOARD_SPI2_NSS_PIN PB12 ?!
#define BOARD_SPI2_SCK_PIN P0_07
#define BOARD_SPI2_MISO_PIN P0_08
#define BOARD_SPI2_MOSI_PIN P0_09
class SPISettings {
public:
SPISettings(uint32_t speed, int, int) : spi_speed(speed) {};
uint32_t spiRate() const { return spi_speed; }
private:
uint32_t spi_speed;
public:
SPISettings(uint32_t speed, int, int) : spi_speed(speed) {};
SPISettings(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
if (__builtin_constant_p(inClock))
init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
else
init_MightInline(inClock, inBitOrder, inDataMode, inDataSize);
}
SPISettings() {
init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0, DATA_SIZE_8BIT);
}
uint32_t spiRate() const { return spi_speed; }
private:
void init_MightInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) {
init_AlwaysInline(inClock, inBitOrder, inDataMode, inDataSize);
}
void init_AlwaysInline(uint32_t inClock, uint8_t inBitOrder, uint8_t inDataMode, uint32_t inDataSize) __attribute__((__always_inline__)) {
clock = inClock;
bitOrder = inBitOrder;
dataMode = inDataMode;
dataSize = inDataSize;
}
uint32_t spi_speed;
uint32_t clock;
uint32_t dataSize;
//uint32_t clockDivider;
uint8_t bitOrder;
uint8_t dataMode;
LPC_SSP_TypeDef *spi_d;
friend class SPIClass;
};
/**
* @brief Wirish SPI interface.
*
* This is the same interface is available across HAL
*
* This implementation uses software slave management, so the caller
* is responsible for controlling the slave select line.
*/
class SPIClass {
public:
void begin();
void beginTransaction(const SPISettings&);
void endTransaction() {};
uint8_t transfer(uint8_t data);
uint16_t transfer16(uint16_t data);
public:
/**
* @param spiPortNumber Number of the SPI port to manage.
*/
SPIClass(uint8_t spiPortNumber);
/**
* Select and configure the current selected SPI device to use
*/
void begin();
/**
* Disable the current SPI device
*/
void end();
void beginTransaction(const SPISettings&);
void endTransaction() {};
// Transfer using 1 "Data Size"
uint8_t transfer(uint16_t data);
// Transfer 2 bytes in 8 bit mode
uint16_t transfer16(uint16_t data);
void send(uint8_t data);
uint16_t read();
void read(uint8_t *buf, uint32_t len);
void dmaSend(void *buf, uint16_t length, bool minc);
/**
* @brief Sets the number of the SPI peripheral to be used by
* this HardwareSPI instance.
*
* @param spi_num Number of the SPI port. 1-2 in low density devices
* or 1-3 in high density devices.
*/
void setModule(uint8_t device);
void setClock(uint32_t clock);
void setBitOrder(uint8_t bitOrder);
void setDataMode(uint8_t dataMode);
void setDataSize(uint32_t ds);
inline uint32_t getDataSize() { return _currentSetting->dataSize; }
private:
SPISettings _settings[BOARD_NR_SPI];
SPISettings *_currentSetting;
void updateSettings();
};
extern SPIClass SPI;

View File

@ -0,0 +1,153 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_SPI_TFT
#include "tft_spi.h"
//TFT_SPI tft;
SPIClass TFT_SPI::SPIx(1);
#define TFT_CS_H WRITE(TFT_CS_PIN, HIGH)
#define TFT_CS_L WRITE(TFT_CS_PIN, LOW)
#define TFT_DC_H WRITE(TFT_DC_PIN, HIGH)
#define TFT_DC_L WRITE(TFT_DC_PIN, LOW)
#define TFT_RST_H WRITE(TFT_RESET_PIN, HIGH)
#define TFT_RST_L WRITE(TFT_RESET_PIN, LOW)
#define TFT_BLK_H WRITE(TFT_BACKLIGHT_PIN, HIGH)
#define TFT_BLK_L WRITE(TFT_BACKLIGHT_PIN, LOW)
void TFT_SPI::Init() {
#if PIN_EXISTS(TFT_RESET)
SET_OUTPUT(TFT_RESET_PIN);
TFT_RST_H;
delay(100);
#endif
#if PIN_EXISTS(TFT_BACKLIGHT)
SET_OUTPUT(TFT_BACKLIGHT_PIN);
TFT_BLK_H;
#endif
SET_OUTPUT(TFT_DC_PIN);
SET_OUTPUT(TFT_CS_PIN);
TFT_DC_H;
TFT_CS_H;
/**
* STM32F1 APB2 = 72MHz, APB1 = 36MHz, max SPI speed of this MCU if 18Mhz
* STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1
* so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2
*/
#if 0
#if SPI_DEVICE == 1
#define SPI_CLOCK_MAX SPI_CLOCK_DIV4
#else
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
#endif
uint8_t clock;
uint8_t spiRate = SPI_FULL_SPEED;
switch (spiRate) {
case SPI_FULL_SPEED: clock = SPI_CLOCK_MAX ; break;
case SPI_HALF_SPEED: clock = SPI_CLOCK_DIV4 ; break;
case SPI_QUARTER_SPEED: clock = SPI_CLOCK_DIV8 ; break;
case SPI_EIGHTH_SPEED: clock = SPI_CLOCK_DIV16; break;
case SPI_SPEED_5: clock = SPI_CLOCK_DIV32; break;
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
default: clock = SPI_CLOCK_DIV2; // Default from the SPI library
}
#endif
#if TFT_MISO_PIN == BOARD_SPI1_MISO_PIN
SPIx.setModule(1);
#elif TFT_MISO_PIN == BOARD_SPI2_MISO_PIN
SPIx.setModule(2);
#endif
SPIx.setClock(SPI_CLOCK_MAX);
SPIx.setBitOrder(MSBFIRST);
SPIx.setDataMode(SPI_MODE0);
}
void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
SPIx.setDataSize(DataSize);
SPIx.begin();
TFT_CS_L;
}
uint32_t TFT_SPI::GetID() {
uint32_t id;
id = ReadID(LCD_READ_ID);
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = ReadID(LCD_READ_ID4);
return id;
}
uint32_t TFT_SPI::ReadID(uint16_t Reg) {
uint32_t data = 0;
#if PIN_EXISTS(TFT_MISO)
uint8_t d = 0;
SPIx.setDataSize(DATASIZE_8BIT);
SPIx.setClock(SPI_CLOCK_DIV64);
SPIx.begin();
TFT_CS_L;
WriteReg(Reg);
LOOP_L_N(i, 4) {
SPIx.read((uint8_t*)&d, 1);
data = (data << 8) | d;
}
DataTransferEnd();
SPIx.setClock(SPI_CLOCK_MAX);
#endif
return data >> 7;
}
bool TFT_SPI::isBusy() {
return false;
}
void TFT_SPI::Abort() {
DataTransferEnd();
}
void TFT_SPI::Transmit(uint16_t Data) {
SPIx.transfer(Data);
}
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DataTransferBegin(DATASIZE_16BIT); //16
TFT_DC_H;
SPIx.dmaSend(Data, Count, MemoryIncrease);
DataTransferEnd();
}
#endif // HAS_SPI_TFT

View File

@ -0,0 +1,77 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfig.h"
#include <SPI.h>
#include <lpc17xx_ssp.h>
// #include <lpc17xx_gpdma.h>
#ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
#ifndef LCD_READ_ID4
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif
#define DATASIZE_8BIT SSP_DATABIT_8
#define DATASIZE_16BIT SSP_DATABIT_16
#define TFT_IO TFT_SPI
#define DMA_MINC_ENABLE 1
#define DMA_MINC_DISABLE 0
class TFT_SPI {
private:
static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public:
static SPIClass SPIx;
static void Init();
static uint32_t GetID();
static bool isBusy();
static void Abort();
static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT);
static void DataTransferEnd() { OUT_WRITE(TFT_CS_PIN, HIGH); SPIx.end(); };
static void DataTransferAbort();
static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg) { OUT_WRITE(TFT_A0_PIN, LOW); Transmit(Reg); OUT_WRITE(TFT_A0_PIN, HIGH); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
// static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
//LPC dma can only write 0xFFF bytes at once.
#define MAX_DMA_SIZE (0xFFF - 1)
while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > MAX_DMA_SIZE ? MAX_DMA_SIZE : Count);
Count = Count > MAX_DMA_SIZE ? Count - MAX_DMA_SIZE : 0;
}
#undef MAX_DMA_SIZE
}
};

View File

@ -0,0 +1,129 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_TFT_XPT2046 || HAS_TOUCH_XPT2046
#include "xpt2046.h"
#include <SPI.h>
uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; }
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
#include <SPI.h>
SPIClass XPT2046::SPIx(TOUCH_BUTTONS_HW_SPI_DEVICE);
static void touch_spi_init(uint8_t spiRate) {
XPT2046::SPIx.setModule(TOUCH_BUTTONS_HW_SPI_DEVICE);
XPT2046::SPIx.setClock(SPI_CLOCK_DIV128);
XPT2046::SPIx.setBitOrder(MSBFIRST);
XPT2046::SPIx.setDataMode(SPI_MODE0);
XPT2046::SPIx.setDataSize(DATA_SIZE_8BIT);
}
#endif
void XPT2046::Init() {
SET_INPUT(TOUCH_MISO_PIN);
SET_OUTPUT(TOUCH_MOSI_PIN);
SET_OUTPUT(TOUCH_SCK_PIN);
OUT_WRITE(TOUCH_CS_PIN, HIGH);
#if PIN_EXISTS(TOUCH_INT)
// Optional Pendrive interrupt pin
SET_INPUT(TOUCH_INT_PIN);
#endif
TERN_(TOUCH_BUTTONS_HW_SPI, touch_spi_init(SPI_SPEED_6));
// Read once to enable pendrive status pin
getRawData(XPT2046_X);
}
bool XPT2046::isTouched() {
return isBusy() ? false : (
#if PIN_EXISTS(TOUCH_INT)
READ(TOUCH_INT_PIN) != HIGH
#else
getRawData(XPT2046_Z1) >= XPT2046_Z1_THRESHOLD
#endif
);
}
bool XPT2046::getRawPoint(int16_t *x, int16_t *y) {
if (isBusy()) return false;
if (!isTouched()) return false;
*x = getRawData(XPT2046_X);
*y = getRawData(XPT2046_Y);
SERIAL_ECHOLNPAIR("X: ", *x, ", Y: ", *y);
return isTouched();
}
uint16_t XPT2046::getRawData(const XPTCoordinate coordinate) {
uint16_t data[3];
DataTransferBegin();
TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.begin());
for (uint16_t i = 0; i < 3 ; i++) {
IO(coordinate);
data[i] = (IO() << 4) | (IO() >> 4);
}
TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.end());
DataTransferEnd();
uint16_t delta01 = delta(data[0], data[1]),
delta02 = delta(data[0], data[2]),
delta12 = delta(data[1], data[2]);
if (delta01 > delta02 || delta01 > delta12)
data[delta02 > delta12 ? 0 : 1] = data[2];
return (data[0] + data[1]) >> 1;
}
uint16_t XPT2046::IO(uint16_t data) {
return TERN(TOUCH_BUTTONS_HW_SPI, HardwareIO, SoftwareIO)(data);
}
extern uint8_t spiTransfer(uint8_t b);
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
uint16_t XPT2046::HardwareIO(uint16_t data) {
return SPIx.transfer(data & 0xFF);
}
#endif
uint16_t XPT2046::SoftwareIO(uint16_t data) {
uint16_t result = 0;
for (uint8_t j = 0x80; j; j >>= 1) {
WRITE(TOUCH_SCK_PIN, LOW);
WRITE(TOUCH_MOSI_PIN, data & j ? HIGH : LOW);
if (READ(TOUCH_MISO_PIN)) result |= j;
WRITE(TOUCH_SCK_PIN, HIGH);
}
WRITE(TOUCH_SCK_PIN, LOW);
return result;
}
#endif // HAS_TFT_XPT2046

View File

@ -0,0 +1,80 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfig.h"
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
#include <SPI.h>
#endif
#ifndef TOUCH_MISO_PIN
#define TOUCH_MISO_PIN MISO_PIN
#endif
#ifndef TOUCH_MOSI_PIN
#define TOUCH_MOSI_PIN MOSI_PIN
#endif
#ifndef TOUCH_SCK_PIN
#define TOUCH_SCK_PIN SCK_PIN
#endif
#ifndef TOUCH_CS_PIN
#define TOUCH_CS_PIN CS_PIN
#endif
#ifndef TOUCH_INT_PIN
#define TOUCH_INT_PIN -1
#endif
#define XPT2046_DFR_MODE 0x00
#define XPT2046_SER_MODE 0x04
#define XPT2046_CONTROL 0x80
enum XPTCoordinate : uint8_t {
XPT2046_X = 0x10 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Y = 0x50 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Z1 = 0x30 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
};
#if !defined(XPT2046_Z1_THRESHOLD)
#define XPT2046_Z1_THRESHOLD 10
#endif
class XPT2046 {
private:
static bool isBusy() { return false; }
static uint16_t getRawData(const XPTCoordinate coordinate);
static bool isTouched();
static inline void DataTransferBegin() { WRITE(TOUCH_CS_PIN, LOW); };
static inline void DataTransferEnd() { WRITE(TOUCH_CS_PIN, HIGH); };
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
static uint16_t HardwareIO(uint16_t data);
#endif
static uint16_t SoftwareIO(uint16_t data);
static uint16_t IO(uint16_t data = 0);
public:
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
static SPIClass SPIx;
#endif
static void Init();
static bool getRawPoint(int16_t *x, int16_t *y);
};

View File

@ -126,82 +126,83 @@
void endstop_ISR() { endstops.update(); }
void setup_endstop_interrupts() {
#define _ATTACH(P) attachInterrupt(P, endstop_ISR, CHANGE)
#if HAS_X_MAX
#if !AVAILABLE_EILINE(X_MAX_PIN)
#error "X_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(X_MAX_PIN, endstop_ISR, CHANGE);
_ATTACH(X_MAX_PIN);
#endif
#if HAS_X_MIN
#if !AVAILABLE_EILINE(X_MIN_PIN)
#error "X_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(X_MIN_PIN, endstop_ISR, CHANGE);
_ATTACH(X_MIN_PIN);
#endif
#if HAS_Y_MAX
#if !AVAILABLE_EILINE(Y_MAX_PIN)
#error "Y_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(Y_MAX_PIN, endstop_ISR, CHANGE);
_ATTACH(Y_MAX_PIN);
#endif
#if HAS_Y_MIN
#if !AVAILABLE_EILINE(Y_MIN_PIN)
#error "Y_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(Y_MIN_PIN, endstop_ISR, CHANGE);
_ATTACH(Y_MIN_PIN);
#endif
#if HAS_Z_MAX
#if !AVAILABLE_EILINE(Z_MAX_PIN)
#error "Z_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(Z_MAX_PIN, endstop_ISR, CHANGE);
_ATTACH(Z_MAX_PIN);
#endif
#if HAS_Z_MIN
#if !AVAILABLE_EILINE(Z_MIN_PIN)
#error "Z_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(Z_MIN_PIN, endstop_ISR, CHANGE);
_ATTACH(Z_MIN_PIN);
#endif
#if HAS_Z2_MAX
#if !AVAILABLE_EILINE(Z2_MAX_PIN)
#error "Z2_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(Z2_MAX_PIN, endstop_ISR, CHANGE);
_ATTACH(Z2_MAX_PIN);
#endif
#if HAS_Z2_MIN
#if !AVAILABLE_EILINE(Z2_MIN_PIN)
#error "Z2_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(Z2_MIN_PIN, endstop_ISR, CHANGE);
_ATTACH(Z2_MIN_PIN);
#endif
#if HAS_Z3_MAX
#if !AVAILABLE_EILINE(Z3_MAX_PIN)
#error "Z3_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(Z3_MAX_PIN, endstop_ISR, CHANGE);
_ATTACH(Z3_MAX_PIN);
#endif
#if HAS_Z3_MIN
#if !AVAILABLE_EILINE(Z3_MIN_PIN)
#error "Z3_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(Z3_MIN_PIN, endstop_ISR, CHANGE);
_ATTACH(Z3_MIN_PIN);
#endif
#if HAS_Z4_MAX
#if !AVAILABLE_EILINE(Z4_MAX_PIN)
#error "Z4_MAX_PIN has no EXTINT line available."
#endif
attachInterrupt(Z4_MAX_PIN, endstop_ISR, CHANGE);
_ATTACH(Z4_MAX_PIN);
#endif
#if HAS_Z4_MIN
#if !AVAILABLE_EILINE(Z4_MIN_PIN)
#error "Z4_MIN_PIN has no EXTINT line available."
#endif
attachInterrupt(Z4_MIN_PIN, endstop_ISR, CHANGE);
_ATTACH(Z4_MIN_PIN);
#endif
#if HAS_Z_MIN_PROBE_PIN
#if !AVAILABLE_EILINE(Z_MIN_PROBE_PIN)
#error "Z_MIN_PROBE_PIN has no EXTINT line available."
#endif
attachInterrupt(Z_MIN_PROBE_PIN, endstop_ISR, CHANGE);
_ATTACH(Z_MIN_PROBE_PIN);
#endif
}

View File

@ -20,3 +20,7 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/SAMD51."
#endif

View File

@ -213,5 +213,10 @@ uint16_t HAL_adc_get_result();
#define GET_PIN_MAP_INDEX(pin) pin
#define PARSED_PIN_INDEX(code, dval) parser.intval(code, dval)
#ifdef STM32F1xx
#define JTAG_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_JTAGDISABLE)
#define JTAGSWD_DISABLE() AFIO_DBGAFR_CONFIG(AFIO_MAPR_SWJ_CFG_DISABLE)
#endif
#define PLATFORM_M997_SUPPORT
void flashFirmware(const int16_t);

View File

@ -76,7 +76,24 @@
SD_HandleTypeDef hsd; // create SDIO structure
#define TRANSFER_CLOCK_DIV (uint8_t(SDIO_INIT_CLK_DIV) / 40)
/*
SDIO_INIT_CLK_DIV is 118
SDIO clock frequency is 48MHz / (TRANSFER_CLOCK_DIV + 2)
SDIO init clock frequency should not exceed 400KHz = 48MHz / (118 + 2)
Default TRANSFER_CLOCK_DIV is 2 (118 / 40)
Default SDIO clock frequency is 48MHz / (2 + 2) = 12 MHz
This might be too fast for stable SDIO operations
MKS Robin board seems to have stable SDIO with BusWide 1bit and ClockDiv 8 i.e. 4.8MHz SDIO clock frequency
Additional testing is required as there are clearly some 4bit initialization problems
Add -DTRANSFER_CLOCK_DIV=8 to build parameters to improve SDIO stability
*/
#ifndef TRANSFER_CLOCK_DIV
#define TRANSFER_CLOCK_DIV (uint8_t(SDIO_INIT_CLK_DIV) / 40)
#endif
#ifndef USBD_OK
#define USBD_OK 0
@ -100,24 +117,25 @@
void SD_LowLevel_Init(void) {
uint32_t tempreg;
GPIO_InitTypeDef GPIO_InitStruct;
__HAL_RCC_SDIO_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE(); //enable GPIO clocks
__HAL_RCC_GPIOD_CLK_ENABLE(); //enable GPIO clocks
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = 1; //GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
#if DISABLED(STM32F1xx)
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
#endif
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_12; // D0 & SCK
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // define D1-D3 only if have a four bit wide SDIO bus
GPIO_InitStruct.Pin = GPIO_PIN_9 | GPIO_PIN_10 | GPIO_PIN_11; // D1-D3
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = 1; // GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#endif
@ -125,10 +143,13 @@
GPIO_InitStruct.Pin = GPIO_PIN_2;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST_Msk; // take SDIO out of reset
RCC->APB2ENR |= RCC_APB2RSTR_SDIORST_Msk; // enable SDIO clock
// Enable the DMA2 Clock
#if DISABLED(STM32F1xx)
// TODO: use __HAL_RCC_SDIO_RELEASE_RESET() and __HAL_RCC_SDIO_CLK_ENABLE();
RCC->APB2RSTR &= ~RCC_APB2RSTR_SDIORST_Msk; // take SDIO out of reset
RCC->APB2ENR |= RCC_APB2RSTR_SDIORST_Msk; // enable SDIO clock
// Enable the DMA2 Clock
#endif
//Initialize the SDIO (with initial <400Khz Clock)
tempreg = 0; //Reset value
@ -156,10 +177,21 @@
bool status;
hsd.Instance = SDIO;
hsd.State = (HAL_SD_StateTypeDef) 0; // HAL_SD_STATE_RESET
/*
hsd.Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
hsd.Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
hsd.Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
hsd.Init.BusWide = SDIO_BUS_WIDE_1B;
hsd.Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
hsd.Init.ClockDiv = 8;
*/
SD_LowLevel_Init();
uint8_t retry_Cnt = retryCnt;
for (;;) {
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
status = (bool) HAL_SD_Init(&hsd);
if (!status) break;
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
@ -170,6 +202,7 @@
#if PINS_EXIST(SDIO_D1, SDIO_D2, SDIO_D3) // go to 4 bit wide mode if pins are defined
retry_Cnt = retryCnt;
for (;;) {
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
if (!HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B)) break; // some cards are only 1 bit wide so a pass here is not required
if (!--retry_Cnt) break;
}
@ -178,6 +211,7 @@
SD_LowLevel_Init();
retry_Cnt = retryCnt;
for (;;) {
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
status = (bool) HAL_SD_Init(&hsd);
if (!status) break;
if (!--retry_Cnt) return false; // return failing status if retries are exhausted
@ -187,15 +221,15 @@
return true;
}
/*
void init_SDIO_pins(void) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
/**SDIO GPIO Configuration
PC8 ------> SDIO_D0
PC12 ------> SDIO_CK
PD2 ------> SDIO_CMD
*/
// SDIO GPIO Configuration
// PC8 ------> SDIO_D0
// PC12 ------> SDIO_CK
// PD2 ------> SDIO_CMD
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
@ -217,7 +251,7 @@
GPIO_InitStruct.Alternate = GPIO_AF12_SDIO;
HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
}
*/
//bool SDIO_init() { return (bool) (SD_SDIO_Init() ? 1 : 0);}
//bool SDIO_Init_C() { return (bool) (SD_SDIO_Init() ? 1 : 0);}
@ -227,6 +261,7 @@
bool status;
for (;;) {
TERN_(USE_WATCHDOG, HAL_watchdog_refresh());
status = (bool) HAL_SD_ReadBlocks(&hsd, (uint8_t*)dst, block, 1, 1000); // read one 512 byte block with 500mS timeout
status |= (bool) HAL_SD_GetCardState(&hsd); // make sure all is OK
if (!status) break; // return passing status

View File

@ -3,14 +3,14 @@
*
* Multi-instance software serial library for Arduino/Wiring
* -- Interrupt-driven receive and other improvements by ladyada
* (https://ladyada.net)
* <https://ladyada.net>
* -- Tuning, circular buffer, derivation from class Print/Stream,
* multi-instance support, porting to 8MHz processors,
* various optimizations, PROGMEM delay tables, inverse logic and
* direct port writing by Mikal Hart (http://www.arduiniana.org)
* -- Pin change interrupt macros by Paul Stoffregen (https://www.pjrc.com)
* -- 20MHz processor support by Garrett Mace (http://www.macetech.com)
* -- ATmega1280/2560 support by Brett Hagman (https://www.roguerobotics.com/)
* direct port writing by Mikal Hart <http://www.arduiniana.org>
* -- Pin change interrupt macros by Paul Stoffregen <https://www.pjrc.com>
* -- 20MHz processor support by Garrett Mace <http://www.macetech.com>
* -- ATmega1280/2560 support by Brett Hagman <https://www.roguerobotics.com>
* -- STM32 support by Armin van der Togt
*
* This library is free software; you can redistribute it and/or

View File

@ -0,0 +1,180 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_FSMC_TFT
#include "tft_fsmc.h"
#include "pinconfig.h"
SRAM_HandleTypeDef TFT_FSMC::SRAMx;
DMA_HandleTypeDef TFT_FSMC::DMAtx;
LCD_CONTROLLER_TypeDef *TFT_FSMC::LCD;
void TFT_FSMC::Init() {
uint32_t controllerAddress;
#if PIN_EXISTS(TFT_RESET)
OUT_WRITE(TFT_RESET_PIN, HIGH);
HAL_Delay(100);
#endif
#if PIN_EXISTS(TFT_BACKLIGHT)
OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH);
#endif
FSMC_NORSRAM_TimingTypeDef Timing, ExtTiming;
uint32_t NSBank = (uint32_t)pinmap_peripheral(digitalPinToPinName(TFT_CS_PIN), PinMap_FSMC_CS);
SRAMx.Instance = FSMC_NORSRAM_DEVICE;
SRAMx.Extended = FSMC_NORSRAM_EXTENDED_DEVICE;
/* SRAMx.Init */
SRAMx.Init.NSBank = NSBank;
SRAMx.Init.DataAddressMux = FSMC_DATA_ADDRESS_MUX_DISABLE;
SRAMx.Init.MemoryType = FSMC_MEMORY_TYPE_SRAM;
SRAMx.Init.MemoryDataWidth = FSMC_NORSRAM_MEM_BUS_WIDTH_16;
SRAMx.Init.BurstAccessMode = FSMC_BURST_ACCESS_MODE_DISABLE;
SRAMx.Init.WaitSignalPolarity = FSMC_WAIT_SIGNAL_POLARITY_LOW;
SRAMx.Init.WrapMode = FSMC_WRAP_MODE_DISABLE;
SRAMx.Init.WaitSignalActive = FSMC_WAIT_TIMING_BEFORE_WS;
SRAMx.Init.WriteOperation = FSMC_WRITE_OPERATION_ENABLE;
SRAMx.Init.WaitSignal = FSMC_WAIT_SIGNAL_DISABLE;
SRAMx.Init.ExtendedMode = FSMC_EXTENDED_MODE_ENABLE;
SRAMx.Init.AsynchronousWait = FSMC_ASYNCHRONOUS_WAIT_DISABLE;
SRAMx.Init.WriteBurst = FSMC_WRITE_BURST_DISABLE;
#ifdef STM32F4xx
SRAMx.Init.PageSize = FSMC_PAGE_SIZE_NONE;
#endif
/* Read Timing - relatively slow to ensure ID information is correctly read from TFT controller */
/* Can be decreases from 15-15-24 to 4-4-8 with risk of stability loss */
Timing.AddressSetupTime = 15;
Timing.AddressHoldTime = 15;
Timing.DataSetupTime = 24;
Timing.BusTurnAroundDuration = 0;
Timing.CLKDivision = 16;
Timing.DataLatency = 17;
Timing.AccessMode = FSMC_ACCESS_MODE_A;
/* Write Timing */
/* Can be decreases from 8-15-8 to 0-0-1 with risk of stability loss */
ExtTiming.AddressSetupTime = 8;
ExtTiming.AddressHoldTime = 15;
ExtTiming.DataSetupTime = 8;
ExtTiming.BusTurnAroundDuration = 0;
ExtTiming.CLKDivision = 16;
ExtTiming.DataLatency = 17;
ExtTiming.AccessMode = FSMC_ACCESS_MODE_A;
__HAL_RCC_FSMC_CLK_ENABLE();
for(uint16_t i = 0; PinMap_FSMC[i].pin != NC; i++)
pinmap_pinout(PinMap_FSMC[i].pin, PinMap_FSMC);
pinmap_pinout(digitalPinToPinName(TFT_CS_PIN), PinMap_FSMC_CS);
pinmap_pinout(digitalPinToPinName(TFT_RS_PIN), PinMap_FSMC_RS);
controllerAddress = FSMC_BANK1_1;
#ifdef PF0
switch (NSBank) {
case FSMC_NORSRAM_BANK2: controllerAddress = FSMC_BANK1_2 ; break;
case FSMC_NORSRAM_BANK3: controllerAddress = FSMC_BANK1_3 ; break;
case FSMC_NORSRAM_BANK4: controllerAddress = FSMC_BANK1_4 ; break;
}
#endif
controllerAddress |= (uint32_t)pinmap_peripheral(digitalPinToPinName(TFT_RS_PIN), PinMap_FSMC_RS);
HAL_SRAM_Init(&SRAMx, &Timing, &ExtTiming);
__HAL_RCC_DMA2_CLK_ENABLE();
#ifdef STM32F1xx
DMAtx.Instance = DMA2_Channel1;
#elif defined(STM32F4xx)
DMAtx.Instance = DMA2_Stream0;
DMAtx.Init.Channel = DMA_CHANNEL_0;
DMAtx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
DMAtx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
DMAtx.Init.MemBurst = DMA_MBURST_SINGLE;
DMAtx.Init.PeriphBurst = DMA_PBURST_SINGLE;
#endif
DMAtx.Init.Direction = DMA_MEMORY_TO_MEMORY;
DMAtx.Init.MemInc = DMA_MINC_DISABLE;
DMAtx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DMAtx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
DMAtx.Init.Mode = DMA_NORMAL;
DMAtx.Init.Priority = DMA_PRIORITY_HIGH;
LCD = (LCD_CONTROLLER_TypeDef *)controllerAddress;
}
uint32_t TFT_FSMC::GetID() {
uint32_t id;
WriteReg(0x0000);
id = LCD->RAM;
if (id == 0)
id = ReadID(LCD_READ_ID);
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = ReadID(LCD_READ_ID4);
return id;
}
uint32_t TFT_FSMC::ReadID(uint16_t Reg) {
uint32_t id;
WriteReg(Reg);
id = LCD->RAM; // dummy read
id = Reg << 24;
id |= (LCD->RAM & 0x00FF) << 16;
id |= (LCD->RAM & 0x00FF) << 8;
id |= LCD->RAM & 0x00FF;
return id;
}
bool TFT_FSMC::isBusy() {
if (__IS_DMA_ENABLED(&DMAtx))
if (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) != 0 || __HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx)) != 0)
Abort();
return __IS_DMA_ENABLED(&DMAtx);
}
void TFT_FSMC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DMAtx.Init.PeriphInc = MemoryIncrease;
HAL_DMA_Init(&DMAtx);
__HAL_DMA_CLEAR_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx));
__HAL_DMA_CLEAR_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx));
#ifdef STM32F1xx
DMAtx.Instance->CNDTR = Count;
DMAtx.Instance->CPAR = (uint32_t)Data;
DMAtx.Instance->CMAR = (uint32_t)&(LCD->RAM);
#elif defined(STM32F4xx)
DMAtx.Instance->NDTR = Count;
DMAtx.Instance->PAR = (uint32_t)Data;
DMAtx.Instance->M0AR = (uint32_t)&(LCD->RAM);
#endif
__HAL_DMA_ENABLE(&DMAtx);
}
#endif // HAS_FSMC_TFT

View File

@ -0,0 +1,160 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#ifdef STM32F1xx
#include "stm32f1xx_hal.h"
#elif defined(STM32F4xx)
#include "stm32f4xx_hal.h"
#else
#error FSMC TFT is currently only supported on STM32F1 and STM32F4 hardware.
#endif
#ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
#ifndef LCD_READ_ID4
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif
#define DATASIZE_8BIT SPI_DATASIZE_8BIT
#define DATASIZE_16BIT SPI_DATASIZE_16BIT
#define TFT_IO TFT_FSMC
#ifdef STM32F1xx
#define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CCR & DMA_CCR_EN)
#elif defined(STM32F4xx)
#define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CR & DMA_SxCR_EN)
#endif
typedef struct {
__IO uint16_t REG;
__IO uint16_t RAM;
} LCD_CONTROLLER_TypeDef;
class TFT_FSMC {
private:
static SRAM_HandleTypeDef SRAMx;
static DMA_HandleTypeDef DMAtx;
static LCD_CONTROLLER_TypeDef *LCD;
static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data) { LCD->RAM = Data; __DSB(); }
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public:
static void Init();
static uint32_t GetID();
static bool isBusy();
static void Abort() { __HAL_DMA_DISABLE(&DMAtx); }
static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT) {}
static void DataTransferEnd() {};
static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg) { LCD->REG = Reg; __DSB(); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_PINC_DISABLE, &Data, Count); }
};
#ifdef STM32F1xx
#define FSMC_PIN_DATA STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, AFIO_NONE)
#elif defined(STM32F4xx)
#define FSMC_PIN_DATA STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF12_FSMC)
#define FSMC_BANK1_1 0x60000000U
#define FSMC_BANK1_2 0x64000000U
#define FSMC_BANK1_3 0x68000000U
#define FSMC_BANK1_4 0x6C000000U
#else
#error No configuration for this MCU
#endif
const PinMap PinMap_FSMC[] = {
{PD_14, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D00
{PD_15, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D01
{PD_0, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D02
{PD_1, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D03
{PE_7, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D04
{PE_8, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D05
{PE_9, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D06
{PE_10, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D07
{PE_11, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D08
{PE_12, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D09
{PE_13, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D10
{PE_14, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D11
{PE_15, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D12
{PD_8, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D13
{PD_9, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D14
{PD_10, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_D15
{PD_4, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_NOE
{PD_5, FSMC_NORSRAM_DEVICE, FSMC_PIN_DATA}, // FSMC_NWE
{NC, NP, 0}
};
const PinMap PinMap_FSMC_CS[] = {
{PD_7, (void *)FSMC_NORSRAM_BANK1, FSMC_PIN_DATA}, // FSMC_NE1
#ifdef PF0
{PG_9, (void *)FSMC_NORSRAM_BANK2, FSMC_PIN_DATA}, // FSMC_NE2
{PG_10, (void *)FSMC_NORSRAM_BANK3, FSMC_PIN_DATA}, // FSMC_NE3
{PG_12, (void *)FSMC_NORSRAM_BANK4, FSMC_PIN_DATA}, // FSMC_NE4
#endif
{NC, NP, 0}
};
#define FSMC_RS(A) (void *)((2 << A) - 2)
const PinMap PinMap_FSMC_RS[] = {
#ifdef PF0
{PF_0, FSMC_RS( 0), FSMC_PIN_DATA}, // FSMC_A0
{PF_1, FSMC_RS( 1), FSMC_PIN_DATA}, // FSMC_A1
{PF_2, FSMC_RS( 2), FSMC_PIN_DATA}, // FSMC_A2
{PF_3, FSMC_RS( 3), FSMC_PIN_DATA}, // FSMC_A3
{PF_4, FSMC_RS( 4), FSMC_PIN_DATA}, // FSMC_A4
{PF_5, FSMC_RS( 5), FSMC_PIN_DATA}, // FSMC_A5
{PF_12, FSMC_RS( 6), FSMC_PIN_DATA}, // FSMC_A6
{PF_13, FSMC_RS( 7), FSMC_PIN_DATA}, // FSMC_A7
{PF_14, FSMC_RS( 8), FSMC_PIN_DATA}, // FSMC_A8
{PF_15, FSMC_RS( 9), FSMC_PIN_DATA}, // FSMC_A9
{PG_0, FSMC_RS(10), FSMC_PIN_DATA}, // FSMC_A10
{PG_1, FSMC_RS(11), FSMC_PIN_DATA}, // FSMC_A11
{PG_2, FSMC_RS(12), FSMC_PIN_DATA}, // FSMC_A12
{PG_3, FSMC_RS(13), FSMC_PIN_DATA}, // FSMC_A13
{PG_4, FSMC_RS(14), FSMC_PIN_DATA}, // FSMC_A14
{PG_5, FSMC_RS(15), FSMC_PIN_DATA}, // FSMC_A15
#endif
{PD_11, FSMC_RS(16), FSMC_PIN_DATA}, // FSMC_A16
{PD_12, FSMC_RS(17), FSMC_PIN_DATA}, // FSMC_A17
{PD_13, FSMC_RS(18), FSMC_PIN_DATA}, // FSMC_A18
{PE_3, FSMC_RS(19), FSMC_PIN_DATA}, // FSMC_A19
{PE_4, FSMC_RS(20), FSMC_PIN_DATA}, // FSMC_A20
{PE_5, FSMC_RS(21), FSMC_PIN_DATA}, // FSMC_A21
{PE_6, FSMC_RS(22), FSMC_PIN_DATA}, // FSMC_A22
{PE_2, FSMC_RS(23), FSMC_PIN_DATA}, // FSMC_A23
#ifdef PF0
{PG_13, FSMC_RS(24), FSMC_PIN_DATA}, // FSMC_A24
{PG_14, FSMC_RS(25), FSMC_PIN_DATA}, // FSMC_A25
#endif
{NC, NP, 0}
};

View File

@ -0,0 +1,212 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_SPI_TFT
#include "tft_spi.h"
#include "pinconfig.h"
SPI_HandleTypeDef TFT_SPI::SPIx;
DMA_HandleTypeDef TFT_SPI::DMAtx;
void TFT_SPI::Init() {
SPI_TypeDef *spiInstance;
#if PIN_EXISTS(TFT_RESET)
OUT_WRITE(TFT_RESET_PIN, HIGH);
HAL_Delay(100);
#endif
#if PIN_EXISTS(TFT_BACKLIGHT)
OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH);
#endif
OUT_WRITE(TFT_A0_PIN, HIGH);
OUT_WRITE(TFT_CS_PIN, HIGH);
if ((spiInstance = (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TFT_SCK_PIN), PinMap_SPI_SCLK)) == NP) return;
if (spiInstance != (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TFT_MOSI_PIN), PinMap_SPI_MOSI)) return;
#if PIN_EXISTS(TFT_MISO) && (TFT_MISO_PIN != TFT_MOSI_PIN)
if (spiInstance != (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TFT_MISO_PIN), PinMap_SPI_MISO)) return;
#endif
SPIx.Instance = spiInstance;
SPIx.State = HAL_SPI_STATE_RESET;
SPIx.Init.NSS = SPI_NSS_SOFT;
SPIx.Init.Mode = SPI_MODE_MASTER;
SPIx.Init.Direction =
#if TFT_MISO_PIN == TFT_MOSI_PIN
SPI_DIRECTION_1LINE;
#else
SPI_DIRECTION_2LINES;
#endif
SPIx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
SPIx.Init.CLKPhase = SPI_PHASE_1EDGE;
SPIx.Init.CLKPolarity = SPI_POLARITY_LOW;
SPIx.Init.DataSize = SPI_DATASIZE_8BIT;
SPIx.Init.FirstBit = SPI_FIRSTBIT_MSB;
SPIx.Init.TIMode = SPI_TIMODE_DISABLE;
SPIx.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
SPIx.Init.CRCPolynomial = 10;
pinmap_pinout(digitalPinToPinName(TFT_SCK_PIN), PinMap_SPI_SCLK);
pinmap_pinout(digitalPinToPinName(TFT_MOSI_PIN), PinMap_SPI_MOSI);
#if PIN_EXISTS(TFT_MISO) && (TFT_MISO_PIN != TFT_MOSI_PIN)
pinmap_pinout(digitalPinToPinName(TFT_MISO_PIN), PinMap_SPI_MISO);
#endif
pin_PullConfig(get_GPIO_Port(STM_PORT(digitalPinToPinName(TFT_SCK_PIN))), STM_LL_GPIO_PIN(digitalPinToPinName(TFT_SCK_PIN)), GPIO_PULLDOWN);
#ifdef SPI1_BASE
if (SPIx.Instance == SPI1) {
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
SPIx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
DMAtx.Instance = DMA1_Channel3;
}
#endif
#ifdef SPI2_BASE
if (SPIx.Instance == SPI2) {
__HAL_RCC_SPI2_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
DMAtx.Instance = DMA1_Channel5;
}
#endif
#ifdef SPI3_BASE
if (SPIx.Instance == SPI3) {
__HAL_RCC_SPI3_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
DMAtx.Instance = DMA2_Channel2;
}
#endif
HAL_SPI_Init(&SPIx);
DMAtx.Init.Direction = DMA_MEMORY_TO_PERIPH;
DMAtx.Init.PeriphInc = DMA_PINC_DISABLE;
DMAtx.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
DMAtx.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
DMAtx.Init.Mode = DMA_NORMAL;
DMAtx.Init.Priority = DMA_PRIORITY_LOW;
}
void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
SPIx.Init.DataSize = DataSize == DATASIZE_8BIT ? SPI_DATASIZE_8BIT : SPI_DATASIZE_16BIT;
HAL_SPI_Init(&SPIx);
WRITE(TFT_CS_PIN, LOW);
}
uint32_t TFT_SPI::GetID() {
uint32_t id;
id = ReadID(LCD_READ_ID);
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = ReadID(LCD_READ_ID4);
return id;
}
uint32_t TFT_SPI::ReadID(uint16_t Reg) {
#if !PIN_EXISTS(TFT_MISO)
return 0;
#else
uint32_t BaudRatePrescaler = SPIx.Init.BaudRatePrescaler;
uint32_t i, Data = 0;
SPIx.Init.BaudRatePrescaler = SPIx.Instance == SPI1 ? SPI_BAUDRATEPRESCALER_8 : SPI_BAUDRATEPRESCALER_4;
DataTransferBegin(DATASIZE_8BIT);
WriteReg(Reg);
if (SPIx.Init.Direction == SPI_DIRECTION_1LINE) SPI_1LINE_RX(&SPIx);
__HAL_SPI_ENABLE(&SPIx);
for (i = 0; i < 4; i++) {
#if TFT_MISO_PIN != TFT_MOSI_PIN
//if (hspi->Init.Direction == SPI_DIRECTION_2LINES) {
while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
SPIx.Instance->DR = 0;
//}
#endif
while ((SPIx.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
Data = (Data << 8) | SPIx.Instance->DR;
}
__HAL_SPI_DISABLE(&SPIx);
DataTransferEnd();
SPIx.Init.BaudRatePrescaler = BaudRatePrescaler;
return Data >> 7;
#endif
}
bool TFT_SPI::isBusy() {
if (DMAtx.Instance->CCR & DMA_CCR_EN)
if (__HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TC_FLAG_INDEX(&DMAtx)) != 0 || __HAL_DMA_GET_FLAG(&DMAtx, __HAL_DMA_GET_TE_FLAG_INDEX(&DMAtx)) != 0)
Abort();
return DMAtx.Instance->CCR & DMA_CCR_EN;
}
void TFT_SPI::Abort() {
__HAL_DMA_DISABLE(&DMAtx);
DataTransferEnd();
}
void TFT_SPI::Transmit(uint16_t Data) {
#if TFT_MISO_PIN == TFT_MOSI_PIN
SPI_1LINE_TX(&SPIx);
#endif
__HAL_SPI_ENABLE(&SPIx);
SPIx.Instance->DR = Data;
while ((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
while ((SPIx.Instance->SR & SPI_FLAG_BSY) == SPI_FLAG_BSY) {}
#if TFT_MISO_PIN != TFT_MOSI_PIN
__HAL_SPI_CLEAR_OVRFLAG(&SPIx); /* Clear overrun flag in 2 Lines communication mode because received is not read */
#endif
}
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DMAtx.Init.MemInc = MemoryIncrease;
HAL_DMA_Init(&DMAtx);
DataTransferBegin();
#if TFT_MISO_PIN == TFT_MOSI_PIN
SPI_1LINE_TX(&SPIx);
#endif
DMAtx.DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << DMAtx.ChannelIndex);
DMAtx.Instance->CNDTR = Count;
DMAtx.Instance->CPAR = (uint32_t)&(SPIx.Instance->DR);
DMAtx.Instance->CMAR = (uint32_t)Data;
__HAL_DMA_ENABLE(&DMAtx);
__HAL_SPI_ENABLE(&SPIx);
SET_BIT(SPIx.Instance->CR2, SPI_CR2_TXDMAEN); /* Enable Tx DMA Request */
}
#endif // HAS_SPI_TFT

View File

@ -0,0 +1,67 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#ifdef STM32F1xx
#include "stm32f1xx_hal.h"
#elif defined(STM32F4xx)
#include "stm32f4xx_hal.h"
#else
#error SPI TFT is currently only supported on STM32F1 and STM32F4 hardware.
#endif
#ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
#ifndef LCD_READ_ID4
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif
#define DATASIZE_8BIT SPI_DATASIZE_8BIT
#define DATASIZE_16BIT SPI_DATASIZE_16BIT
#define TFT_IO TFT_SPI
class TFT_SPI {
private:
static SPI_HandleTypeDef SPIx;
static DMA_HandleTypeDef DMAtx;
static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public:
static void Init();
static uint32_t GetID();
static bool isBusy();
static void Abort();
static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT);
static void DataTransferEnd() { WRITE(TFT_CS_PIN, HIGH); };
static void DataTransferAbort();
static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg) { WRITE(TFT_A0_PIN, LOW); Transmit(Reg); WRITE(TFT_A0_PIN, HIGH); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
};

View File

@ -0,0 +1,185 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_TFT_XPT2046
#include "xpt2046.h"
#include "pinconfig.h"
uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; }
SPI_HandleTypeDef XPT2046::SPIx;
DMA_HandleTypeDef XPT2046::DMAtx;
void XPT2046::Init() {
SPI_TypeDef *spiInstance;
OUT_WRITE(TOUCH_CS_PIN, HIGH);
#if PIN_EXISTS(TOUCH_INT)
// Optional Pendrive interrupt pin
SET_INPUT(TOUCH_INT_PIN);
#endif
spiInstance = (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TOUCH_SCK_PIN), PinMap_SPI_SCLK);
if (spiInstance != (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TOUCH_MOSI_PIN), PinMap_SPI_MOSI)) spiInstance = NP;
if (spiInstance != (SPI_TypeDef *)pinmap_peripheral(digitalPinToPinName(TOUCH_MISO_PIN), PinMap_SPI_MISO)) spiInstance = NP;
SPIx.Instance = spiInstance;
if (SPIx.Instance) {
SPIx.State = HAL_SPI_STATE_RESET;
SPIx.Init.NSS = SPI_NSS_SOFT;
SPIx.Init.Mode = SPI_MODE_MASTER;
SPIx.Init.Direction = SPI_DIRECTION_2LINES;
SPIx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
SPIx.Init.CLKPhase = SPI_PHASE_2EDGE;
SPIx.Init.CLKPolarity = SPI_POLARITY_HIGH;
SPIx.Init.DataSize = SPI_DATASIZE_8BIT;
SPIx.Init.FirstBit = SPI_FIRSTBIT_MSB;
SPIx.Init.TIMode = SPI_TIMODE_DISABLE;
SPIx.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
SPIx.Init.CRCPolynomial = 10;
pinmap_pinout(digitalPinToPinName(TOUCH_SCK_PIN), PinMap_SPI_SCLK);
pinmap_pinout(digitalPinToPinName(TOUCH_MOSI_PIN), PinMap_SPI_MOSI);
pinmap_pinout(digitalPinToPinName(TOUCH_MISO_PIN), PinMap_SPI_MISO);
#ifdef SPI1_BASE
if (SPIx.Instance == SPI1) {
__HAL_RCC_SPI1_CLK_ENABLE();
SPIx.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_16;
#ifdef STM32F1xx
DMAtx.Instance = DMA1_Channel3;
#elif defined(STM32F4xx)
DMAtx.Instance = DMA2_Stream3; // DMA2_Stream5
#endif
//SERIAL_ECHO_MSG(" Touch Screen on SPI1");
}
#endif
#ifdef SPI2_BASE
if (SPIx.Instance == SPI2) {
__HAL_RCC_SPI2_CLK_ENABLE();
#ifdef STM32F1xx
DMAtx.Instance = DMA1_Channel5;
#elif defined(STM32F4xx)
DMAtx.Instance = DMA1_Stream4;
#endif
//SERIAL_ECHO_MSG(" Touch Screen on SPI2");
}
#endif
#ifdef SPI3_BASE
if (SPIx.Instance == SPI3) {
__HAL_RCC_SPI3_CLK_ENABLE();
#ifdef STM32F1xx
DMAtx.Instance = DMA2_Channel2;
#elif defined(STM32F4xx)
DMAtx.Instance = DMA1_Stream5; // DMA1_Stream7
#endif
//SERIAL_ECHO_MSG(" Touch Screen on SPI3");
}
#endif
}
else {
SPIx.Instance = NULL;
SET_INPUT(TOUCH_MISO_PIN);
SET_OUTPUT(TOUCH_MOSI_PIN);
SET_OUTPUT(TOUCH_SCK_PIN);
//SERIAL_ECHO_MSG(" Touch Screen on Software SPI");
}
getRawData(XPT2046_Z1);
}
bool XPT2046::isTouched() {
return isBusy() ? false : (
#if PIN_EXISTS(TOUCH_INT)
READ(TOUCH_INT_PIN) != HIGH
#else
getRawData(XPT2046_Z1) >= XPT2046_Z1_THRESHOLD
#endif
);
}
bool XPT2046::getRawPoint(int16_t *x, int16_t *y) {
if (isBusy()) return false;
if (!isTouched()) return false;
*x = getRawData(XPT2046_X);
*y = getRawData(XPT2046_Y);
return isTouched();
}
uint16_t XPT2046::getRawData(const XPTCoordinate coordinate) {
uint16_t data[3];
DataTransferBegin();
for (uint16_t i = 0; i < 3 ; i++) {
IO(coordinate);
data[i] = (IO() << 4) | (IO() >> 4);
}
DataTransferEnd();
uint16_t delta01 = delta(data[0], data[1]);
uint16_t delta02 = delta(data[0], data[2]);
uint16_t delta12 = delta(data[1], data[2]);
if (delta01 > delta02 || delta01 > delta12) {
if (delta02 > delta12)
data[0] = data[2];
else
data[1] = data[2];
}
return (data[0] + data[1]) >> 1;
}
uint16_t XPT2046::HardwareIO(uint16_t data) {
__HAL_SPI_ENABLE(&SPIx);
while((SPIx.Instance->SR & SPI_FLAG_TXE) != SPI_FLAG_TXE) {}
SPIx.Instance->DR = data;
while((SPIx.Instance->SR & SPI_FLAG_RXNE) != SPI_FLAG_RXNE) {}
__HAL_SPI_DISABLE(&SPIx);
return SPIx.Instance->DR;
}
uint16_t XPT2046::SoftwareIO(uint16_t data) {
uint16_t result = 0;
for (uint8_t j = 0x80; j > 0; j >>= 1) {
WRITE(TOUCH_SCK_PIN, LOW);
__DSB();
WRITE(TOUCH_MOSI_PIN, data & j ? HIGH : LOW);
__DSB();
if (READ(TOUCH_MISO_PIN)) result |= j;
__DSB();
WRITE(TOUCH_SCK_PIN, HIGH);
__DSB();
}
WRITE(TOUCH_SCK_PIN, LOW);
__DSB();
return result;
}
#endif // HAS_TFT_XPT2046

View File

@ -0,0 +1,86 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#ifdef STM32F1xx
#include <stm32f1xx_hal.h>
#elif defined(STM32F4xx)
#include <stm32f4xx_hal.h>
#endif
#include "../../../inc/MarlinConfig.h"
// Not using regular SPI interface by default to avoid SPI mode conflicts with other SPI devices
#if !PIN_EXISTS(TOUCH_MISO)
#error "TOUCH_MISO_PIN is not defined."
#elif !PIN_EXISTS(TOUCH_MOSI)
#error "TOUCH_MOSI_PIN is not defined."
#elif !PIN_EXISTS(TOUCH_SCK)
#error "TOUCH_SCK_PIN is not defined."
#elif !PIN_EXISTS(TOUCH_CS)
#error "TOUCH_CS_PIN is not defined."
#endif
#ifndef TOUCH_INT_PIN
#define TOUCH_INT_PIN -1
#endif
#define XPT2046_DFR_MODE 0x00
#define XPT2046_SER_MODE 0x04
#define XPT2046_CONTROL 0x80
enum XPTCoordinate : uint8_t {
XPT2046_X = 0x10 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Y = 0x50 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Z1 = 0x30 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
};
#if !defined(XPT2046_Z1_THRESHOLD)
#define XPT2046_Z1_THRESHOLD 10
#endif
#ifdef STM32F1xx
#define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CCR & DMA_CCR_EN)
#elif defined(STM32F4xx)
#define __IS_DMA_ENABLED(__HANDLE__) ((__HANDLE__)->Instance->CR & DMA_SxCR_EN)
#endif
class XPT2046 {
private:
static SPI_HandleTypeDef SPIx;
static DMA_HandleTypeDef DMAtx;
static bool isBusy() { return SPIx.Instance ? __IS_DMA_ENABLED(&DMAtx) : false; }
static uint16_t getRawData(const XPTCoordinate coordinate);
static bool isTouched();
static inline void DataTransferBegin() { if (SPIx.Instance) { HAL_SPI_Init(&SPIx); } WRITE(TOUCH_CS_PIN, LOW); };
static inline void DataTransferEnd() { WRITE(TOUCH_CS_PIN, HIGH); };
static uint16_t HardwareIO(uint16_t data);
static uint16_t SoftwareIO(uint16_t data);
static uint16_t IO(uint16_t data = 0) { return SPIx.Instance ? HardwareIO(data) : SoftwareIO(data); }
public:
static void Init();
static bool getRawPoint(int16_t *x, int16_t *y);
};

View File

@ -277,7 +277,7 @@ void SPIClass::read(uint8_t *buf, uint32_t len) {
regs->DR = 0x00FF; // write the first byte
// main loop
while (--len) {
while(!(regs->SR & SPI_SR_TXE)) { /* nada */ } // wait for TXE flag
while (!(regs->SR & SPI_SR_TXE)) { /* nada */ } // wait for TXE flag
noInterrupts(); // go atomic level - avoid interrupts to surely get the previously received data
regs->DR = 0x00FF; // write the next data item to be transmitted into the SPI_DR register. This clears the TXE flag.
while (!(regs->SR & SPI_SR_RXNE)) { /* nada */ } // wait till data is available in the DR register

View File

@ -208,6 +208,8 @@ public:
*/
void setDataSize(uint32_t ds);
uint32_t getDataSize() { return _currentSetting->dataSize; }
/* Victor Perez 2017. Added to set and clear callback functions for callback
* on DMA transfer completion.
* onReceive used to set the callback in case of dmaTransfer (tx/rx), once rx is completed

View File

@ -25,3 +25,10 @@
//#warning "SD_CHECK_AND_RETRY isn't needed with USE_USB_COMPOSITE."
#undef SD_CHECK_AND_RETRY
#endif
// This emulated DOGM has 'touch/xpt2046', not 'tft/xpt2046'
#if ENABLED(TOUCH_SCREEN) && !HAS_GRAPHICAL_TFT
#undef TOUCH_SCREEN
#undef TOUCH_SCREEN_CALIBRATION
#define HAS_TOUCH_XPT2046 1
#endif

View File

@ -51,3 +51,7 @@
#elif ENABLED(SERIAL_STATS_DROPPED_RX)
#error "SERIAL_STATS_DROPPED_RX is not supported on this platform."
#endif
#if ENABLED(NEOPIXEL_LED)
#error "NEOPIXEL_LED (Adafruit NeoPixel) is not supported for HAL/STM32F1. Comment out this line to proceed at your own risk!"
#endif

View File

@ -20,96 +20,16 @@
*
*/
/**
* u8g_com_stm32duino_fsmc.cpp
*
* Communication interface for FSMC
*/
#include "../../../inc/MarlinConfig.h"
#if defined(ARDUINO_ARCH_STM32F1) && PIN_EXISTS(FSMC_CS) // FSMC on 100/144 pins SoCs
#if HAS_FSMC_TFT
#if HAS_GRAPHICAL_LCD
#include <U8glib.h>
#include "tft_fsmc.h"
#include <libmaple/fsmc.h>
#include <libmaple/gpio.h>
#include <libmaple/dma.h>
#include <boards.h>
#ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
/* Timing configuration */
#define FSMC_ADDRESS_SETUP_TIME 15 // AddressSetupTime
#define FSMC_DATA_SETUP_TIME 15 // DataSetupTime
void LCD_IO_Init(uint8_t cs, uint8_t rs);
void LCD_IO_WriteData(uint16_t RegValue);
void LCD_IO_WriteReg(uint16_t Reg);
uint16_t LCD_IO_ReadData(uint16_t RegValue);
uint32_t LCD_IO_ReadData(uint16_t RegValue, uint8_t ReadSize);
#ifdef LCD_USE_DMA_FSMC
void LCD_IO_WriteMultiple(uint16_t data, uint32_t count);
void LCD_IO_WriteSequence(uint16_t *data, uint16_t length);
#endif
static uint8_t msgInitCount = 2; // Ignore all messages until 2nd U8G_COM_MSG_INIT
uint8_t u8g_com_stm32duino_fsmc_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val, void *arg_ptr) {
if (msgInitCount) {
if (msg == U8G_COM_MSG_INIT) msgInitCount--;
if (msgInitCount) return -1;
}
static uint8_t isCommand;
switch (msg) {
case U8G_COM_MSG_STOP: break;
case U8G_COM_MSG_INIT:
u8g_SetPIOutput(u8g, U8G_PI_RESET);
#ifdef LCD_USE_DMA_FSMC
dma_init(FSMC_DMA_DEV);
dma_disable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
dma_set_priority(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, DMA_PRIORITY_MEDIUM);
#endif
LCD_IO_Init(u8g->pin_list[U8G_PI_CS], u8g->pin_list[U8G_PI_A0]);
u8g_Delay(50);
if (arg_ptr) {
*((uint32_t *)arg_ptr) = LCD_IO_ReadData(0x0000);
if (*((uint32_t *)arg_ptr) == 0)
*((uint32_t *)arg_ptr) = (LCD_READ_ID << 24) | LCD_IO_ReadData(LCD_READ_ID, 3);
}
isCommand = 0;
break;
case U8G_COM_MSG_ADDRESS: // define cmd (arg_val = 0) or data mode (arg_val = 1)
isCommand = arg_val == 0 ? 1 : 0;
break;
case U8G_COM_MSG_RESET:
u8g_SetPILevel(u8g, U8G_PI_RESET, arg_val);
break;
case U8G_COM_MSG_WRITE_BYTE:
if (isCommand)
LCD_IO_WriteReg(arg_val);
else
LCD_IO_WriteData((uint16_t)arg_val);
break;
case U8G_COM_MSG_WRITE_SEQ:
for (uint8_t i = 0; i < arg_val; i += 2)
LCD_IO_WriteData(*(uint16_t *)(((uint32_t)arg_ptr) + i));
break;
}
return 1;
}
LCD_CONTROLLER_TypeDef *TFT_FSMC::LCD;
/**
* FSMC LCD IO
@ -160,27 +80,35 @@ __attribute__((always_inline)) __STATIC_INLINE void __DSB() {
#define FSMC_RS_A25 PG14
#endif
/* Timing configuration */
#define FSMC_ADDRESS_SETUP_TIME 15 // AddressSetupTime
#define FSMC_DATA_SETUP_TIME 15 // DataSetupTime
static uint8_t fsmcInit = 0;
typedef struct {
__IO uint16_t REG;
__IO uint16_t RAM;
} LCD_CONTROLLER_TypeDef;
LCD_CONTROLLER_TypeDef *LCD;
void LCD_IO_Init(uint8_t cs, uint8_t rs) {
void TFT_FSMC::Init() {
uint8_t cs = FSMC_CS_PIN, rs = FSMC_RS_PIN;
uint32_t controllerAddress;
#if PIN_EXISTS(TFT_RESET)
OUT_WRITE(TFT_RESET_PIN, HIGH);
delay(100);
#endif
#if PIN_EXISTS(TFT_BACKLIGHT)
OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH);
#endif
struct fsmc_nor_psram_reg_map* fsmcPsramRegion;
if (fsmcInit) return;
fsmcInit = 1;
switch (cs) {
case FSMC_CS_NE1: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION1; break;
case FSMC_CS_NE1: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION1; fsmcPsramRegion = FSMC_NOR_PSRAM1_BASE; break;
#if ENABLED(STM32_XL_DENSITY)
case FSMC_CS_NE2: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION2; break;
case FSMC_CS_NE3: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION3; break;
case FSMC_CS_NE4: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION4; break;
case FSMC_CS_NE2: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION2; fsmcPsramRegion = FSMC_NOR_PSRAM2_BASE; break;
case FSMC_CS_NE3: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION3; fsmcPsramRegion = FSMC_NOR_PSRAM3_BASE; break;
case FSMC_CS_NE4: controllerAddress = (uint32_t)FSMC_NOR_PSRAM_REGION4; fsmcPsramRegion = FSMC_NOR_PSRAM4_BASE; break;
#endif
default: return;
}
@ -246,90 +174,65 @@ void LCD_IO_Init(uint8_t cs, uint8_t rs) {
gpio_set_mode(PIN_MAP[cs].gpio_device, PIN_MAP[cs].gpio_bit, GPIO_AF_OUTPUT_PP); //FSMC_CS_NEx
gpio_set_mode(PIN_MAP[rs].gpio_device, PIN_MAP[rs].gpio_bit, GPIO_AF_OUTPUT_PP); //FSMC_RS_Ax
#if ENABLED(STM32_XL_DENSITY)
FSMC_NOR_PSRAM4_BASE->BCR = FSMC_BCR_WREN | FSMC_BCR_MTYP_SRAM | FSMC_BCR_MWID_16BITS | FSMC_BCR_MBKEN;
FSMC_NOR_PSRAM4_BASE->BTR = (FSMC_DATA_SETUP_TIME << 8) | FSMC_ADDRESS_SETUP_TIME;
#else // PSRAM1 for STM32F103V (high density)
FSMC_NOR_PSRAM1_BASE->BCR = FSMC_BCR_WREN | FSMC_BCR_MTYP_SRAM | FSMC_BCR_MWID_16BITS | FSMC_BCR_MBKEN;
FSMC_NOR_PSRAM1_BASE->BTR = (FSMC_DATA_SETUP_TIME << 8) | FSMC_ADDRESS_SETUP_TIME;
#endif
fsmcPsramRegion->BCR = FSMC_BCR_WREN | FSMC_BCR_MTYP_SRAM | FSMC_BCR_MWID_16BITS | FSMC_BCR_MBKEN;
fsmcPsramRegion->BTR = (FSMC_DATA_SETUP_TIME << 8) | FSMC_ADDRESS_SETUP_TIME;
afio_remap(AFIO_REMAP_FSMC_NADV);
LCD = (LCD_CONTROLLER_TypeDef*)controllerAddress;
}
void LCD_IO_WriteData(uint16_t RegValue) {
LCD->RAM = RegValue;
void TFT_FSMC::Transmit(uint16_t Data) {
LCD->RAM = Data;
__DSB();
}
void LCD_IO_WriteReg(uint16_t Reg) {
void TFT_FSMC::WriteReg(uint16_t Reg) {
LCD->REG = Reg;
__DSB();
}
uint16_t LCD_IO_ReadData(uint16_t RegValue) {
LCD->REG = RegValue;
__DSB();
uint32_t TFT_FSMC::GetID() {
uint32_t id;
WriteReg(0x0000);
id = LCD->RAM;
return LCD->RAM;
if (id == 0)
id = ReadID(LCD_READ_ID);
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = ReadID(LCD_READ_ID4);
return id;
}
uint32_t LCD_IO_ReadData(uint16_t RegValue, uint8_t ReadSize) {
volatile uint32_t data;
LCD->REG = RegValue;
__DSB();
uint32_t TFT_FSMC::ReadID(uint16_t Reg) {
uint32_t id;
WriteReg(Reg);
id = LCD->RAM; // dummy read
id = Reg << 24;
id |= (LCD->RAM & 0x00FF) << 16;
id |= (LCD->RAM & 0x00FF) << 8;
id |= LCD->RAM & 0x00FF;
return id;
}
data = LCD->RAM; // dummy read
data = LCD->RAM & 0x00FF;
while (--ReadSize) {
data <<= 8;
data |= (LCD->RAM & 0x00FF);
}
return uint32_t(data);
bool TFT_FSMC::isBusy() {
return false;
}
#ifdef LCD_USE_DMA_FSMC
void TFT_FSMC::Abort() {
void LCD_IO_WriteMultiple(uint16_t color, uint32_t count) {
while (count > 0) {
dma_setup_transfer(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, &color, DMA_SIZE_16BITS, &LCD->RAM, DMA_SIZE_16BITS, DMA_MEM_2_MEM);
dma_set_num_transfers(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, count > 65535 ? 65535 : count);
}
void TFT_FSMC::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
#if defined(FSMC_DMA_DEV) && defined(FSMC_DMA_CHANNEL)
dma_setup_transfer(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, Data, DMA_SIZE_16BITS, &LCD->RAM, DMA_SIZE_16BITS, DMA_MEM_2_MEM | MemoryIncrease);
dma_set_num_transfers(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, Count);
dma_clear_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
dma_enable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
while ((dma_get_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL) & 0x0A) == 0) {};
dma_disable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
count = count > 65535 ? count - 65535 : 0;
}
#endif
}
void LCD_IO_WriteSequence(uint16_t *data, uint16_t length) {
dma_setup_transfer(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, data, DMA_SIZE_16BITS, &LCD->RAM, DMA_SIZE_16BITS, DMA_MEM_2_MEM | DMA_PINC_MODE);
dma_set_num_transfers(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, length);
dma_clear_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
dma_enable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
while ((dma_get_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL) & 0x0A) == 0) {};
dma_disable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
}
void LCD_IO_WriteSequence_Async(uint16_t *data, uint16_t length) {
dma_setup_transfer(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, data, DMA_SIZE_16BITS, &LCD->RAM, DMA_SIZE_16BITS, DMA_MEM_2_MEM | DMA_PINC_MODE);
dma_set_num_transfers(FSMC_DMA_DEV, FSMC_DMA_CHANNEL, length);
dma_clear_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
dma_enable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
}
void LCD_IO_WaitSequence_Async() {
while ((dma_get_isr_bits(FSMC_DMA_DEV, FSMC_DMA_CHANNEL) & 0x0A) == 0) {};
dma_disable(FSMC_DMA_DEV, FSMC_DMA_CHANNEL);
}
#endif // LCD_USE_DMA_FSMC
#endif // HAS_GRAPHICAL_LCD
#endif // ARDUINO_ARCH_STM32F1 && FSMC_CS_PIN
#endif // HAS_FSMC_TFT

View File

@ -0,0 +1,71 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
#ifndef LCD_READ_ID4
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif
#include <libmaple/dma.h>
#define DATASIZE_8BIT DMA_SIZE_8BITS
#define DATASIZE_16BIT DMA_SIZE_16BITS
#define TFT_IO TFT_FSMC
typedef struct {
__IO uint16_t REG;
__IO uint16_t RAM;
} LCD_CONTROLLER_TypeDef;
class TFT_FSMC {
private:
static LCD_CONTROLLER_TypeDef *LCD;
static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public:
static void Init();
static uint32_t GetID();
static bool isBusy();
static void Abort();
static void DataTransferBegin(uint16_t DataWidth = DATASIZE_16BIT) {};
static void DataTransferEnd() {};
static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg);
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_PINC_MODE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_CIRC_MODE, &Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
while (Count > 0) {
TransmitDMA(DMA_CIRC_MODE, &Data, Count > 0xFFFF ? 0xFFFF : Count);
Count = Count > 0xFFFF ? Count - 0xFFFF : 0;
}
}
};

View File

@ -0,0 +1,149 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_SPI_TFT
#include "tft_spi.h"
// TFT_SPI tft;
SPIClass TFT_SPI::SPIx(1);
#define TFT_CS_H OUT_WRITE(TFT_CS_PIN, HIGH)
#define TFT_CS_L OUT_WRITE(TFT_CS_PIN, LOW)
#define TFT_DC_H OUT_WRITE(TFT_DC_PIN, HIGH)
#define TFT_DC_L OUT_WRITE(TFT_DC_PIN, LOW)
#define TFT_RST_H OUT_WRITE(TFT_RST_PIN, HIGH)
#define TFT_RST_L OUT_WRITE(TFT_RST_PIN, LOW)
#define TFT_BLK_H OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH)
#define TFT_BLK_L OUT_WRITE(TFT_BACKLIGHT_PIN, LOW)
void TFT_SPI::Init() {
#if PIN_EXISTS(TFT_RESET)
// OUT_WRITE(TFT_RESET_PIN, HIGH);
TFT_RST_H;
delay(100);
#endif
#if PIN_EXISTS(TFT_BACKLIGHT)
// OUT_WRITE(TFT_BACKLIGHT_PIN, HIGH);
TFT_BLK_H;
#endif
TFT_DC_H;
TFT_CS_H;
/**
* STM32F1 APB2 = 72MHz, APB1 = 36MHz, max SPI speed of this MCU if 18Mhz
* STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1
* so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2
*/
#if SPI_DEVICE == 1
#define SPI_CLOCK_MAX SPI_CLOCK_DIV4
#else
#define SPI_CLOCK_MAX SPI_CLOCK_DIV2
#endif
uint8_t clock;
uint8_t spiRate = SPI_FULL_SPEED;
switch (spiRate) {
case SPI_FULL_SPEED: clock = SPI_CLOCK_MAX ; break;
case SPI_HALF_SPEED: clock = SPI_CLOCK_DIV4 ; break;
case SPI_QUARTER_SPEED: clock = SPI_CLOCK_DIV8 ; break;
case SPI_EIGHTH_SPEED: clock = SPI_CLOCK_DIV16; break;
case SPI_SPEED_5: clock = SPI_CLOCK_DIV32; break;
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
default: clock = SPI_CLOCK_DIV2; // Default from the SPI library
}
SPIx.setModule(1);
SPIx.setClockDivider(clock);
SPIx.setBitOrder(MSBFIRST);
SPIx.setDataMode(SPI_MODE0);
}
void TFT_SPI::DataTransferBegin(uint16_t DataSize) {
SPIx.setDataSize(DataSize);
SPIx.begin();
TFT_CS_L;
}
uint32_t TFT_SPI::GetID() {
uint32_t id;
id = ReadID(LCD_READ_ID);
if ((id & 0xFFFF) == 0 || (id & 0xFFFF) == 0xFFFF)
id = ReadID(LCD_READ_ID4);
return id;
}
uint32_t TFT_SPI::ReadID(uint16_t Reg) {
#if !PIN_EXISTS(TFT_MISO)
return 0;
#else
uint8_t d = 0;
uint32_t data = 0;
SPIx.setClockDivider(SPI_CLOCK_DIV16);
DataTransferBegin(DATASIZE_8BIT);
WriteReg(Reg);
LOOP_L_N(i, 4) {
SPIx.read((uint8_t*)&d, 1);
data = (data << 8) | d;
}
DataTransferEnd();
SPIx.setClockDivider(SPI_CLOCK_MAX);
return data >> 7;
#endif
}
bool TFT_SPI::isBusy() {
return false;
}
void TFT_SPI::Abort() {
DataTransferEnd();
}
void TFT_SPI::Transmit(uint16_t Data) {
SPIx.send(Data);
}
void TFT_SPI::TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count) {
DataTransferBegin();
TFT_DC_H;
if (MemoryIncrease == DMA_MINC_ENABLE) {
SPIx.dmaSend(Data, Count, true);
}
else {
SPIx.dmaSend(Data, Count, false);
}
DataTransferEnd();
}
#endif // HAS_SPI_TFT

View File

@ -0,0 +1,72 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfig.h"
#include <SPI.h>
#ifndef LCD_READ_ID
#define LCD_READ_ID 0x04 // Read display identification information (0xD3 on ILI9341)
#endif
#ifndef LCD_READ_ID4
#define LCD_READ_ID4 0xD3 // Read display identification information (0xD3 on ILI9341)
#endif
#define DATASIZE_8BIT DATA_SIZE_8BIT
#define DATASIZE_16BIT DATA_SIZE_16BIT
#define TFT_IO TFT_SPI
#define DMA_MINC_ENABLE 1
#define DMA_MINC_DISABLE 0
class TFT_SPI {
private:
static uint32_t ReadID(uint16_t Reg);
static void Transmit(uint16_t Data);
static void TransmitDMA(uint32_t MemoryIncrease, uint16_t *Data, uint16_t Count);
public:
static SPIClass SPIx;
static void Init();
static uint32_t GetID();
static bool isBusy();
static void Abort();
static void DataTransferBegin(uint16_t DataWidth = DATA_SIZE_16BIT);
static void DataTransferEnd() { WRITE(TFT_CS_PIN, HIGH); SPIx.end(); };
static void DataTransferAbort();
static void WriteData(uint16_t Data) { Transmit(Data); }
static void WriteReg(uint16_t Reg) { WRITE(TFT_A0_PIN, LOW); Transmit(Reg); WRITE(TFT_A0_PIN, HIGH); }
static void WriteSequence(uint16_t *Data, uint16_t Count) { TransmitDMA(DMA_MINC_ENABLE, Data, Count); }
static void WriteMultiple(uint16_t Color, uint16_t Count) { static uint16_t Data; Data = Color; TransmitDMA(DMA_MINC_DISABLE, &Data, Count); }
static void WriteMultiple(uint16_t Color, uint32_t Count) {
static uint16_t Data; Data = Color;
while (Count > 0) {
TransmitDMA(DMA_MINC_DISABLE, &Data, Count > 0xFFFF ? 0xFFFF : Count);
Count = Count > 0xFFFF ? Count - 0xFFFF : 0;
}
}
};

View File

@ -0,0 +1,141 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../../inc/MarlinConfig.h"
#if HAS_TFT_XPT2046 || HAS_TOUCH_XPT2046
#include "xpt2046.h"
#include <SPI.h>
uint16_t delta(uint16_t a, uint16_t b) { return a > b ? a - b : b - a; }
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
#include <SPI.h>
SPIClass XPT2046::SPIx(TOUCH_BUTTONS_HW_SPI_DEVICE);
static void touch_spi_init(uint8_t spiRate) {
/**
* STM32F1 APB2 = 72MHz, APB1 = 36MHz, max SPI speed of this MCU if 18Mhz
* STM32F1 has 3 SPI ports, SPI1 in APB2, SPI2/SPI3 in APB1
* so the minimum prescale of SPI1 is DIV4, SPI2/SPI3 is DIV2
*/
uint8_t clock;
switch (spiRate) {
case SPI_FULL_SPEED: clock = SPI_CLOCK_DIV4; break;
case SPI_HALF_SPEED: clock = SPI_CLOCK_DIV4; break;
case SPI_QUARTER_SPEED: clock = SPI_CLOCK_DIV8; break;
case SPI_EIGHTH_SPEED: clock = SPI_CLOCK_DIV16; break;
case SPI_SPEED_5: clock = SPI_CLOCK_DIV32; break;
case SPI_SPEED_6: clock = SPI_CLOCK_DIV64; break;
default: clock = SPI_CLOCK_DIV2; // Default from the SPI library
}
XPT2046::SPIx.setModule(TOUCH_BUTTONS_HW_SPI_DEVICE);
XPT2046::SPIx.setClockDivider(clock);
XPT2046::SPIx.setBitOrder(MSBFIRST);
XPT2046::SPIx.setDataMode(SPI_MODE0);
}
#endif // TOUCH_BUTTONS_HW_SPI
void XPT2046::Init() {
SET_INPUT(TOUCH_MISO_PIN);
SET_OUTPUT(TOUCH_MOSI_PIN);
SET_OUTPUT(TOUCH_SCK_PIN);
OUT_WRITE(TOUCH_CS_PIN, HIGH);
#if PIN_EXISTS(TOUCH_INT)
// Optional Pendrive interrupt pin
SET_INPUT(TOUCH_INT_PIN);
#endif
TERN_(TOUCH_BUTTONS_HW_SPI, touch_spi_init(SPI_SPEED_6));
// Read once to enable pendrive status pin
getRawData(XPT2046_X);
}
bool XPT2046::isTouched() {
return isBusy() ? false : (
#if PIN_EXISTS(TOUCH_INT)
READ(TOUCH_INT_PIN) != HIGH
#else
getRawData(XPT2046_Z1) >= XPT2046_Z1_THRESHOLD
#endif
);
}
bool XPT2046::getRawPoint(int16_t *x, int16_t *y) {
if (isBusy()) return false;
if (!isTouched()) return false;
*x = getRawData(XPT2046_X);
*y = getRawData(XPT2046_Y);
return isTouched();
}
uint16_t XPT2046::getRawData(const XPTCoordinate coordinate) {
uint16_t data[3];
DataTransferBegin();
TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.begin());
for (uint16_t i = 0; i < 3 ; i++) {
IO(coordinate);
data[i] = (IO() << 4) | (IO() >> 4);
}
TERN_(TOUCH_BUTTONS_HW_SPI, SPIx.end());
DataTransferEnd();
uint16_t delta01 = delta(data[0], data[1]),
delta02 = delta(data[0], data[2]),
delta12 = delta(data[1], data[2]);
if (delta01 > delta02 || delta01 > delta12)
data[delta02 > delta12 ? 0 : 1] = data[2];
return (data[0] + data[1]) >> 1;
}
uint16_t XPT2046::IO(uint16_t data) {
return TERN(TOUCH_BUTTONS_HW_SPI, HardwareIO, SoftwareIO)(data);
}
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
uint16_t XPT2046::HardwareIO(uint16_t data) {
uint16_t result = SPIx.transfer(data);
return result;
}
#endif
uint16_t XPT2046::SoftwareIO(uint16_t data) {
uint16_t result = 0;
for (uint8_t j = 0x80; j; j >>= 1) {
WRITE(TOUCH_SCK_PIN, LOW);
WRITE(TOUCH_MOSI_PIN, data & j ? HIGH : LOW);
if (READ(TOUCH_MISO_PIN)) result |= j;
WRITE(TOUCH_SCK_PIN, HIGH);
}
WRITE(TOUCH_SCK_PIN, LOW);
return result;
}
#endif // HAS_TFT_XPT2046

View File

@ -0,0 +1,80 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../../inc/MarlinConfig.h"
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
#include <SPI.h>
#endif
#ifndef TOUCH_MISO_PIN
#define TOUCH_MISO_PIN MISO_PIN
#endif
#ifndef TOUCH_MOSI_PIN
#define TOUCH_MOSI_PIN MOSI_PIN
#endif
#ifndef TOUCH_SCK_PIN
#define TOUCH_SCK_PIN SCK_PIN
#endif
#ifndef TOUCH_CS_PIN
#define TOUCH_CS_PIN CS_PIN
#endif
#ifndef TOUCH_INT_PIN
#define TOUCH_INT_PIN -1
#endif
#define XPT2046_DFR_MODE 0x00
#define XPT2046_SER_MODE 0x04
#define XPT2046_CONTROL 0x80
enum XPTCoordinate : uint8_t {
XPT2046_X = 0x10 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Y = 0x50 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Z1 = 0x30 | XPT2046_CONTROL | XPT2046_DFR_MODE,
XPT2046_Z2 = 0x40 | XPT2046_CONTROL | XPT2046_DFR_MODE,
};
#if !defined(XPT2046_Z1_THRESHOLD)
#define XPT2046_Z1_THRESHOLD 10
#endif
class XPT2046 {
private:
static bool isBusy() { return false; }
static uint16_t getRawData(const XPTCoordinate coordinate);
static bool isTouched();
static inline void DataTransferBegin() { WRITE(TOUCH_CS_PIN, LOW); };
static inline void DataTransferEnd() { WRITE(TOUCH_CS_PIN, HIGH); };
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
static uint16_t HardwareIO(uint16_t data);
#endif
static uint16_t SoftwareIO(uint16_t data);
static uint16_t IO(uint16_t data = 0);
public:
#if ENABLED(TOUCH_BUTTONS_HW_SPI)
static SPIClass SPIx;
#endif
static void Init();
static bool getRawPoint(int16_t *x, int16_t *y);
};

View File

@ -40,7 +40,7 @@
#include "../../../module/stepper/indirection.h"
#include "../../../module/printcounter.h"
#include "../../../libs/duration_t.h"
#include "../../../libs/hex_print_routines.h"
#include "../../../libs/hex_print.h"
//some default values used in initialization
#define DEFAULT_MICROSTEPPING_VALUE 32

View File

@ -20,3 +20,7 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/STM32F4_F7."
#endif

View File

@ -20,3 +20,7 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/TEENSY31_32."
#endif

View File

@ -20,3 +20,7 @@
*
*/
#pragma once
#if HAS_SPI_TFT || HAS_FSMC_TFT
#error "Sorry! TFT displays are not available for HAL/TEENSY35_36."
#endif

View File

@ -4,7 +4,7 @@
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
* file, You can obtain one at https://www.mozilla.org/en-US/MPL/2.0/
*
* This library was modified, some bugs fixed, stack address validated
* and adapted to be used in Marlin 3D printer firmware as backtracer

View File

@ -30,6 +30,10 @@
#include "MarlinCore.h"
#if ENABLED(MARLIN_DEV_MODE)
#warning "WARNING! Disable MARLIN_DEV_MODE for the final build!"
#endif
#include "HAL/shared/Delay.h"
#include "HAL/shared/esp_wifi.h"
@ -39,26 +43,27 @@
#include <math.h>
#include "core/utility.h"
#include "lcd/ultralcd.h"
#include "module/motion.h"
#include "module/planner.h"
#include "module/stepper.h"
#include "module/endstops.h"
#include "module/probe.h"
#include "module/temperature.h"
#include "sd/cardreader.h"
#include "module/configuration_store.h"
#include "module/settings.h"
#include "module/printcounter.h" // PrintCounter or Stopwatch
#include "feature/closedloop.h"
#include "module/stepper.h"
#include "module/stepper/indirection.h"
#include "libs/nozzle.h"
#include "gcode/gcode.h"
#include "gcode/parser.h"
#include "gcode/queue.h"
#include "sd/cardreader.h"
#include "lcd/ultralcd.h"
#if HAS_TOUCH_XPT2046
#include "lcd/touch/touch_buttons.h"
#endif
#if HAS_TFT_LVGL_UI
#include "lcd/extui/lib/mks_ui/tft_lvgl_configuration.h"
#include "lcd/extui/lib/mks_ui/draw_ui.h"
@ -80,10 +85,6 @@
#include "feature/direct_stepping.h"
#endif
#if ENABLED(TOUCH_BUTTONS)
#include "feature/touch/xpt2046.h"
#endif
#if ENABLED(HOST_ACTION_COMMANDS)
#include "feature/host_actions.h"
#endif
@ -92,6 +93,10 @@
#include "libs/buzzer.h"
#endif
#if ENABLED(EXTERNAL_CLOSED_LOOP_CONTROLLER)
#include "feature/closedloop.h"
#endif
#if HAS_I2C_DIGIPOT
#include "feature/digipot/digipot.h"
#endif
@ -176,6 +181,10 @@
#include "feature/runout.h"
#endif
#if HAS_Z_SERVO_PROBE
#include "module/probe.h"
#endif
#if ENABLED(HOTEND_IDLE_TIMEOUT)
#include "feature/hotend_idle.h"
#endif
@ -184,7 +193,7 @@
#include "feature/leds/tempstat.h"
#endif
#if HAS_CASE_LIGHT
#if ENABLED(CASE_LIGHT_ENABLE)
#include "feature/caselight.h"
#endif
@ -208,6 +217,10 @@
#include "libs/L64XX/L64XX_Marlin.h"
#endif
#if ENABLED(PASSWORD_FEATURE)
#include "feature/password/password.h"
#endif
PGMSTR(NUL_STR, "");
PGMSTR(M112_KILL_STR, "M112 Shutdown");
PGMSTR(G28_STR, "G28");
@ -444,14 +457,18 @@ void startOrResumeJob() {
#endif
wait_for_heatup = false;
TERN_(POWER_LOSS_RECOVERY, recovery.purge());
#ifdef EVENT_GCODE_SD_STOP
queue.inject_P(PSTR(EVENT_GCODE_SD_STOP));
#ifdef EVENT_GCODE_SD_ABORT
queue.inject_P(PSTR(EVENT_GCODE_SD_ABORT));
#endif
TERN_(PASSWORD_AFTER_SD_PRINT_ABORT, password.lock_machine());
}
inline void finishSDPrinting() {
if (queue.enqueue_one_P(PSTR("M1001")))
if (queue.enqueue_one_P(PSTR("M1001"))) {
marlin_state = MF_RUNNING;
TERN_(PASSWORD_AFTER_SD_PRINT_END, password.lock_machine());
}
}
#endif // SDSUPPORT
@ -671,7 +688,7 @@ inline void manage_inactivity(const bool ignore_stepper_queue=false) {
* - Read Buttons and Update the LCD
* - Run i2c Position Encoders
* - Auto-report Temperatures / SD Status
* - Update the Prusa MMU2
* - Update the Průša MMU2
* - Handle Joystick jogging
*/
void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) {
@ -747,7 +764,7 @@ void idle(TERN_(ADVANCED_PAUSE_FEATURE, bool no_stepper_sleep/*=false*/)) {
}
#endif
// Update the Prusa MMU2
// Update the Průša MMU2
TERN_(PRUSA_MMU2, mmu2.mmu_loop());
// Handle Joystick jogging
@ -909,7 +926,7 @@ void setup() {
SETUP_RUN(L64xxManager.init()); // Set up SPI, init drivers
#endif
#if ENABLED(SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
#if ENABLED(DUET_SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
OUT_WRITE(SMART_EFFECTOR_MOD_PIN, LOW); // Put Smart Effector into NORMAL mode
#endif
@ -978,6 +995,10 @@ void setup() {
SETUP_RUN(leds.setup());
#endif
#if ENABLED(NEOPIXEL2_SEPARATE)
SETUP_RUN(leds2.setup());
#endif
#if ENABLED(USE_CONTROLLER_FAN) // Set up fan controller to initialize also the default configurations.
SETUP_RUN(controllerFan.setup());
#endif
@ -1006,7 +1027,7 @@ void setup() {
SETUP_RUN(settings.first_load()); // Load data from EEPROM if available (or use defaults)
// This also updates variables in the planner, elsewhere
#if ENABLED(TOUCH_BUTTONS)
#if HAS_TOUCH_XPT2046
SETUP_RUN(touch.init());
#endif
@ -1077,11 +1098,11 @@ void setup() {
OUT_WRITE(STAT_LED_BLUE_PIN, LOW); // OFF
#endif
#if HAS_CASE_LIGHT
#if ENABLED(CASE_LIGHT_ENABLE)
#if DISABLED(CASE_LIGHT_USE_NEOPIXEL)
if (PWM_PIN(CASE_LIGHT_PIN)) SET_PWM(CASE_LIGHT_PIN); else SET_OUTPUT(CASE_LIGHT_PIN);
#endif
SETUP_RUN(update_case_light());
SETUP_RUN(caselight.update_brightness());
#endif
#if ENABLED(MK2_MULTIPLEXER)
@ -1194,10 +1215,16 @@ void setup() {
#endif
#if HAS_TFT_LVGL_UI
if (!card.isMounted()) SETUP_RUN(card.mount()); // Mount SD to load graphics and fonts
#if ENABLED(SDSUPPORT)
if (!card.isMounted()) SETUP_RUN(card.mount()); // Mount SD to load graphics and fonts
#endif
SETUP_RUN(tft_lvgl_init());
#endif
#if ENABLED(PASSWORD_ON_STARTUP)
SETUP_RUN(password.lock_machine()); // Will not proceed until correct password provided
#endif
marlin_state = MF_RUNNING;
SETUP_LOG("setup() completed.");

View File

@ -89,8 +89,8 @@ extern bool wait_for_heatup;
#if ENABLED(PSU_CONTROL)
extern bool powersupply_on;
#define PSU_PIN_ON() do{ OUT_WRITE(PS_ON_PIN, PSU_ACTIVE_HIGH); powersupply_on = true; }while(0)
#define PSU_PIN_OFF() do{ OUT_WRITE(PS_ON_PIN, !PSU_ACTIVE_HIGH); powersupply_on = false; }while(0)
#define PSU_PIN_ON() do{ OUT_WRITE(PS_ON_PIN, PSU_ACTIVE_STATE); powersupply_on = true; }while(0)
#define PSU_PIN_OFF() do{ OUT_WRITE(PS_ON_PIN, !PSU_ACTIVE_STATE); powersupply_on = false; }while(0)
#if ENABLED(AUTO_POWER_CONTROL)
#define PSU_ON() powerManager.power_on()
#define PSU_OFF() powerManager.power_off()

View File

@ -171,6 +171,7 @@
#define BOARD_STB_11 1508 // STB V1.1
#define BOARD_AZTEEG_X1 1509 // Azteeg X1
#define BOARD_ANET_10 1510 // Anet 1.0 (Melzi clone)
#define BOARD_ZMIB_V2 1511 // ZoneStar ZMIB V2
//
// Other ATmega644P, ATmega644, ATmega1284P
@ -312,7 +313,8 @@
#define BOARD_CHITU3D_V5 4031 // Chitu3D TronXY X5SA V5 Board
#define BOARD_CHITU3D_V6 4032 // Chitu3D TronXY X5SA V5 Board
#define BOARD_CREALITY_V4 4033 // Creality v4.x (STM32F103RE)
#define BOARD_TRIGORILLA_PRO 4034 // Trigorilla Pro (STM32F103ZET6)
#define BOARD_CREALITY_V427 4034 // Creality v4.2.7 (STM32F103RE)
#define BOARD_TRIGORILLA_PRO 4035 // Trigorilla Pro (STM32F103ZET6)
//
// ARM Cortex-M4F
@ -343,8 +345,9 @@
#define BOARD_LERDGE_X 4215 // Lerdge X (STM32F407VE)
#define BOARD_VAKE403D 4216 // VAkE 403D (STM32F446VET6)
#define BOARD_FYSETC_S6 4217 // FYSETC S6 board
#define BOARD_FLYF407ZG 4218 // FLYF407ZG board (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4219 // MKS_ROBIN2 (STM32F407ZE)
#define BOARD_FYSETC_S6_V2_0 4218 // FYSETC S6 v2.0 board
#define BOARD_FLYF407ZG 4219 // FLYF407ZG board (STM32F407ZG)
#define BOARD_MKS_ROBIN2 4220 // MKS_ROBIN2 (STM32F407ZE)
//
// ARM Cortex M7
@ -366,6 +369,11 @@
//
#define BOARD_AGCM4_RAMPS_144 6100 // RAMPS 1.4.4
//
// Custom board
//
#define BOARD_CUSTOM 9998 // Custom pins definition for development and/or rare boards
//
// Simulations
//

View File

@ -266,6 +266,13 @@
#define STR_DEBUG_COMMUNICATION "COMMUNICATION"
#define STR_DEBUG_LEVELING "LEVELING"
#define STR_PRINTER_LOCKED "Printer locked! (Unlock with M511 or LCD)"
#define STR_WRONG_PASSWORD "Incorrect Password"
#define STR_PASSWORD_TOO_LONG "Password too long"
#define STR_PASSWORD_REMOVED "Password removed"
#define STR_REMINDER_SAVE_SETTINGS "Remember to save!"
#define STR_PASSWORD_SET "Password is "
// LCD Menu Messages
#define LANGUAGE_DATA_INCL_(M) STRINGIFY_(fontdata/langdata_##M.h)
@ -346,7 +353,7 @@
*
*/
#if ENABLED(NUMBER_TOOLS_FROM_0)
#define LCD_FIRST_TOOL '0'
#define LCD_FIRST_TOOL 0
#define LCD_STR_N0 "0"
#define LCD_STR_N1 "1"
#define LCD_STR_N2 "2"
@ -356,7 +363,7 @@
#define LCD_STR_N6 "6"
#define LCD_STR_N7 "7"
#else
#define LCD_FIRST_TOOL '1'
#define LCD_FIRST_TOOL 1
#define LCD_STR_N0 "1"
#define LCD_STR_N1 "2"
#define LCD_STR_N2 "3"

View File

@ -342,15 +342,22 @@
#endif
// Macros for adding
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INC_9 10
#define INC_10 11
#define INC_11 12
#define INC_12 13
#define INC_13 14
#define INC_14 15
#define INC_15 16
#define INCREMENT_(n) INC_##n
#define INCREMENT(n) INCREMENT_(n)
@ -367,16 +374,22 @@
#define ADD10(N) ADD5(ADD5(N))
// Macros for subtracting
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
#define DEC_10 9
#define DEC_11 10
#define DEC_12 11
#define DEC_13 12
#define DEC_14 13
#define DEC_15 14
#define DECREMENT_(n) DEC_##n
#define DECREMENT(n) DECREMENT_(n)

View File

@ -26,7 +26,8 @@
#include "babystep.h"
#include "../MarlinCore.h"
#include "../module/planner.h"
#include "../module/motion.h" // for axes_should_home()
#include "../module/planner.h" // for axis_steps_per_mm[]
#include "../module/stepper.h"
#if ENABLED(BABYSTEP_ALWAYS_AVAILABLE)
@ -54,7 +55,7 @@ void Babystep::add_mm(const AxisEnum axis, const float &mm) {
}
void Babystep::add_steps(const AxisEnum axis, const int16_t distance) {
if (DISABLED(BABYSTEP_WITHOUT_HOMING) && !TEST(axis_known_position, axis)) return;
if (DISABLED(BABYSTEP_WITHOUT_HOMING) && axes_should_home(_BV(axis))) return;
accum += distance; // Count up babysteps for the UI
steps[BS_AXIS_IND(axis)] += distance;

View File

@ -31,7 +31,7 @@
#include "../../../MarlinCore.h"
#include "../../../gcode/gcode.h"
#include "../../../module/configuration_store.h"
#include "../../../module/settings.h"
#include "../../../module/planner.h"
#include "../../../module/motion.h"
#include "../../../module/probe.h"

View File

@ -28,8 +28,8 @@
#include "../../../MarlinCore.h"
#include "../../../HAL/shared/eeprom_api.h"
#include "../../../libs/hex_print_routines.h"
#include "../../../module/configuration_store.h"
#include "../../../libs/hex_print.h"
#include "../../../module/settings.h"
#include "../../../lcd/ultralcd.h"
#include "../../../module/stepper.h"
#include "../../../module/planner.h"
@ -321,7 +321,7 @@
// Check for commands that require the printer to be homed
if (may_move) {
planner.synchronize();
if (axes_need_homing()) gcode.home_all_axes();
if (axes_should_home()) gcode.home_all_axes();
TERN_(HAS_MULTI_HOTEND, if (active_extruder) tool_change(0));
}

View File

@ -25,7 +25,7 @@
#if ENABLED(BINARY_FILE_TRANSFER)
#include "../sd/cardreader.h"
#include "binary_protocol.h"
#include "binary_stream.h"
char* SDFileTransferProtocol::Packet::Open::data = nullptr;
size_t SDFileTransferProtocol::data_waiting, SDFileTransferProtocol::transfer_timeout, SDFileTransferProtocol::idle_timeout;
@ -33,4 +33,4 @@ bool SDFileTransferProtocol::transfer_active, SDFileTransferProtocol::dummy_tran
BinaryStream binaryStream[NUM_SERIAL];
#endif // BINARY_FILE_TRANSFER
#endif

View File

@ -22,14 +22,17 @@
#include "../inc/MarlinConfig.h"
#if HAS_CASE_LIGHT
#if ENABLED(CASE_LIGHT_ENABLE)
uint8_t case_light_brightness = CASE_LIGHT_DEFAULT_BRIGHTNESS;
bool case_light_on = CASE_LIGHT_DEFAULT_ON;
#include "caselight.h"
CaseLight caselight;
uint8_t CaseLight::brightness = CASE_LIGHT_DEFAULT_BRIGHTNESS;
bool CaseLight::on = CASE_LIGHT_DEFAULT_ON;
#if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
#include "leds/leds.h"
LEDColor case_light_color =
LEDColor CaseLight::color =
#ifdef CASE_LIGHT_NEOPIXEL_COLOR
CASE_LIGHT_NEOPIXEL_COLOR
#else
@ -38,34 +41,33 @@ bool case_light_on = CASE_LIGHT_DEFAULT_ON;
;
#endif
/**
* The following are needed because ARM chips ignore a "WRITE(CASE_LIGHT_PIN,x)" command to the pins that
* are directly controlled by the PWM module. In order to turn them off the brightness level needs to be
* set to off. Since we can't use the pwm register to save the last brightness level we need a variable
* to save it.
*/
uint8_t case_light_brightness_sav; // saves brighness info so can restore when "M355 S1" received
bool case_light_arg_flag; // flag to notify if S or P argument type
#ifndef INVERT_CASE_LIGHT
#define INVERT_CASE_LIGHT false
#endif
void update_case_light() {
void CaseLight::update(const bool sflag) {
/**
* The brightness_sav (and sflag) is needed because ARM chips ignore
* a "WRITE(CASE_LIGHT_PIN,x)" command to the pins that are directly
* controlled by the PWM module. In order to turn them off the brightness
* level needs to be set to OFF. Since we can't use the PWM register to
* save the last brightness level we need a variable to save it.
*/
static uint8_t brightness_sav; // Save brightness info for restore on "M355 S1"
if (!(case_light_arg_flag && !case_light_on))
case_light_brightness_sav = case_light_brightness; // save brightness except if this is an S0 argument
if (case_light_arg_flag && case_light_on)
case_light_brightness = case_light_brightness_sav; // restore last brightens if this is an S1 argument
if (on || !sflag)
brightness_sav = brightness; // Save brightness except for M355 S0
if (sflag && on)
brightness = brightness_sav; // Restore last brightness for M355 S1
#if ENABLED(CASE_LIGHT_USE_NEOPIXEL) || DISABLED(CASE_LIGHT_NO_BRIGHTNESS)
const uint8_t i = case_light_on ? case_light_brightness : 0, n10ct = INVERT_CASE_LIGHT ? 255 - i : i;
const uint8_t i = on ? brightness : 0, n10ct = INVERT_CASE_LIGHT ? 255 - i : i;
#endif
#if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
leds.set_color(
MakeLEDColor(case_light_color.r, case_light_color.g, case_light_color.b, case_light_color.w, n10ct),
MakeLEDColor(color.r, color.g, color.b, color.w, n10ct),
false
);
@ -83,11 +85,11 @@ void update_case_light() {
else
#endif
{
const bool s = case_light_on ? !INVERT_CASE_LIGHT : INVERT_CASE_LIGHT;
const bool s = on ? !INVERT_CASE_LIGHT : INVERT_CASE_LIGHT;
WRITE(CASE_LIGHT_PIN, s ? HIGH : LOW);
}
#endif // !CASE_LIGHT_USE_NEOPIXEL
}
#endif // HAS_CASE_LIGHT
#endif // CASE_LIGHT_ENABLE

View File

@ -21,9 +21,25 @@
*/
#pragma once
extern uint8_t case_light_brightness;
extern bool case_light_on;
extern uint8_t case_light_brightness_sav; // saves brighness info when case_light_on is false
extern bool case_light_arg_flag; // flag to notify if S or P argument type
#include "../inc/MarlinConfigPre.h"
void update_case_light();
#if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
#include "leds/leds.h"
#endif
class CaseLight {
public:
static uint8_t brightness;
static bool on;
static void update(const bool sflag);
static inline void update_brightness() { update(false); }
static inline void update_enabled() { update(true); }
private:
#if ENABLED(CASE_LIGHT_USE_NEOPIXEL)
static LEDColor color;
#endif
};
extern CaseLight caselight;

View File

@ -27,7 +27,7 @@
* https://ww1.microchip.com/downloads/en/DeviceDoc/22187a.pdf
*
* For discussion and feedback, please go to:
* https://arduino.cc/forum/index.php/topic,51842.0.html
* https://forum.arduino.cc/index.php/topic,51842.0.html
*/
#include "../../inc/MarlinConfig.h"

View File

@ -56,9 +56,6 @@ namespace DirectStepping {
template<typename Cfg>
volatile bool SerialPageManager<Cfg>::page_states_dirty;
template<typename Cfg>
millis_t SerialPageManager<Cfg>::next_response;
template<typename Cfg>
uint8_t SerialPageManager<Cfg>::pages[Cfg::NUM_PAGES][Cfg::PAGE_SIZE];
@ -80,7 +77,6 @@ namespace DirectStepping {
page_states[i] = PageState::FREE;
fatal_error = false;
next_response = 0;
state = State::NEWLINE;
page_states_dirty = false;
@ -181,15 +177,8 @@ namespace DirectStepping {
return;
}
// Runs on a set interval also, as responses may get lost.
if (next_response && next_response < millis()) {
page_states_dirty = true;
}
if (!page_states_dirty) return;
page_states_dirty = false;
next_response = millis() + Cfg::RESPONSE_INTERVAL_MS;
SERIAL_ECHO(Cfg::CONTROL_CHAR);
constexpr int state_bits = 2;
@ -238,29 +227,29 @@ const uint8_t segment_table[DirectStepping::Config::NUM_SEGMENTS][DirectStepping
#if STEPPER_PAGE_FORMAT == SP_4x4D_128
{ 1, 1, 1, 1, 1, 1, 1, 0 }, // 0 = -7
{ 1, 1, 1, 0, 1, 1, 1, 0 }, // 1 = -6
{ 0, 1, 1, 0, 1, 0, 1, 1 }, // 2 = -5
{ 0, 1, 0, 1, 0, 1, 0, 1 }, // 3 = -4
{ 0, 1, 0, 0, 1, 0, 0, 1 }, // 4 = -3
{ 0, 0, 1, 0, 0, 0, 1, 0 }, // 5 = -2
{ 0, 0, 0, 0, 1, 0, 0, 0 }, // 6 = -1
{ 0, 0, 0, 0, 0, 0, 0, 0 }, // 7 = 0
{ 0, 0, 0, 0, 1, 0, 0, 0 }, // 8 = 1
{ 0, 0, 1, 0, 0, 0, 1, 0 }, // 9 = 2
{ 0, 1, 0, 0, 1, 0, 0, 1 }, // 10 = 3
{ 0, 1, 0, 1, 0, 1, 0, 1 }, // 11 = 4
{ 0, 1, 1, 0, 1, 0, 1, 1 }, // 12 = 5
{ 1, 1, 1, 0, 1, 1, 1, 0 }, // 13 = 6
{ 1, 1, 1, 1, 1, 1, 1, 0 }, // 14 = 7
{ 1, 1, 1, 1, 1, 1, 1 }, // 0 = -7
{ 1, 1, 1, 0, 1, 1, 1 }, // 1 = -6
{ 1, 1, 1, 0, 1, 0, 1 }, // 2 = -5
{ 1, 1, 0, 1, 0, 1, 0 }, // 3 = -4
{ 1, 1, 0, 0, 1, 0, 0 }, // 4 = -3
{ 0, 0, 1, 0, 0, 0, 1 }, // 5 = -2
{ 0, 0, 0, 1, 0, 0, 0 }, // 6 = -1
{ 0, 0, 0, 0, 0, 0, 0 }, // 7 = 0
{ 0, 0, 0, 1, 0, 0, 0 }, // 8 = 1
{ 0, 0, 1, 0, 0, 0, 1 }, // 9 = 2
{ 1, 1, 0, 0, 1, 0, 0 }, // 10 = 3
{ 1, 1, 0, 1, 0, 1, 0 }, // 11 = 4
{ 1, 1, 1, 0, 1, 0, 1 }, // 12 = 5
{ 1, 1, 1, 0, 1, 1, 1 }, // 13 = 6
{ 1, 1, 1, 1, 1, 1, 1 }, // 14 = 7
{ 0 }
#elif STEPPER_PAGE_FORMAT == SP_4x2_256
{ 0, 0, 0, 0 }, // 0
{ 0, 1, 0, 0 }, // 1
{ 1, 0, 1, 0 }, // 2
{ 1, 1, 1, 0 }, // 3
{ 0, 0, 0 }, // 0
{ 0, 1, 0 }, // 1
{ 1, 0, 1 }, // 2
{ 1, 1, 1 }, // 3
#elif STEPPER_PAGE_FORMAT == SP_4x1_512

View File

@ -70,7 +70,6 @@ namespace DirectStepping {
static volatile PageState page_states[Cfg::NUM_PAGES];
static volatile bool page_states_dirty;
static millis_t next_response;
static uint8_t pages[Cfg::NUM_PAGES][Cfg::PAGE_SIZE];
static uint8_t checksum;
@ -94,14 +93,11 @@ namespace DirectStepping {
static constexpr int DIRECTIONAL = dir ? 1 : 0;
static constexpr int SEGMENTS = segments;
static constexpr int RAW = (BITS_SEGMENT == 1) ? 1 : 0;
static constexpr int NUM_SEGMENTS = 1 << BITS_SEGMENT;
static constexpr int SEGMENT_STEPS = 1 << (BITS_SEGMENT - DIRECTIONAL - RAW);
static constexpr int SEGMENT_STEPS = (1 << (BITS_SEGMENT - DIRECTIONAL)) - 1;
static constexpr int TOTAL_STEPS = SEGMENT_STEPS * SEGMENTS;
static constexpr int PAGE_SIZE = (NUM_AXES * BITS_SEGMENT * SEGMENTS) / 8;
static constexpr millis_t RESPONSE_INTERVAL_MS = 50;
typedef typename TypeSelector<(PAGE_SIZE>256), uint16_t, uint8_t>::type write_byte_idx_t;
typedef typename TypeSelector<(NUM_PAGES>256), uint16_t, uint8_t>::type page_idx_t;
};

View File

@ -21,7 +21,7 @@
*/
/**
* emergency_parser.cpp - Intercept special commands directly in the serial stream
* e_parser.cpp - Intercept special commands directly in the serial stream
*/
#include "../inc/MarlinConfigPre.h"

View File

@ -22,7 +22,7 @@
#pragma once
/**
* emergency_parser.h - Intercept special commands directly in the serial stream
* e_parser.h - Intercept special commands directly in the serial stream
*/
#include "../inc/MarlinConfigPre.h"

View File

@ -44,11 +44,8 @@
#if ENABLED(LED_COLOR_PRESETS)
const LEDColor LEDLights::defaultLEDColor = MakeLEDColor(
LED_USER_PRESET_RED,
LED_USER_PRESET_GREEN,
LED_USER_PRESET_BLUE,
LED_USER_PRESET_WHITE,
LED_USER_PRESET_BRIGHTNESS
LED_USER_PRESET_RED, LED_USER_PRESET_GREEN, LED_USER_PRESET_BLUE,
LED_USER_PRESET_WHITE, LED_USER_PRESET_BRIGHTNESS
);
#endif
@ -117,24 +114,22 @@ void LEDLights::set_color(const LEDColor &incol
// This variant uses 3-4 separate pins for the RGB(W) components.
// If the pins can do PWM then their intensity will be set.
#define UPDATE_RGBW(C,c) do { if (PWM_PIN(RGB_LED_##C##_PIN)) \
#define UPDATE_RGBW(C,c) do { \
if (PWM_PIN(RGB_LED_##C##_PIN)) \
analogWrite(pin_t(RGB_LED_##C##_PIN), incol.c); \
else WRITE(RGB_LED_##C##_PIN, incol.c ? HIGH : LOW); }while(0)
UPDATE_RGBW(R,r);
UPDATE_RGBW(G,g);
UPDATE_RGBW(B,b);
else \
WRITE(RGB_LED_##C##_PIN, incol.c ? HIGH : LOW); \
}while(0)
UPDATE_RGBW(R,r); UPDATE_RGBW(G,g); UPDATE_RGBW(B,b);
#if ENABLED(RGBW_LED)
UPDATE_RGBW(W,w);
#endif
#endif
#if ENABLED(PCA9632)
// Update I2C LED driver
pca9632_set_led_color(incol);
#endif
TERN_(PCA9533, PCA9533_setColor(incol.r, incol.g, incol.b));
// Update I2C LED driver
TERN_(PCA9632, PCA9632_set_led_color(incol));
TERN_(PCA9533, PCA9533_set_rgb(incol.r, incol.g, incol.b));
#if EITHER(LED_CONTROL_MENU, PRINTER_EVENT_LEDS)
// Don't update the color when OFF
@ -161,4 +156,35 @@ void LEDLights::set_color(const LEDColor &incol
#endif
#endif // HAS_COLOR_LEDS
#if ENABLED(NEOPIXEL2_SEPARATE)
#if ENABLED(NEO2_COLOR_PRESETS)
const LEDColor LEDLights2::defaultLEDColor = MakeLEDColor(
NEO2_USER_PRESET_RED, NEO2_USER_PRESET_GREEN, NEO2_USER_PRESET_BLUE,
NEO2_USER_PRESET_WHITE, NEO2_USER_PRESET_BRIGHTNESS
);
#endif
#if ENABLED(LED_CONTROL_MENU)
LEDColor LEDLights2::color;
bool LEDLights2::lights_on;
#endif
LEDLights2 leds2;
void LEDLights2::setup() {
neo2.init();
TERN_(NEO2_USER_PRESET_STARTUP, set_default());
}
void LEDLights2::set_color(const LEDColor &incol) {
const uint32_t neocolor = LEDColorWhite() == incol
? neo2.Color(NEO2_WHITE)
: neo2.Color(incol.r, incol.g, incol.b, incol.w);
neo2.set_brightness(incol.i);
neo2.set_color(neocolor);
}
#endif // NEOPIXEL2_SEPARATE
#endif // HAS_COLOR_LEDS

View File

@ -104,11 +104,7 @@ typedef struct LEDColor {
bool operator!=(const LEDColor &right) { return !operator==(right); }
bool is_off() const {
return 3 > r + g + b
#if HAS_WHITE_LED
+ w
#endif
;
return 3 > r + g + b + TERN0(HAS_WHITE_LED, w);
}
} LEDColor;
@ -156,14 +152,12 @@ public:
#endif
);
inline void set_color(uint8_t r, uint8_t g, uint8_t b
static inline void set_color(uint8_t r, uint8_t g, uint8_t b
#if HAS_WHITE_LED
, uint8_t w=0
#if ENABLED(NEOPIXEL_LED)
, uint8_t i=NEOPIXEL_BRIGHTNESS
#endif
#endif
#if ENABLED(NEOPIXEL_LED)
, uint8_t i=NEOPIXEL_BRIGHTNESS
, bool isSequence=false
#endif
) {
@ -216,3 +210,44 @@ public:
};
extern LEDLights leds;
#if ENABLED(NEOPIXEL2_SEPARATE)
class LEDLights2 {
public:
LEDLights2() {}
static void setup(); // init()
static void set_color(const LEDColor &color);
inline void set_color(uint8_t r, uint8_t g, uint8_t b, uint8_t w=0, uint8_t i=NEOPIXEL2_BRIGHTNESS) {
set_color(MakeLEDColor(r, g, b, w, i));
}
static inline void set_off() { set_color(LEDColorOff()); }
static inline void set_green() { set_color(LEDColorGreen()); }
static inline void set_white() { set_color(LEDColorWhite()); }
#if ENABLED(NEO2_COLOR_PRESETS)
static const LEDColor defaultLEDColor;
static inline void set_default() { set_color(defaultLEDColor); }
static inline void set_red() { set_color(LEDColorRed()); }
static inline void set_orange() { set_color(LEDColorOrange()); }
static inline void set_yellow() { set_color(LEDColorYellow()); }
static inline void set_blue() { set_color(LEDColorBlue()); }
static inline void set_indigo() { set_color(LEDColorIndigo()); }
static inline void set_violet() { set_color(LEDColorViolet()); }
#endif
#if ENABLED(LED_CONTROL_MENU)
static LEDColor color; // last non-off color
static bool lights_on; // the last set color was "on"
static void toggle(); // swap "off" with color
static inline void update() { set_color(color); }
#endif
};
extern LEDLights2 leds2;
#endif // NEOPIXEL2_SEPARATE

View File

@ -30,7 +30,7 @@
#include "neopixel.h"
#if ENABLED(NEOPIXEL_STARTUP_TEST)
#if EITHER(NEOPIXEL_STARTUP_TEST, NEOPIXEL2_STARTUP_TEST)
#include "../../core/utility.h"
#endif
@ -38,7 +38,7 @@ Marlin_NeoPixel neo;
int8_t Marlin_NeoPixel::neoindex;
Adafruit_NeoPixel Marlin_NeoPixel::adaneo1(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIXEL_TYPE + NEO_KHZ800)
#if MULTIPLE_NEOPIXEL_TYPES
#if CONJOINED_NEOPIXEL
, Marlin_NeoPixel::adaneo2(NEOPIXEL_PIXELS, NEOPIXEL2_PIN, NEOPIXEL2_TYPE + NEO_KHZ800)
#endif
;
@ -53,9 +53,9 @@ Adafruit_NeoPixel Marlin_NeoPixel::adaneo1(NEOPIXEL_PIXELS, NEOPIXEL_PIN, NEOPIX
#endif
void Marlin_NeoPixel::set_color(const uint32_t color) {
if (get_neo_index() >= 0) {
set_pixel_color(get_neo_index(), color);
set_neo_index(-1);
if (neoindex >= 0) {
set_pixel_color(neoindex, color);
neoindex = -1;
}
else {
for (uint16_t i = 0; i < pixels(); ++i) {
@ -78,18 +78,18 @@ void Marlin_NeoPixel::set_color_startup(const uint32_t color) {
}
void Marlin_NeoPixel::init() {
set_neo_index(-1); // -1 .. NEOPIXEL_PIXELS-1 range
neoindex = -1; // -1 .. NEOPIXEL_PIXELS-1 range
set_brightness(NEOPIXEL_BRIGHTNESS); // 0 .. 255 range
begin();
show(); // initialize to all off
#if ENABLED(NEOPIXEL_STARTUP_TEST)
set_color_startup(adaneo1.Color(255, 0, 0, 0)); // red
safe_delay(1000);
safe_delay(500);
set_color_startup(adaneo1.Color(0, 255, 0, 0)); // green
safe_delay(1000);
safe_delay(500);
set_color_startup(adaneo1.Color(0, 0, 255, 0)); // blue
safe_delay(1000);
safe_delay(500);
#endif
#ifdef NEOPIXEL_BKGD_LED_INDEX
@ -120,4 +120,53 @@ bool Marlin_NeoPixel::set_led_color(const uint8_t r, const uint8_t g, const uint
}
#endif
#if ENABLED(NEOPIXEL2_SEPARATE)
Marlin_NeoPixel2 neo2;
int8_t Marlin_NeoPixel2::neoindex;
Adafruit_NeoPixel Marlin_NeoPixel2::adaneo(NEOPIXEL2_PIXELS, NEOPIXEL2_PIN, NEOPIXEL2_TYPE);
void Marlin_NeoPixel2::set_color(const uint32_t color) {
if (neoindex >= 0) {
set_pixel_color(neoindex, color);
neoindex = -1;
}
else {
for (uint16_t i = 0; i < pixels(); ++i)
set_pixel_color(i, color);
}
show();
}
void Marlin_NeoPixel2::set_color_startup(const uint32_t color) {
for (uint16_t i = 0; i < pixels(); ++i)
set_pixel_color(i, color);
show();
}
void Marlin_NeoPixel2::init() {
neoindex = -1; // -1 .. NEOPIXEL2_PIXELS-1 range
set_brightness(NEOPIXEL2_BRIGHTNESS); // 0 .. 255 range
begin();
show(); // initialize to all off
#if ENABLED(NEOPIXEL2_STARTUP_TEST)
set_color_startup(adaneo.Color(255, 0, 0, 0)); // red
safe_delay(500);
set_color_startup(adaneo.Color(0, 255, 0, 0)); // green
safe_delay(500);
set_color_startup(adaneo.Color(0, 0, 255, 0)); // blue
safe_delay(500);
#endif
#if ENABLED(NEO2_USER_PRESET_STARTUP)
set_color(adaneo.Color(NEO2_USER_PRESET_RED, NEO2_USER_PRESET_GREEN, NEO2_USER_PRESET_BLUE, NEO2_USER_PRESET_WHITE));
#else
set_color(adaneo.Color(0, 0, 0, 0));
#endif
}
#endif // NEOPIXEL2_SEPARATE
#endif // NEOPIXEL_LED

View File

@ -22,7 +22,7 @@
#pragma once
/**
* Neopixel support
* NeoPixel support
*/
// ------------------------
@ -38,10 +38,14 @@
// Defines
// ------------------------
#if defined(NEOPIXEL2_TYPE) && NEOPIXEL2_TYPE != NEOPIXEL_TYPE
#if defined(NEOPIXEL2_TYPE) && NEOPIXEL2_TYPE != NEOPIXEL_TYPE && DISABLED(NEOPIXEL2_SEPARATE)
#define MULTIPLE_NEOPIXEL_TYPES 1
#endif
#if EITHER(MULTIPLE_NEOPIXEL_TYPES, NEOPIXEL2_INSERIES)
#define CONJOINED_NEOPIXEL 1
#endif
#if NEOPIXEL_TYPE == NEO_RGB || NEOPIXEL_TYPE == NEO_RBG || NEOPIXEL_TYPE == NEO_GRB || NEOPIXEL_TYPE == NEO_GBR || NEOPIXEL_TYPE == NEO_BRG || NEOPIXEL_TYPE == NEO_BGR
#define NEOPIXEL_IS_RGB 1
#else
@ -61,44 +65,49 @@
class Marlin_NeoPixel {
private:
static Adafruit_NeoPixel adaneo1
#if MULTIPLE_NEOPIXEL_TYPES
#if CONJOINED_NEOPIXEL
, adaneo2
#endif
;
static int8_t neoindex;
public:
static int8_t neoindex;
static void init();
static void set_color_startup(const uint32_t c);
static void set_color(const uint32_t c);
FORCE_INLINE static void set_neo_index(const int8_t neoIndex) { neoindex = neoIndex; }
FORCE_INLINE static int8_t get_neo_index() { return neoindex; }
#ifdef NEOPIXEL_BKGD_LED_INDEX
static void set_color_background();
#endif
static inline void begin() {
adaneo1.begin();
TERN_(MULTIPLE_NEOPIXEL_TYPES, adaneo2.begin());
TERN_(CONJOINED_NEOPIXEL, adaneo2.begin());
}
static inline void set_pixel_color(const uint16_t n, const uint32_t c) {
adaneo1.setPixelColor(n, c);
TERN_(MULTIPLE_NEOPIXEL_TYPES, adaneo2.setPixelColor(n, c));
#if ENABLED(NEOPIXEL2_INSERIES)
if (n >= NEOPIXEL_PIXELS) adaneo2.setPixelColor(n - (NEOPIXEL_PIXELS), c);
else adaneo1.setPixelColor(n, c);
#else
adaneo1.setPixelColor(n, c);
#if MULTIPLE_NEOPIXEL_TYPES
adaneo2.setPixelColor(n, c);
#endif
#endif
}
static inline void set_brightness(const uint8_t b) {
adaneo1.setBrightness(b);
TERN_(MULTIPLE_NEOPIXEL_TYPES, adaneo2.setBrightness(b));
TERN_(CONJOINED_NEOPIXEL, adaneo2.setBrightness(b));
}
static inline void show() {
adaneo1.show();
#if PIN_EXISTS(NEOPIXEL2)
#if MULTIPLE_NEOPIXEL_TYPES
#if CONJOINED_NEOPIXEL
adaneo2.show();
#else
adaneo1.setPin(NEOPIXEL2_PIN);
@ -113,7 +122,7 @@ public:
#endif
// Accessors
static inline uint16_t pixels() { return adaneo1.numPixels(); }
static inline uint16_t pixels() { TERN(NEOPIXEL2_INSERIES, return adaneo1.numPixels() * 2, return adaneo1.numPixels()); }
static inline uint8_t brightness() { return adaneo1.getBrightness(); }
static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
return adaneo1.Color(r, g, b, w);
@ -121,3 +130,47 @@ public:
};
extern Marlin_NeoPixel neo;
// Neo pixel channel 2
#if ENABLED(NEOPIXEL2_SEPARATE)
#if NEOPIXEL2_TYPE == NEO_RGB || NEOPIXEL2_TYPE == NEO_RBG || NEOPIXEL2_TYPE == NEO_GRB || NEOPIXEL2_TYPE == NEO_GBR || NEOPIXEL2_TYPE == NEO_BRG || NEOPIXEL2_TYPE == NEO_BGR
#define NEOPIXEL2_IS_RGB 1
#else
#define NEOPIXEL2_IS_RGBW 1
#endif
#if NEOPIXEL2_IS_RGB
#define NEO2_WHITE 255, 255, 255, 0
#else
#define NEO2_WHITE 0, 0, 0, 255
#endif
class Marlin_NeoPixel2 {
private:
static Adafruit_NeoPixel adaneo;
public:
static int8_t neoindex;
static void init();
static void set_color_startup(const uint32_t c);
static void set_color(const uint32_t c);
static inline void begin() { adaneo.begin(); }
static inline void set_pixel_color(const uint16_t n, const uint32_t c) { adaneo.setPixelColor(n, c); }
static inline void set_brightness(const uint8_t b) { adaneo.setBrightness(b); }
static inline void show() { adaneo.show(); }
// Accessors
static inline uint16_t pixels() { return adaneo.numPixels();}
static inline uint8_t brightness() { return adaneo.getBrightness(); }
static inline uint32_t Color(uint8_t r, uint8_t g, uint8_t b, uint8_t w) {
return adaneo.Color(r, g, b, w);
}
};
extern Marlin_NeoPixel2 neo2;
#endif // NEOPIXEL2_SEPARATE

View File

@ -62,7 +62,7 @@ void PCA9533_setOff() {
PCA9533_writeRegister(PCA9533_REG_SEL, 0);
}
void PCA9533_setColor(uint8_t red, uint8_t green, uint8_t blue) {
void PCA9533_set_rgb(uint8_t red, uint8_t green, uint8_t blue) {
uint8_t r_pwm0 = 0; // Register data - PWM value
uint8_t r_pwm1 = 0; // Register data - PWM value

View File

@ -55,5 +55,5 @@
void PCA9533_init();
void PCA9533_reset();
void PCA9533_setColor(uint8_t red, uint8_t green, uint8_t blue);
void PCA9533_set_rgb(uint8_t red, uint8_t green, uint8_t blue);
void PCA9533_setOff();

View File

@ -120,7 +120,7 @@ static void PCA9632_WriteAllRegisters(const byte addr, const byte regadd, const
}
#endif
void pca9632_set_led_color(const LEDColor &color) {
void PCA9632_set_led_color(const LEDColor &color) {
Wire.begin();
if (!PCA_init) {
PCA_init = 1;
@ -138,7 +138,7 @@ void pca9632_set_led_color(const LEDColor &color) {
#if ENABLED(PCA9632_BUZZER)
void pca9632_buzz(const long, const uint16_t) {
void PCA9632_buzz(const long, const uint16_t) {
uint8_t data[] = PCA9632_BUZZER_DATA;
Wire.beginTransmission(I2C_ADDRESS(PCA9632_ADDRESS));
Wire.write(data, sizeof(data));

View File

@ -29,9 +29,9 @@
struct LEDColor;
typedef LEDColor LEDColor;
void pca9632_set_led_color(const LEDColor &color);
void PCA9632_set_led_color(const LEDColor &color);
#if ENABLED(PCA9632_BUZZER)
#include <stdint.h>
void pca9632_buzz(const long, const uint16_t);
void PCA9632_buzz(const long, const uint16_t);
#endif

View File

@ -21,7 +21,7 @@
*/
/**
* printer_event_leds.cpp - LED color changing based on printer status
* feature/leds/printer_event_leds.cpp - LED color changing based on printer status
*/
#include "../../inc/MarlinConfigPre.h"

View File

@ -22,7 +22,7 @@
#pragma once
/**
* printer_event_leds.h - LED color changing based on printer status
* feature/leds/printer_event_leds.h - LED color changing based on printer status
*/
#include "leds.h"

View File

@ -0,0 +1,58 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(PASSWORD_FEATURE)
#include "password.h"
#include "../../gcode/gcode.h"
#include "../../core/serial.h"
Password password;
// public:
bool Password::is_set, Password::is_locked;
uint32_t Password::value, Password::value_entry;
//
// Authenticate user with password.
// Called from Setup, after SD Prinitng Stops/Aborts, and M510
//
void Password::lock_machine() {
is_locked = true;
TERN_(HAS_LCD_MENU, authenticate_user(ui.status_screen, screen_password_entry));
}
//
// Authentication check
//
void Password::authentication_check() {
if (value_entry == value)
is_locked = false;
else
SERIAL_ECHOLNPGM(STR_WRONG_PASSWORD);
TERN_(HAS_LCD_MENU, authentication_done());
}
#endif // PASSWORD_FEATURE

View File

@ -0,0 +1,57 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#include "../../lcd/ultralcd.h"
class Password {
public:
static bool is_set, is_locked;
static uint32_t value, value_entry;
Password() { is_locked = false; }
static void lock_machine();
#if HAS_LCD_MENU
static void access_menu_password();
static void authentication_check();
static void authentication_done();
static void media_gatekeeper();
private:
static void authenticate_user(const screenFunc_t, const screenFunc_t);
static void menu_password();
static void menu_password_entry();
static void screen_password_entry();
static void screen_set_password();
static void start_over();
static void digit_entered();
static void set_password_done();
static void menu_password_report();
static void remove_password();
#endif
};
extern Password password;

View File

@ -413,7 +413,7 @@ bool pause_print(const float &retract, const xyz_pos_t &park_point, const float
unscaled_e_move(retract, PAUSE_PARK_RETRACT_FEEDRATE);
// Park the nozzle by moving up by z_lift and then moving to (x_pos, y_pos)
if (!axes_need_homing())
if (!axes_should_home())
nozzle.park(0, park_point);
#if ENABLED(DUAL_X_CARRIAGE)
@ -582,6 +582,9 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le
TERN_(HAS_LCD_MENU, lcd_pause_show_message(PAUSE_MESSAGE_RESUME));
// Check Temperature before moving hotend
ensure_safe_temperature();
// Retract to prevent oozing
unscaled_e_move(-(PAUSE_PARK_RETRACT_LENGTH), feedRate_t(PAUSE_PARK_RETRACT_FEEDRATE));
@ -594,8 +597,6 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le
// Unretract
unscaled_e_move(PAUSE_PARK_RETRACT_LENGTH, feedRate_t(PAUSE_PARK_RETRACT_FEEDRATE));
ensure_safe_temperature();
// Intelligent resuming
#if ENABLED(FWRETRACT)
// If retracted before goto pause

View File

@ -59,7 +59,6 @@ bool Power::is_power_needed() {
// If any of the drivers or the bed are enabled...
if (X_ENABLE_READ() == X_ENABLE_ON || Y_ENABLE_READ() == Y_ENABLE_ON || Z_ENABLE_READ() == Z_ENABLE_ON
|| TERN0(HAS_HEATED_BED, thermalManager.temp_bed.soft_pwm_amount > 0)
#if HAS_X2_ENABLE
|| X2_ENABLE_READ() == X_ENABLE_ON
#endif
@ -75,8 +74,8 @@ bool Power::is_power_needed() {
#endif
) return true;
HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0) return true;
if (TERN0(HAS_HEATED_BED, thermalManager.degTargetBed() > 0)) return true;
HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0 || thermalManager.temp_hotend[e].soft_pwm_amount > 0) return true;
if (TERN0(HAS_HEATED_BED, thermalManager.degTargetBed() > 0 || thermalManager.temp_bed.soft_pwm_amount > 0)) return true;
#if HAS_HOTEND && AUTO_POWER_E_TEMP
HOTEND_LOOP() if (thermalManager.degHotend(e) >= AUTO_POWER_E_TEMP) return true;

View File

@ -21,7 +21,7 @@
*/
/**
* power_loss_recovery.cpp - Resume an SD print after power-loss
* feature/powerloss.cpp - Resume an SD print after power-loss
*/
#include "../inc/MarlinConfigPre.h"
@ -365,7 +365,7 @@ void PrintJobRecovery::resume() {
#endif
// Pretend that all axes are homed
axis_homed = axis_known_position = xyz_bits;
set_all_homed();
// Recover volumetric extrusion state
#if DISABLED(NO_VOLUMETRICS)

View File

@ -22,7 +22,7 @@
#pragma once
/**
* power_loss_recovery.h - Resume an SD print after power-loss
* feature/powerloss.h - Resume an SD print after power-loss
*/
#include "../sd/cardreader.h"

View File

@ -44,14 +44,6 @@ bool FilamentMonitorBase::enabled = true,
#include "../module/tool_change.h"
#endif
/**
* Called by FilamentSensorSwitch::run when filament is detected.
* Called by FilamentSensorEncoder::block_completed when motion is detected.
*/
void FilamentSensorBase::filament_present(const uint8_t extruder) {
runout.filament_present(extruder); // calls response.filament_present(extruder)
}
#if HAS_FILAMENT_RUNOUT_DISTANCE
float RunoutResponseDelayed::runout_distance_mm = FILAMENT_RUNOUT_DISTANCE_MM;
volatile float RunoutResponseDelayed::runout_mm_countdown[EXTRUDERS];

View File

@ -48,6 +48,24 @@
void event_filament_runout();
template<class RESPONSE_T, class SENSOR_T>
class TFilamentMonitor;
class FilamentSensorEncoder;
class FilamentSensorSwitch;
class RunoutResponseDelayed;
class RunoutResponseDebounced;
/********************************* TEMPLATE SPECIALIZATION *********************************/
typedef TFilamentMonitor<
TERN(HAS_FILAMENT_RUNOUT_DISTANCE, RunoutResponseDelayed, RunoutResponseDebounced),
TERN(FILAMENT_MOTION_SENSOR, FilamentSensorEncoder, FilamentSensorSwitch)
> FilamentMonitor;
extern FilamentMonitor runout;
/*******************************************************************************************/
class FilamentMonitorBase {
public:
static bool enabled, filament_ran_out;
@ -121,7 +139,13 @@ class TFilamentMonitor : public FilamentMonitorBase {
class FilamentSensorBase {
protected:
static void filament_present(const uint8_t extruder);
/**
* Called by FilamentSensorSwitch::run when filament is detected.
* Called by FilamentSensorEncoder::block_completed when motion is detected.
*/
static inline void filament_present(const uint8_t extruder) {
runout.filament_present(extruder); // ...which calls response.filament_present(extruder)
}
public:
static inline void setup() {
@ -311,12 +335,3 @@ class FilamentSensorBase {
};
#endif // !HAS_FILAMENT_RUNOUT_DISTANCE
/********************************* TEMPLATE SPECIALIZATION *********************************/
typedef TFilamentMonitor<
TERN(HAS_FILAMENT_RUNOUT_DISTANCE, RunoutResponseDelayed, RunoutResponseDebounced),
TERN(FILAMENT_MOTION_SENSOR, FilamentSensorEncoder, FilamentSensorSwitch)
> FilamentMonitor;
extern FilamentMonitor runout;

View File

@ -37,7 +37,7 @@ cutter_power_t SpindleLaser::menuPower, // Power s
SpindleLaser::unitPower; // LCD status power in PWM, PERCENT, or RPM
#if ENABLED(MARLIN_DEV_MODE)
cutter_frequency_t SpindleLaser::frequency; // setting PWM frequency; range: 2K - 50K
cutter_frequency_t SpindleLaser::frequency; // PWM frequency setting; range: 2K - 50K
#endif
#define SPINDLE_LASER_PWM_OFF ((SPINDLE_LASER_PWM_INVERT) ? 255 : 0)
@ -45,13 +45,13 @@ cutter_power_t SpindleLaser::menuPower, // Power s
// Init the cutter to a safe OFF state
//
void SpindleLaser::init() {
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_HIGH); // Init spindle to off
OUT_WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Init spindle to off
#if ENABLED(SPINDLE_CHANGE_DIR)
OUT_WRITE(SPINDLE_DIR_PIN, SPINDLE_INVERT_DIR ? 255 : 0); // Init rotation to clockwise (M3)
#endif
#if ENABLED(SPINDLE_LASER_PWM)
SET_PWM(SPINDLE_LASER_PWM_PIN);
analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // set to lowest speed
analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Set to lowest speed
#endif
#if ENABLED(HAL_CAN_SET_PWM_FREQ) && defined(SPINDLE_LASER_FREQUENCY)
set_pwm_frequency(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_FREQUENCY);
@ -64,14 +64,14 @@ void SpindleLaser::init() {
* Set the cutter PWM directly to the given ocr value
*/
void SpindleLaser::set_ocr(const uint8_t ocr) {
WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_HIGH); // turn spindle on
WRITE(SPINDLE_LASER_ENA_PIN, SPINDLE_LASER_ACTIVE_STATE); // Turn spindle on
analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
#if NEEDS_HARDWARE_PWM && SPINDLE_LASER_FREQUENCY
set_pwm_duty(pin_t(SPINDLE_LASER_PWM_PIN), ocr ^ SPINDLE_LASER_PWM_OFF);
#endif
#endif
}
void SpindleLaser::ocr_off() {
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_HIGH); // Turn spindle off
WRITE(SPINDLE_LASER_ENA_PIN, !SPINDLE_LASER_ACTIVE_STATE); // Turn spindle off
analogWrite(pin_t(SPINDLE_LASER_PWM_PIN), SPINDLE_LASER_PWM_OFF); // Only write low byte
}
#endif
@ -98,7 +98,7 @@ void SpindleLaser::apply_power(const uint8_t opwr) {
isReady = false;
}
#else
WRITE(SPINDLE_LASER_ENA_PIN, enabled() == SPINDLE_LASER_ACTIVE_HIGH);
WRITE(SPINDLE_LASER_ENA_PIN, enabled() ? SPINDLE_LASER_ACTIVE_STATE : !SPINDLE_LASER_ACTIVE_STATE);
isReady = true;
#endif
}

View File

@ -34,7 +34,7 @@
#if ENABLED(TMC_DEBUG)
#include "../module/planner.h"
#include "../libs/hex_print_routines.h"
#include "../libs/hex_print.h"
#if ENABLED(MONITOR_DRIVER_STATUS)
static uint16_t report_tmc_status_interval; // = 0
#endif

View File

@ -1,200 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
*
* 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(TOUCH_BUTTONS)
#include "xpt2046.h"
#include "../../inc/MarlinConfig.h"
#if ENABLED(FSMC_GRAPHICAL_TFT)
#include "../../lcd/dogm/ultralcd_DOGM.h" // for LCD_FULL_PIXEL_WIDTH, etc.
#endif
/*
* Draw and Touch processing
*
* LCD_PIXEL_WIDTH/HEIGHT (128x64) is the (emulated DOGM) Pixel Drawing resolution.
* TOUCH_SCREEN_WIDTH/HEIGHT (320x240) is the Touch Area resolution.
* LCD_FULL_PIXEL_WIDTH/HEIGHT (320x240 or 480x320) is the Actual (FSMC) Display resolution.
*
* - All native (u8g) drawing is done in LCD_PIXEL_* (128x64)
* - The DOGM pixels are is upscaled 2-3x (as needed) for display.
* - Touch coordinates use TOUCH_SCREEN_* resolution and are converted to
* click and scroll-wheel events (emulating of a common DOGM display).
*
* TOUCH_SCREEN resolution exists to fit our calibration values. The original touch code was made
* and originally calibrated for 320x240. If you decide to change the resolution of the touch code,
* new calibration values will be needed.
*
* The Marlin menus are drawn scaled in the upper region of the screen. The bottom region (in a
* fixed location in TOUCH_SCREEN* coordinate space) is used for 4 general-purpose buttons to
* navigate and select menu items. Both regions are touchable.
*
* The Marlin screen touchable area starts at LCD_PIXEL_OFFSET_X/Y (translated to SCREEN_START_LEFT/TOP)
* and spans LCD_PIXEL_WIDTH/HEIGHT (scaled to SCREEN_WIDTH/HEIGHT).
*/
// Touch screen resolution independent of display resolution
#define TOUCH_SCREEN_HEIGHT 240
#define TOUCH_SCREEN_WIDTH 320
// Coordinates in terms of touch area
#define BUTTON_AREA_TOP 175
#define BUTTON_AREA_BOT 234
#define SCREEN_START_TOP ((LCD_PIXEL_OFFSET_Y) * (TOUCH_SCREEN_HEIGHT) / (LCD_FULL_PIXEL_HEIGHT))
#define SCREEN_START_LEFT ((LCD_PIXEL_OFFSET_X) * (TOUCH_SCREEN_WIDTH) / (LCD_FULL_PIXEL_WIDTH))
#define SCREEN_HEIGHT ((LCD_PIXEL_HEIGHT * FSMC_UPSCALE) * (TOUCH_SCREEN_HEIGHT) / (LCD_FULL_PIXEL_HEIGHT))
#define SCREEN_WIDTH ((LCD_PIXEL_WIDTH * FSMC_UPSCALE) * (TOUCH_SCREEN_WIDTH) / (LCD_FULL_PIXEL_WIDTH))
#define TOUCHABLE_Y_HEIGHT SCREEN_HEIGHT
#define TOUCHABLE_X_WIDTH SCREEN_WIDTH
#ifndef TOUCH_INT_PIN
#define TOUCH_INT_PIN -1
#endif
#ifndef TOUCH_MISO_PIN
#define TOUCH_MISO_PIN MISO_PIN
#endif
#ifndef TOUCH_MOSI_PIN
#define TOUCH_MOSI_PIN MOSI_PIN
#endif
#ifndef TOUCH_SCK_PIN
#define TOUCH_SCK_PIN SCK_PIN
#endif
#ifndef TOUCH_CS_PIN
#define TOUCH_CS_PIN CS_PIN
#endif
XPT2046 touch;
void XPT2046::init() {
SET_INPUT(TOUCH_MISO_PIN);
SET_OUTPUT(TOUCH_MOSI_PIN);
SET_OUTPUT(TOUCH_SCK_PIN);
OUT_WRITE(TOUCH_CS_PIN, HIGH);
#if PIN_EXISTS(TOUCH_INT)
// Optional Pendrive interrupt pin
SET_INPUT(TOUCH_INT_PIN);
#endif
// Read once to enable pendrive status pin
getInTouch(XPT2046_X);
}
#include "../../lcd/ultralcd.h" // For EN_C bit mask
uint8_t XPT2046::read_buttons() {
#ifdef HAS_SPI_LCD
int16_t tsoffsets[4] = { 0 };
if (tsoffsets[0] + tsoffsets[1] == 0) {
// Not yet set, so use defines as fallback...
tsoffsets[0] = XPT2046_X_CALIBRATION;
tsoffsets[1] = XPT2046_X_OFFSET;
tsoffsets[2] = XPT2046_Y_CALIBRATION;
tsoffsets[3] = XPT2046_Y_OFFSET;
}
// We rely on XPT2046 compatible mode to ADS7843, hence no Z1 and Z2 measurements possible.
if (!isTouched()) return 0;
const uint16_t x = uint16_t(((uint32_t(getInTouch(XPT2046_X))) * tsoffsets[0]) >> 16) + tsoffsets[1],
y = uint16_t(((uint32_t(getInTouch(XPT2046_Y))) * tsoffsets[2]) >> 16) + tsoffsets[3];
if (!isTouched()) return 0; // Fingers must still be on the TS for a valid read.
// Touch within the button area simulates an encoder button
if (y > BUTTON_AREA_TOP && y < BUTTON_AREA_BOT)
return WITHIN(x, 14, 77) ? EN_D
: WITHIN(x, 90, 153) ? EN_A
: WITHIN(x, 166, 229) ? EN_B
: WITHIN(x, 242, 305) ? EN_C
: 0;
if (x > TOUCH_SCREEN_WIDTH || !WITHIN(y, SCREEN_START_TOP, SCREEN_START_TOP + SCREEN_HEIGHT)) return 0;
// Column and row above BUTTON_AREA_TOP
int8_t col = (x - (SCREEN_START_LEFT)) * (LCD_WIDTH) / (TOUCHABLE_X_WIDTH),
row = (y - (SCREEN_START_TOP)) * (LCD_HEIGHT) / (TOUCHABLE_Y_HEIGHT);
// Send the touch to the UI (which will simulate the encoder wheel)
MarlinUI::screen_click(row, col, x, y);
#endif
return 0;
}
bool XPT2046::isTouched() {
return (
#if PIN_EXISTS(TOUCH_INT)
READ(TOUCH_INT_PIN) != HIGH
#else
getInTouch(XPT2046_Z1) >= XPT2046_Z1_THRESHOLD
#endif
);
}
uint16_t XPT2046::getInTouch(const XPTCoordinate coordinate) {
uint16_t data[3];
OUT_WRITE(TOUCH_CS_PIN, LOW);
const uint8_t coord = uint8_t(coordinate) | XPT2046_CONTROL | XPT2046_DFR_MODE;
for (uint16_t i = 0; i < 3 ; i++) {
for (uint8_t j = 0x80; j; j >>= 1) {
WRITE(TOUCH_SCK_PIN, LOW);
WRITE(TOUCH_MOSI_PIN, bool(coord & j));
WRITE(TOUCH_SCK_PIN, HIGH);
}
data[i] = 0;
for (uint16_t j = 0x8000; j; j >>= 1) {
WRITE(TOUCH_SCK_PIN, LOW);
if (READ(TOUCH_MISO_PIN)) data[i] |= j;
WRITE(TOUCH_SCK_PIN, HIGH);
}
WRITE(TOUCH_SCK_PIN, LOW);
data[i] >>= 4;
}
WRITE(TOUCH_CS_PIN, HIGH);
uint16_t delta01 = _MAX(data[0], data[1]) - _MIN(data[0], data[1]),
delta02 = _MAX(data[0], data[2]) - _MIN(data[0], data[2]),
delta12 = _MAX(data[1], data[2]) - _MIN(data[1], data[2]);
if (delta01 <= delta02 && delta01 <= delta12)
return (data[0] + data[1]) >> 1;
if (delta02 <= delta12)
return (data[0] + data[2]) >> 1;
return (data[1] + data[2]) >> 1;
}
bool XPT2046::getTouchPoint(uint16_t &x, uint16_t &y) {
if (isTouched()) {
x = getInTouch(XPT2046_X);
y = getInTouch(XPT2046_Y);
}
return isTouched();
}
#endif // TOUCH_BUTTONS

View File

@ -405,7 +405,7 @@ inline bool turn_on_heaters() {
inline bool prime_nozzle() {
const feedRate_t fr_slow_e = planner.settings.max_feedrate_mm_s[E_AXIS] / 15.0f;
#if HAS_LCD_MENU && DISABLED(TOUCH_BUTTONS) // ui.button_pressed issue with touchscreen
#if HAS_LCD_MENU && !HAS_TOUCH_XPT2046 // ui.button_pressed issue with touchscreen
#if ENABLED(PREVENT_LENGTHY_EXTRUDE)
float Total_Prime = 0.0;
#endif
@ -490,7 +490,7 @@ void GcodeSuite::G26() {
// Don't allow Mesh Validation without homing first,
// or if the parameter parsing did not go OK, abort
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
// Change the tool first, if specified
if (parser.seenval('T')) tool_change(parser.value_int());

View File

@ -176,7 +176,7 @@ void GcodeSuite::G35() {
probe.stow();
// After this operation the Z position needs correction
set_axis_not_trusted(Z_AXIS);
set_axis_never_homed(Z_AXIS);
// Home Z after the alignment procedure
process_subcommands_now_P(PSTR("G28Z"));

View File

@ -30,7 +30,7 @@
#include "../../module/probe.h"
#if ENABLED(EEPROM_SETTINGS)
#include "../../module/configuration_store.h"
#include "../../module/settings.h"
#endif
#if ENABLED(EXTENSIBLE_UI)

View File

@ -183,7 +183,7 @@ G29_TYPE GcodeSuite::G29() {
faux = ENABLED(DEBUG_LEVELING_FEATURE) && DISABLED(PROBE_MANUALLY) ? parser.boolval('C') : no_action;
// Don't allow auto-leveling without homing first
if (axis_unhomed_error()) G29_RETURN(false);
if (homing_needed_error()) G29_RETURN(false);
if (!no_action && planner.leveling_active && parser.boolval('O')) { // Auto-level only if needed
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> Auto-level not needed, skip");

View File

@ -118,7 +118,7 @@
DEBUG_SECTION(log_G28, "home_z_safely", DEBUGGING(LEVELING));
// Disallow Z homing if X or Y homing is needed
if (axis_unhomed_error(_BV(X_AXIS) | _BV(Y_AXIS))) return;
if (homing_needed_error(_BV(X_AXIS) | _BV(Y_AXIS))) return;
sync_plan_position();
@ -299,8 +299,8 @@ void GcodeSuite::G28() {
#else // NOT DELTA
const bool homeZ = parser.seen('Z'),
needX = homeZ && TERN0(Z_SAFE_HOMING, axes_need_homing(_BV(X_AXIS))),
needY = homeZ && TERN0(Z_SAFE_HOMING, axes_need_homing(_BV(Y_AXIS))),
needX = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(X_AXIS))),
needY = homeZ && TERN0(Z_SAFE_HOMING, axes_should_home(_BV(Y_AXIS))),
homeX = needX || parser.seen('X'), homeY = needY || parser.seen('Y'),
home_all = homeX == homeY && homeX == homeZ, // All or None
doX = home_all || homeX, doY = home_all || homeY, doZ = home_all || homeZ;

View File

@ -346,7 +346,7 @@ void GcodeSuite::G34() {
#if ENABLED(HOME_AFTER_G34)
// After this operation the z position needs correction
set_axis_not_trusted(Z_AXIS);
set_axis_never_homed(Z_AXIS);
// Home Z after the alignment procedure
process_subcommands_now_P(PSTR("G28Z"));
#else

View File

@ -584,7 +584,7 @@ void GcodeSuite::G425() {
TEMPORARY_SOFT_ENDSTOP_STATE(false);
TEMPORARY_BED_LEVELING_STATE(false);
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
measurements_t m;

View File

@ -45,7 +45,7 @@
* - When calibrating bed, probe temperature is held constant.
* Compensation values are deltas to first probe measurement at bed temp. = 60°C.
* - The hotend will not be heated at any time.
* - On my Prusa MK3S clone I put a piece of paper between the probe and the hotend
* - On my Průša MK3S clone I put a piece of paper between the probe and the hotend
* so the hotend fan would not cool my probe constantly. Alternativly you could just
* make sure the fan is not running while running the calibration process.
*

View File

@ -26,7 +26,7 @@
#include "../gcode.h"
#include "../queue.h"
#include "../../libs/hex_print_routines.h"
#include "../../libs/hex_print.h"
#include "../../MarlinCore.h" // for idle()
@ -156,8 +156,8 @@ inline int32_t count_test_bytes(const char * const start_free_memory) {
// Start and end the dump on a nice 16 byte boundary
// (even though the values are not 16-byte aligned).
//
start_free_memory = (char*)(ptr_int_t(uint32_t(start_free_memory) & ~0xFUL)); // Align to 16-byte boundary
end_free_memory = (char*)(ptr_int_t(uint32_t(end_free_memory) | 0xFUL)); // Align end_free_memory to the 15th byte (at or above end_free_memory)
start_free_memory = (char*)(uintptr_t(uint32_t(start_free_memory) & ~0xFUL)); // Align to 16-byte boundary
end_free_memory = (char*)(uintptr_t(uint32_t(end_free_memory) | 0xFUL)); // Align end_free_memory to the 15th byte (at or above end_free_memory)
// Dump command main loop
while (start_free_memory < end_free_memory) {
@ -189,8 +189,8 @@ inline int32_t count_test_bytes(const char * const start_free_memory) {
// Round the start and end locations to produce full lines of output
//
dump_free_memory(
(char*)(ptr_int_t(uint32_t(start) & ~0xFUL)), // Align to 16-byte boundary
(char*)(ptr_int_t(uint32_t(end) | 0xFUL)) // Align end_free_memory to the 15th byte (at or above end_free_memory)
(char*)(uintptr_t(uint32_t(start) & ~0xFUL)), // Align to 16-byte boundary
(char*)(uintptr_t(uint32_t(end) | 0xFUL)) // Align end_free_memory to the 15th byte (at or above end_free_memory)
);
}

View File

@ -27,13 +27,10 @@
#include "../gcode.h"
#include "../../module/motion.h"
#include "../../module/probe.h"
#include "../../lcd/ultralcd.h"
#include "../../feature/bedlevel/bedlevel.h"
#if HAS_SPI_LCD
#include "../../lcd/ultralcd.h"
#endif
#if HAS_LEVELING
#include "../../module/planner.h"
#endif
@ -58,7 +55,7 @@ extern const char SP_Y_STR[];
void GcodeSuite::M48() {
if (axis_unhomed_error()) return;
if (homing_needed_error()) return;
const int8_t verbose_level = parser.byteval('V', 1);
if (!WITHIN(verbose_level, 0, 4)) {
@ -77,61 +74,85 @@ void GcodeSuite::M48() {
const ProbePtRaise raise_after = parser.boolval('E') ? PROBE_PT_STOW : PROBE_PT_RAISE;
xy_float_t next_pos = current_position;
const xy_pos_t probe_pos = {
parser.linearval('X', next_pos.x + probe.offset_xy.x), // If no X use the probe's current X position
parser.linearval('Y', next_pos.y + probe.offset_xy.y) // If no Y, ditto
// Test at the current position by default, overridden by X and Y
const xy_pos_t test_position = {
parser.linearval('X', current_position.x + probe.offset_xy.x), // If no X use the probe's current X position
parser.linearval('Y', current_position.y + probe.offset_xy.y) // If no Y, ditto
};
if (!probe.can_reach(probe_pos)) {
if (!probe.can_reach(test_position)) {
ui.set_status_P(GET_TEXT(MSG_M48_OUT_OF_BOUNDS), 99);
SERIAL_ECHOLNPGM("? (X,Y) out of bounds.");
return;
}
// Get the number of leg moves per test-point
bool seen_L = parser.seen('L');
uint8_t n_legs = seen_L ? parser.value_byte() : 0;
if (n_legs > 15) {
SERIAL_ECHOLNPGM("?Number of legs in movement not plausible (0-15).");
SERIAL_ECHOLNPGM("?Legs of movement implausible (0-15).");
return;
}
if (n_legs == 1) n_legs = 2;
// Schizoid motion as an optional stress-test
const bool schizoid_flag = parser.boolval('S');
if (schizoid_flag && !seen_L) n_legs = 7;
/**
* Now get everything to the specified probe point So we can safely do a
* probe to get us close to the bed. If the Z-Axis is far from the bed,
* we don't want to use that as a starting point for each probe.
*/
if (verbose_level > 2)
SERIAL_ECHOLNPGM("Positioning the probe...");
// Disable bed level correction in M48 because we want the raw data when we probe
// Always disable Bed Level correction before probing...
#if HAS_LEVELING
const bool was_enabled = planner.leveling_active;
set_bed_leveling_enabled(false);
#endif
// Work with reasonable feedrates
remember_feedrate_scaling_off();
float mean = 0.0, sigma = 0.0, min = 99999.9, max = -99999.9, sample_set[n_samples];
// Working variables
float mean = 0.0, // The average of all points so far, used to calculate deviation
sigma = 0.0, // Standard deviation of all points so far
min = 99999.9, // Smallest value sampled so far
max = -99999.9, // Largest value sampled so far
sample_set[n_samples]; // Storage for sampled values
auto dev_report = [](const bool verbose, const float &mean, const float &sigma, const float &min, const float &max, const bool final=false) {
if (verbose) {
SERIAL_ECHOPAIR_F("Mean: ", mean, 6);
if (!final) SERIAL_ECHOPAIR_F(" Sigma: ", sigma, 6);
SERIAL_ECHOPAIR_F(" Min: ", min, 3);
SERIAL_ECHOPAIR_F(" Max: ", max, 3);
SERIAL_ECHOPAIR_F(" Range: ", max-min, 3);
if (final) SERIAL_EOL();
}
if (final) {
SERIAL_ECHOLNPAIR_F("Standard Deviation: ", sigma, 6);
SERIAL_EOL();
}
};
// Move to the first point, deploy, and probe
const float t = probe.probe_at_point(probe_pos, raise_after, verbose_level);
const float t = probe.probe_at_point(test_position, raise_after, verbose_level);
bool probing_good = !isnan(t);
if (probing_good) {
randomSeed(millis());
float sample_sum = 0.0;
LOOP_L_N(n, n_samples) {
#if HAS_SPI_LCD
// Display M48 progress in the status bar
ui.status_printf_P(0, PSTR(S_FMT ": %d/%d"), GET_TEXT(MSG_M48_POINT), int(n + 1), int(n_samples));
#endif
// When there are "legs" of movement move around the point before probing
if (n_legs) {
// Pick a random direction, starting angle, and radius
const int dir = (random(0, 10) > 5.0) ? -1 : 1; // clockwise or counter clockwise
float angle = random(0, 360);
const float radius = random(
@ -142,48 +163,51 @@ void GcodeSuite::M48() {
int(5), int(0.125 * _MIN(X_BED_SIZE, Y_BED_SIZE))
#endif
);
if (verbose_level > 3) {
SERIAL_ECHOPAIR("Start radius:", radius, " angle:", angle, " dir:");
if (dir > 0) SERIAL_CHAR('C');
SERIAL_ECHOLNPGM("CW");
}
// Move from leg to leg in rapid succession
LOOP_L_N(l, n_legs - 1) {
float delta_angle;
// Move some distance around the perimeter
float delta_angle;
if (schizoid_flag) {
// The points of a 5 point star are 72 degrees apart. We need to
// skip a point and go to the next one on the star.
// The points of a 5 point star are 72 degrees apart.
// Skip a point and go to the next one on the star.
delta_angle = dir * 2.0 * 72.0;
}
else {
// If we do this line, we are just trying to move further
// around the circle.
delta_angle = dir * (float) random(25, 45);
// Just move further along the perimeter.
delta_angle = dir * (float)random(25, 45);
}
angle += delta_angle;
while (angle > 360.0) angle -= 360.0; // We probably do not need to keep the angle between 0 and 2*PI, but the
// Arduino documentation says the trig functions should not be given values
while (angle < 0.0) angle += 360.0; // outside of this range. It looks like they behave correctly with
// numbers outside of the range, but just to be safe we clamp them.
const xy_pos_t noz_pos = probe_pos - probe.offset_xy;
next_pos.set(noz_pos.x + cos(RADIANS(angle)) * radius,
noz_pos.y + sin(RADIANS(angle)) * radius);
// Trig functions work without clamping, but just to be safe...
while (angle > 360.0) angle -= 360.0;
while (angle < 0.0) angle += 360.0;
#if DISABLED(DELTA)
LIMIT(next_pos.x, X_MIN_POS, X_MAX_POS);
LIMIT(next_pos.y, Y_MIN_POS, Y_MAX_POS);
#else
// If we have gone out too far, we can do a simple fix and scale the numbers
// back in closer to the origin.
// Choose the next position as an offset to chosen test position
const xy_pos_t noz_pos = test_position - probe.offset_xy;
xy_pos_t next_pos = {
noz_pos.x + cos(RADIANS(angle)) * radius,
noz_pos.y + sin(RADIANS(angle)) * radius
};
#if ENABLED(DELTA)
// If the probe can't reach the point on a round bed...
// Simply scale the numbers to bring them closer to origin.
while (!probe.can_reach(next_pos)) {
next_pos *= 0.8f;
if (verbose_level > 3)
SERIAL_ECHOLNPAIR_P(PSTR("Moving inward: X"), next_pos.x, SP_Y_STR, next_pos.y);
}
#else
// For a rectangular bed just keep the probe in bounds
LIMIT(next_pos.x, X_MIN_POS, X_MAX_POS);
LIMIT(next_pos.y, Y_MIN_POS, Y_MAX_POS);
#endif
if (verbose_level > 3)
@ -194,45 +218,35 @@ void GcodeSuite::M48() {
} // n_legs
// Probe a single point
sample_set[n] = probe.probe_at_point(probe_pos, raise_after, 0);
const float pz = probe.probe_at_point(test_position, raise_after, 0);
// Break the loop if the probe fails
probing_good = !isnan(sample_set[n]);
probing_good = !isnan(pz);
if (!probing_good) break;
/**
* Get the current mean for the data points we have so far
*/
float sum = 0.0;
LOOP_LE_N(j, n) sum += sample_set[j];
mean = sum / (n + 1);
// Store the new sample
sample_set[n] = pz;
NOMORE(min, sample_set[n]);
NOLESS(max, sample_set[n]);
// Keep track of the largest and smallest samples
NOMORE(min, pz);
NOLESS(max, pz);
/**
* Now, use that mean to calculate the standard deviation for the
* data points we have so far
*/
sum = 0.0;
LOOP_LE_N(j, n)
sum += sq(sample_set[j] - mean);
// Get the mean value of all samples thus far
sample_sum += pz;
mean = sample_sum / (n + 1);
sigma = SQRT(sum / (n + 1));
if (verbose_level > 0) {
if (verbose_level > 1) {
SERIAL_ECHO(n + 1);
SERIAL_ECHOPAIR(" of ", int(n_samples));
SERIAL_ECHOPAIR_F(": z: ", sample_set[n], 3);
if (verbose_level > 2) {
SERIAL_ECHOPAIR_F(" mean: ", mean, 4);
SERIAL_ECHOPAIR_F(" sigma: ", sigma, 6);
SERIAL_ECHOPAIR_F(" min: ", min, 3);
SERIAL_ECHOPAIR_F(" max: ", max, 3);
SERIAL_ECHOPAIR_F(" range: ", max-min, 3);
}
SERIAL_EOL();
}
// Calculate the standard deviation so far.
// The value after the last sample will be the final output.
float dev_sum = 0.0;
LOOP_LE_N(j, n) dev_sum += sq(sample_set[j] - mean);
sigma = SQRT(dev_sum / (n + 1));
if (verbose_level > 1) {
SERIAL_ECHO(n + 1);
SERIAL_ECHOPAIR(" of ", int(n_samples));
SERIAL_ECHOPAIR_F(": z: ", pz, 3);
dev_report(verbose_level > 2, mean, sigma, min, max);
SERIAL_EOL();
}
} // n_samples loop
@ -242,16 +256,7 @@ void GcodeSuite::M48() {
if (probing_good) {
SERIAL_ECHOLNPGM("Finished!");
if (verbose_level > 0) {
SERIAL_ECHOPAIR_F("Mean: ", mean, 6);
SERIAL_ECHOPAIR_F(" Min: ", min, 3);
SERIAL_ECHOPAIR_F(" Max: ", max, 3);
SERIAL_ECHOLNPAIR_F(" Range: ", max-min, 3);
}
SERIAL_ECHOLNPAIR_F("Standard Deviation: ", sigma, 6);
SERIAL_EOL();
dev_report(verbose_level > 0, mean, sigma, min, max, true);
#if HAS_SPI_LCD
// Display M48 results in the status bar

View File

@ -33,7 +33,21 @@
* B<baudrate> - Baud rate (bits per second)
*/
void GcodeSuite::M575() {
const int32_t baud = parser.ulongval('B');
int32_t baud = parser.ulongval('B');
switch (baud) {
case 24:
case 96:
case 192:
case 384:
case 576:
case 1152: baud *= 100; break;
case 250:
case 500: baud *= 1000; break;
case 19: baud = 19200; break;
case 38: baud = 38400; break;
case 57: baud = 57600; break;
case 115: baud = 115200; break;
}
switch (baud) {
case 2400: case 9600: case 19200: case 38400: case 57600:
case 115200: case 250000: case 500000: case 1000000: {

View File

@ -22,20 +22,12 @@
#include "../../inc/MarlinConfig.h"
#if ENABLED(SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
#if ENABLED(DUET_SMART_EFFECTOR) && PIN_EXISTS(SMART_EFFECTOR_MOD)
#include "../gcode.h"
#include "../../HAL/shared/Delay.h"
#include "../parser.h"
/**
* M672 - Set/reset Duet Smart Effector sensitivity
*
* One of these is required:
* S<sensitivity> - 0-255
* R - Flag to reset sensitivity to default
*/
/**
* The Marlin format for the M672 command is different than shown in the Duet Smart Effector
* documentation https://duet3d.dozuki.com/Wiki/Smart_effector_and_carriage_adapters_for_delta_printer
@ -77,6 +69,13 @@ void M672_send(uint8_t b) { // bit rate requirement: 1KHz +/- 30%
}
}
/**
* M672 - Set/reset Duet Smart Effector sensitivity
*
* One of these is required:
* S<sensitivity> - 0-255
* R - Flag to reset sensitivity to default
*/
void GcodeSuite::M672() {
if (parser.seen('R')) {
M672_send(M672_ERASEBYTE);
@ -96,4 +95,4 @@ void GcodeSuite::M672() {
OUT_WRITE(SMART_EFFECTOR_MOD_PIN, LOW); // Keep Smart Effector in NORMAL mode
}
#endif // SMART_EFFECTOR && SMART_EFFECTOR_MOD_PIN
#endif // DUET_SMART_EFFECTOR && SMART_EFFECTOR_MOD_PIN

View File

@ -21,16 +21,14 @@
*/
#include "../gcode.h"
#include "../../module/temperature.h"
#include "../../module/stepper.h"
#include "../../module/printcounter.h" // for print_job_timer
#include "../../module/planner.h" // for planner.finish_and_disable
#include "../../module/printcounter.h" // for print_job_timer.stop
#include "../../lcd/ultralcd.h" // for LCD_MESSAGEPGM_P
#include "../../inc/MarlinConfig.h"
#if HAS_LCD_MENU
#include "../../lcd/ultralcd.h"
#endif
#if HAS_SUICIDE
#include "../../MarlinCore.h"
#endif
@ -39,6 +37,8 @@
#if ENABLED(AUTO_POWER_CONTROL)
#include "../../feature/power.h"
#else
void restore_stepper_drivers();
#endif
// Could be moved to a feature, but this is all the data
@ -108,7 +108,5 @@ void GcodeSuite::M81() {
PSU_OFF();
#endif
#if HAS_LCD_MENU
LCD_MESSAGEPGM_P(PSTR(MACHINE_NAME " " STR_OFF "."));
#endif
LCD_MESSAGEPGM_P(PSTR(MACHINE_NAME " " STR_OFF "."));
}

Some files were not shown because too many files have changed in this diff Show More