Merge remote-tracking branch 'upstream/bugfix-2.0.x' into 2.0.x
This commit is contained in:
commit
b90e7c421f
4
.github/pull_request_template.md
vendored
4
.github/pull_request_template.md
vendored
@ -14,6 +14,10 @@ We must be able to understand your proposed change from this description. If we
|
||||
|
||||
<!-- What does this fix or improve? -->
|
||||
|
||||
### Configurations
|
||||
|
||||
<!-- Attach any Configuration.h, Configuration_adv.h, or platformio.ini files needed to compile/test your Pull Request. -->
|
||||
|
||||
### Related Issues
|
||||
|
||||
<!-- Whether this fixes a bug or fulfills a feature request, please list any related Issues here. -->
|
||||
|
3
.github/workflows/test-builds.yml
vendored
3
.github/workflows/test-builds.yml
vendored
@ -67,6 +67,7 @@ jobs:
|
||||
- BIGTREE_SKR_PRO
|
||||
- BIGTREE_GTR_V1_0
|
||||
- mks_robin
|
||||
- mks_robin_stm32
|
||||
- ARMED
|
||||
- FYSETC_S6
|
||||
- STM32F070RB_malyan
|
||||
@ -77,6 +78,7 @@ jobs:
|
||||
- mks_robin_pro
|
||||
- STM32F103RET6_creality
|
||||
- LERDGEX
|
||||
- mks_robin_nano35
|
||||
|
||||
# Put lengthy tests last
|
||||
|
||||
@ -93,7 +95,6 @@ jobs:
|
||||
#- at90usb1286_dfu
|
||||
#- STM32F103CB_malyan
|
||||
#- mks_robin_mini
|
||||
#- mks_robin_nano
|
||||
|
||||
steps:
|
||||
|
||||
|
5
LICENSE
5
LICENSE
@ -3,7 +3,7 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (c) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Copyright (c) 2007 Free Software Foundation, Inc. <https://www.fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@ -673,5 +673,4 @@ into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
|
@ -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,6 +1178,7 @@
|
||||
*/
|
||||
//#define FILAMENT_RUNOUT_SENSOR
|
||||
#if ENABLED(FILAMENT_RUNOUT_SENSOR)
|
||||
#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.
|
||||
@ -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.
|
||||
|
||||
//
|
||||
@ -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
|
||||
//
|
||||
@ -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
|
||||
|
@ -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,22 +809,28 @@
|
||||
#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.
|
||||
|
||||
// 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.
|
||||
@ -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 }, \
|
||||
|
@ -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
|
||||
// ------------------------
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -59,11 +59,13 @@
|
||||
// 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
|
||||
#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
|
||||
#elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
|
||||
|
@ -20,3 +20,7 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/AVR."
|
||||
#endif
|
||||
|
@ -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)
|
||||
|
@ -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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
|
@ -20,3 +20,7 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/DUE."
|
||||
#endif
|
||||
|
@ -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
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
@ -20,3 +20,7 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/ESP32."
|
||||
#endif
|
||||
|
@ -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
|
||||
|
@ -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() {
|
||||
|
@ -20,3 +20,7 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/LINUX."
|
||||
#endif
|
||||
|
@ -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(); }
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
|
||||
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) {
|
||||
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);
|
||||
setBitOrder(cfg.bitOrder);
|
||||
setDataMode(cfg.dataMode);
|
||||
setDataSize(cfg.dataSize);
|
||||
//setClockDivider(determine_baud_rate(_currentSetting->spi_d, settings.clock));
|
||||
begin();
|
||||
}
|
||||
|
||||
uint8_t SPIClass::transfer(const uint8_t B) { return spiTransfer(B); }
|
||||
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
|
||||
|
@ -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
|
||||
|
@ -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) {};
|
||||
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:
|
||||
/**
|
||||
* @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() {};
|
||||
uint8_t transfer(uint8_t data);
|
||||
|
||||
// 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;
|
||||
|
153
Marlin/src/HAL/LPC1768/tft/tft_spi.cpp
Normal file
153
Marlin/src/HAL/LPC1768/tft/tft_spi.cpp
Normal 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
|
77
Marlin/src/HAL/LPC1768/tft/tft_spi.h
Normal file
77
Marlin/src/HAL/LPC1768/tft/tft_spi.h
Normal 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
|
||||
}
|
||||
};
|
129
Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
Normal file
129
Marlin/src/HAL/LPC1768/tft/xpt2046.cpp
Normal 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
|
80
Marlin/src/HAL/LPC1768/tft/xpt2046.h
Normal file
80
Marlin/src/HAL/LPC1768/tft/xpt2046.h
Normal 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);
|
||||
};
|
@ -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
|
||||
}
|
||||
|
@ -20,3 +20,7 @@
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if HAS_SPI_TFT || HAS_FSMC_TFT
|
||||
#error "Sorry! TFT displays are not available for HAL/SAMD51."
|
||||
#endif
|
||||
|
@ -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);
|
||||
|
@ -76,7 +76,24 @@
|
||||
|
||||
SD_HandleTypeDef hsd; // create SDIO structure
|
||||
|
||||
/*
|
||||
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;
|
||||
|
||||
#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);
|
||||
|
||||
|
||||
#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
|
||||
|
@ -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
|
||||
|
180
Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
Normal file
180
Marlin/src/HAL/STM32/tft/tft_fsmc.cpp
Normal 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
|
160
Marlin/src/HAL/STM32/tft/tft_fsmc.h
Normal file
160
Marlin/src/HAL/STM32/tft/tft_fsmc.h
Normal 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}
|
||||
};
|
212
Marlin/src/HAL/STM32/tft/tft_spi.cpp
Normal file
212
Marlin/src/HAL/STM32/tft/tft_spi.cpp
Normal 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
|
67
Marlin/src/HAL/STM32/tft/tft_spi.h
Normal file
67
Marlin/src/HAL/STM32/tft/tft_spi.h
Normal 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); }
|
||||
};
|
185
Marlin/src/HAL/STM32/tft/xpt2046.cpp
Normal file
185
Marlin/src/HAL/STM32/tft/xpt2046.cpp
Normal 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
|
86
Marlin/src/HAL/STM32/tft/xpt2046.h
Normal file
86
Marlin/src/HAL/STM32/tft/xpt2046.h
Normal 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);
|
||||
};
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
data = LCD->RAM; // dummy read
|
||||
data = LCD->RAM & 0x00FF;
|
||||
|
||||
while (--ReadSize) {
|
||||
data <<= 8;
|
||||
data |= (LCD->RAM & 0x00FF);
|
||||
}
|
||||
return uint32_t(data);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifdef LCD_USE_DMA_FSMC
|
||||
bool TFT_FSMC::isBusy() {
|
||||
return false;
|
||||
}
|
||||
|
||||
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::Abort() {
|
||||
|
||||
}
|
||||
|
||||
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
|
71
Marlin/src/HAL/STM32F1/tft/tft_fsmc.h
Normal file
71
Marlin/src/HAL/STM32F1/tft/tft_fsmc.h
Normal 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;
|
||||
}
|
||||
}
|
||||
};
|
149
Marlin/src/HAL/STM32F1/tft/tft_spi.cpp
Normal file
149
Marlin/src/HAL/STM32F1/tft/tft_spi.cpp
Normal 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
|
72
Marlin/src/HAL/STM32F1/tft/tft_spi.h
Normal file
72
Marlin/src/HAL/STM32F1/tft/tft_spi.h
Normal 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;
|
||||
}
|
||||
}
|
||||
};
|
141
Marlin/src/HAL/STM32F1/tft/xpt2046.cpp
Normal file
141
Marlin/src/HAL/STM32F1/tft/xpt2046.cpp
Normal 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
|
80
Marlin/src/HAL/STM32F1/tft/xpt2046.h
Normal file
80
Marlin/src/HAL/STM32F1/tft/xpt2046.h
Normal 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);
|
||||
};
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 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.");
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
//
|
||||
|
@ -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"
|
||||
|
@ -351,6 +351,13 @@
|
||||
#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)
|
||||
|
||||
@ -377,6 +384,12 @@
|
||||
#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)
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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));
|
||||
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
|
||||
|
||||
#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
|
||||
|
@ -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
|
||||
#endif
|
||||
#if ENABLED(NEOPIXEL_LED)
|
||||
, uint8_t i=NEOPIXEL_BRIGHTNESS
|
||||
#endif
|
||||
#endif
|
||||
#if ENABLED(NEOPIXEL_LED)
|
||||
, 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
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
#if ENABLED(NEOPIXEL2_INSERIES)
|
||||
if (n >= NEOPIXEL_PIXELS) adaneo2.setPixelColor(n - (NEOPIXEL_PIXELS), c);
|
||||
else adaneo1.setPixelColor(n, c);
|
||||
#else
|
||||
adaneo1.setPixelColor(n, c);
|
||||
TERN_(MULTIPLE_NEOPIXEL_TYPES, adaneo2.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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
58
Marlin/src/feature/password/password.cpp
Normal file
58
Marlin/src/feature/password/password.cpp
Normal 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
|
57
Marlin/src/feature/password/password.h
Normal file
57
Marlin/src/feature/password/password.h
Normal 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;
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
}
|
||||
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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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());
|
||||
|
@ -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"));
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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.
|
||||
*
|
||||
|
@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -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.
|
||||
// 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,46 +218,36 @@ 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);
|
||||
|
||||
// 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));
|
||||
|
||||
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_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
|
||||
|
@ -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: {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user