Bump to head

This commit is contained in:
InsanityAutomation
2019-11-21 09:30:10 -05:00
parent f1e187a5dd
commit e81a1c7044
552 changed files with 15116 additions and 14062 deletions
+9 -10
View File
@@ -25,23 +25,27 @@ env:
- TEST_PLATFORM="sanguino_atmega1284p"
- TEST_PLATFORM="sanguino_atmega644p"
# Broken Extended STM32 Environments
#- TEST_PLATFORM="ARMED"
#- TEST_PLATFORM="BIGTREE_BTT002"
#- TEST_PLATFORM="BIGTREE_SKR_PRO"
# Extended STM32 Environments
- TEST_PLATFORM="STM32F103RC_bigtree"
- TEST_PLATFORM="STM32F103RC_bigtree_NOUSB"
- TEST_PLATFORM="STM32F103RC_fysetc"
- TEST_PLATFORM="jgaurora_a5s_a1"
- TEST_PLATFORM="STM32F103VE_longer"
- TEST_PLATFORM="STM32F407VE_black"
- TEST_PLATFORM="BIGTREE_SKR_PRO"
- TEST_PLATFORM="mks_robin"
- TEST_PLATFORM="ARMED"
# STM32 with non-STM framework. both broken for now. they should use HAL_STM32 which is working.
#- TEST_PLATFORM="STM32F4"
#- TEST_PLATFORM="STM32F7"
# Put lengthy tests last
- TEST_PLATFORM="LPC1768"
- TEST_PLATFORM="LPC1769"
# Non-working environment tests
#- TEST_PLATFORM="BIGTREE_BTT002" this board isn't released yet. we need pinout to be sure about what we do
#- TEST_PLATFORM="at90usb1286_cdc"
#- TEST_PLATFORM="at90usb1286_dfu"
#- TEST_PLATFORM="STM32F103CB_malyan"
@@ -49,11 +53,6 @@ env:
#- TEST_PLATFORM="mks_robin_mini"
#- TEST_PLATFORM="mks_robin_nano"
#- TEST_PLATFORM="SAMD51_grandcentral_m4"
#- TEST_PLATFORM="STM32F103RC_bigtree"
#- TEST_PLATFORM="STM32F103RC_bigtree_USB"
#- TEST_PLATFORM="STM32F103RC_fysetc"
#- TEST_PLATFORM="STM32F4"
#- TEST_PLATFORM="STM32F7"
before_install:
#
+2 -1
View File
@@ -1317,7 +1317,8 @@
//#define BABYSTEP_WITHOUT_HOMING
#define BABYSTEP_XY // Also enable X/Y Babystepping. Not supported on DELTA!
#define BABYSTEP_INVERT_Z false // Change if Z babysteps should go the other way
#define BABYSTEP_MULTIPLICATOR 20 // Babysteps are very small. Increase for faster motion.
#define BABYSTEP_MULTIPLICATOR_Z 20 // Babysteps are very small. Increase for faster motion.
#define BABYSTEP_MULTIPLICATOR_XY 1
#define DOUBLECLICK_FOR_Z_BABYSTEPPING // Double-click on the Status Screen for Z Babystepping.
#if ENABLED(DOUBLECLICK_FOR_Z_BABYSTEPPING)
+2 -2
View File
@@ -28,7 +28,7 @@
/**
* Marlin release version identifier
*/
#define SHORT_BUILD_VERSION "2.0.x_TR20"
#define SHORT_BUILD_VERSION "2.0.x_TR21"
/**
* Verbose version identifier which should contain a reference to the location
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
#define STRING_DISTRIBUTION_DATE "2019-10-26"
#define STRING_DISTRIBUTION_DATE "2019-11-19"
/**
* Defines a generic printer name to be output to the LCD after booting Marlin.
+2
View File
@@ -25,6 +25,8 @@
#include HAL_PATH(.,HAL.h)
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
inline void watchdog_refresh() {
#if ENABLED(USE_WATCHDOG)
HAL_watchdog_refresh();
+3 -2
View File
@@ -25,7 +25,7 @@
#include "math.h"
#ifdef USBCON
#include "HardwareSerial.h"
#include <HardwareSerial.h>
#else
#define HardwareSerial_h // Hack to prevent HardwareSerial.h header inclusion
#include "MarlinSerial.h"
@@ -41,7 +41,7 @@
#ifndef pgm_read_ptr
// Compatibility for avr-libc 1.8.0-4.1 included with Ubuntu for
// Windows Subsystem for Linux on Windows 10 as of 10/18/2019
#define pgm_read_ptr_far(address_long) (void*)__ELPM_word((uint32_t)(address_long))
#define pgm_read_ptr_far(address_long) (void*)__ELPM_word((uint32_t)(address_long))
#define pgm_read_ptr_near(address_short) (void*)__LPM_word((uint16_t)(address_short))
#define pgm_read_ptr(address_short) pgm_read_ptr_near(address_short)
#endif
@@ -365,6 +365,7 @@ inline void HAL_adc_init() {
#define HAL_START_ADC(pin) ADCSRB = 0; SET_ADMUX_ADCSRA(pin)
#endif
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() ADC
#define HAL_ADC_READY() !TEST(ADCSRA, ADSC)
+51 -35
View File
@@ -46,39 +46,55 @@ void endstop_ISR() { endstops.update(); }
/**
* Patch for pins_arduino.h (...\Arduino\hardware\arduino\avr\variants\mega\pins_arduino.h)
*
* These macros for the Arduino MEGA do not include the two connected pins on Port J (D13, D14).
* These macros for the Arduino MEGA do not include the two connected pins on Port J (D14, D15).
* So we extend them here because these are the normal pins for Y_MIN and Y_MAX on RAMPS.
* There are more PCI-enabled processor pins on Port J, but they are not connected to Arduino MEGA.
*/
#if defined(ARDUINO_AVR_MEGA2560) || defined(ARDUINO_AVR_MEGA)
#define digitalPinHasPCICR(p) (WITHIN(p, 10, 15) || WITHIN(p, 50, 53) || WITHIN(p, 62, 69))
#undef digitalPinToPCICR
#define digitalPinToPCICR(p) ( WITHIN(p, 10, 15) || \
WITHIN(p, 50, 53) || \
WITHIN(p, 62, 69) ? &PCICR : nullptr )
#define digitalPinToPCICR(p) (digitalPinHasPCICR(p) ? (&PCICR) : nullptr)
#undef digitalPinToPCICRbit
#define digitalPinToPCICRbit(p) ( WITHIN(p, 10, 13) || WITHIN(p, 50, 53) ? 0 : \
WITHIN(p, 14, 15) ? 1 : \
WITHIN(p, 62, 69) ? 2 : \
0 )
#define digitalPinToPCICRbit(p) (WITHIN(p, 10, 13) || WITHIN(p, 50, 53) ? 0 : \
WITHIN(p, 14, 15) ? 1 : \
WITHIN(p, 62, 69) ? 2 : \
0)
#undef digitalPinToPCMSK
#define digitalPinToPCMSK(p) ( WITHIN(p, 10, 13) || WITHIN(p, 50, 53) ? &PCMSK0 : \
WITHIN(p, 14, 15) ? &PCMSK1 : \
WITHIN(p, 62, 69) ? &PCMSK2 : \
nullptr )
#define digitalPinToPCMSK(p) (WITHIN(p, 10, 13) || WITHIN(p, 50, 53) ? (&PCMSK0) : \
WITHIN(p, 14, 15) ? (&PCMSK1) : \
WITHIN(p, 62, 69) ? (&PCMSK2) : \
nullptr)
#undef digitalPinToPCMSKbit
#define digitalPinToPCMSKbit(p) ( WITHIN(p, 10, 13) ? ((p) - 6) : \
(p) == 14 || (p) == 51 ? 2 : \
(p) == 15 || (p) == 52 ? 1 : \
(p) == 50 ? 3 : \
(p) == 53 ? 0 : \
WITHIN(p, 62, 69) ? ((p) - 62) : \
0 )
#define digitalPinToPCMSKbit(p) (WITHIN(p, 10, 13) ? ((p) - 6) : \
(p) == 14 || (p) == 51 ? 2 : \
(p) == 15 || (p) == 52 ? 1 : \
(p) == 50 ? 3 : \
(p) == 53 ? 0 : \
WITHIN(p, 62, 69) ? ((p) - 62) : \
0)
#elif defined(__AVR_ATmega164A__) || defined(__AVR_ATmega164P__) || defined(__AVR_ATmega324A__) || \
defined(__AVR_ATmega324P__) || defined(__AVR_ATmega324PA__) || defined(__AVR_ATmega324PB__) || \
defined(__AVR_ATmega644A__) || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284__) || \
defined(__AVR_ATmega1284P__)
#define digitalPinHasPCICR(p) WITHIN(p, 0, NUM_DIGITAL_PINS)
#else
#error "Unsupported AVR variant!"
#endif
// Install Pin change interrupt for a pin. Can be called multiple times.
void pciSetup(const int8_t pin) {
if (digitalPinToPCMSK(pin) != nullptr) {
if (digitalPinHasPCICR(pin)) {
SBI(*digitalPinToPCMSK(pin), digitalPinToPCMSKbit(pin)); // enable pin
SBI(PCIFR, digitalPinToPCICRbit(pin)); // clear any outstanding interrupt
SBI(PCICR, digitalPinToPCICRbit(pin)); // enable interrupt for the group
@@ -108,7 +124,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X_MAX_PIN);
#else
static_assert(digitalPinToPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(X_MAX_PIN), "X_MAX_PIN is not interrupt-capable");
pciSetup(X_MAX_PIN);
#endif
#endif
@@ -116,7 +132,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X_MIN_PIN);
#else
static_assert(digitalPinToPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(X_MIN_PIN), "X_MIN_PIN is not interrupt-capable");
pciSetup(X_MIN_PIN);
#endif
#endif
@@ -124,7 +140,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y_MAX_PIN);
#else
static_assert(digitalPinToPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Y_MAX_PIN), "Y_MAX_PIN is not interrupt-capable");
pciSetup(Y_MAX_PIN);
#endif
#endif
@@ -132,7 +148,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y_MIN_PIN);
#else
static_assert(digitalPinToPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Y_MIN_PIN), "Y_MIN_PIN is not interrupt-capable");
pciSetup(Y_MIN_PIN);
#endif
#endif
@@ -140,7 +156,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MAX_PIN);
#else
static_assert(digitalPinToPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Z_MAX_PIN), "Z_MAX_PIN is not interrupt-capable");
pciSetup(Z_MAX_PIN);
#endif
#endif
@@ -148,7 +164,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MIN_PIN);
#else
static_assert(digitalPinToPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Z_MIN_PIN), "Z_MIN_PIN is not interrupt-capable");
pciSetup(Z_MIN_PIN);
#endif
#endif
@@ -156,7 +172,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MAX_PIN);
#else
static_assert(digitalPinToPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(X2_MAX_PIN), "X2_MAX_PIN is not interrupt-capable");
pciSetup(X2_MAX_PIN);
#endif
#endif
@@ -164,7 +180,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(X2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(X2_MIN_PIN);
#else
static_assert(digitalPinToPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(X2_MIN_PIN), "X2_MIN_PIN is not interrupt-capable");
pciSetup(X2_MIN_PIN);
#endif
#endif
@@ -172,7 +188,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y2_MAX_PIN);
#else
static_assert(digitalPinToPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Y2_MAX_PIN), "Y2_MAX_PIN is not interrupt-capable");
pciSetup(Y2_MAX_PIN);
#endif
#endif
@@ -180,7 +196,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Y2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Y2_MIN_PIN);
#else
static_assert(digitalPinToPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Y2_MIN_PIN), "Y2_MIN_PIN is not interrupt-capable");
pciSetup(Y2_MIN_PIN);
#endif
#endif
@@ -188,7 +204,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z2_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z2_MAX_PIN);
#else
static_assert(digitalPinToPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Z2_MAX_PIN), "Z2_MAX_PIN is not interrupt-capable");
pciSetup(Z2_MAX_PIN);
#endif
#endif
@@ -196,7 +212,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z2_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z2_MIN_PIN);
#else
static_assert(digitalPinToPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Z2_MIN_PIN), "Z2_MIN_PIN is not interrupt-capable");
pciSetup(Z2_MIN_PIN);
#endif
#endif
@@ -204,7 +220,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z3_MAX_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z3_MAX_PIN);
#else
static_assert(digitalPinToPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Z3_MAX_PIN), "Z3_MAX_PIN is not interrupt-capable");
pciSetup(Z3_MAX_PIN);
#endif
#endif
@@ -212,7 +228,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z3_MIN_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z3_MIN_PIN);
#else
static_assert(digitalPinToPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Z3_MIN_PIN), "Z3_MIN_PIN is not interrupt-capable");
pciSetup(Z3_MIN_PIN);
#endif
#endif
@@ -220,7 +236,7 @@ void setup_endstop_interrupts() {
#if (digitalPinToInterrupt(Z_MIN_PROBE_PIN) != NOT_AN_INTERRUPT)
_ATTACH(Z_MIN_PROBE_PIN);
#else
static_assert(digitalPinToPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable");
static_assert(digitalPinHasPCICR(Z_MIN_PROBE_PIN), "Z_MIN_PROBE_PIN is not interrupt-capable");
pciSetup(Z_MIN_PROBE_PIN);
#endif
#endif
+1
View File
@@ -133,6 +133,7 @@ extern uint16_t HAL_adc_result; // result of last ADC conversion
inline void HAL_adc_init() {}//todo
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
@@ -19,6 +19,9 @@ void sd_mmc_spi_mem_init() {
}
Ctrl_status sd_mmc_spi_test_unit_ready() {
#ifdef DISABLE_DUE_SD_MMC
return CTRL_NO_PRESENT;
#endif
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
return CTRL_NO_PRESENT;
return CTRL_GOOD;
@@ -55,6 +58,9 @@ uint8_t sector_buf[SD_MMC_BLOCK_SIZE];
// #define DEBUG_MMC
Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
#ifdef DISABLE_DUE_SD_MMC
return CTRL_NO_PRESENT;
#endif
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
return CTRL_NO_PRESENT;
@@ -92,6 +98,9 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
}
Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
#ifdef DISABLE_DUE_SD_MMC
return CTRL_NO_PRESENT;
#endif
if (!IS_SD_INSERTED() || IS_SD_PRINTING() || IS_SD_FILE_OPEN() || !card.isMounted())
return CTRL_NO_PRESENT;
+3 -2
View File
@@ -45,11 +45,12 @@
#ifdef ARDUINO_ARCH_SAM
#include "conf_usb.h"
#include "udc.h"
#include <Arduino.h>
#include <Reset.h>
#include "conf_usb.h"
#include "udc.h"
#if ENABLED(SDSUPPORT)
static volatile bool main_b_msc_enable = false;
#endif
+1
View File
@@ -111,6 +111,7 @@ void eeprom_update_block (const void *__src, void *__dst, size_t __n);
void HAL_adc_init();
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
+1 -1
View File
@@ -23,7 +23,7 @@
#include "../../inc/MarlinConfig.h"
#include "Stream.h"
#include <Stream.h>
#ifndef RX_BUFFER_SIZE
#define RX_BUFFER_SIZE 128
+4 -4
View File
@@ -26,10 +26,10 @@
#include "i2s.h"
#include "../shared/Marduino.h"
#include "driver/periph_ctrl.h"
#include "rom/lldesc.h"
#include "soc/i2s_struct.h"
#include "freertos/queue.h"
#include <driver/periph_ctrl.h>
#include <rom/lldesc.h>
#include <soc/i2s_struct.h>
#include <freertos/queue.h>
#include "../../module/stepper.h"
#define DMA_BUF_COUNT 8 // number of DMA buffers to store data
+1 -1
View File
@@ -27,7 +27,7 @@
#include <ESPmDNS.h>
#include <WiFiUdp.h>
#include <ArduinoOTA.h>
#include "driver/timer.h"
#include <driver/timer.h>
void OTA_init() {
ArduinoOTA
+4 -4
View File
@@ -23,10 +23,10 @@
#ifdef ARDUINO_ARCH_ESP32
#include <stdio.h>
#include "esp_types.h"
#include "soc/timer_group_struct.h"
#include "driver/periph_ctrl.h"
#include "driver/timer.h"
#include <esp_types.h>
#include <soc/timer_group_struct.h>
#include <driver/periph_ctrl.h>
#include <driver/timer.h>
#include "HAL.h"
+3 -3
View File
@@ -22,7 +22,7 @@
#pragma once
#include <stdint.h>
#include "driver/timer.h"
#include <driver/timer.h>
// Includes needed to get I2S_STEPPER_STREAM. Note that pins.h
// is included in case this header is being included early.
@@ -51,8 +51,8 @@ typedef uint64_t hal_timer_t;
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs // wrong would be 0.25
#else
#define STEPPER_TIMER_PRESCALE 40
#define STEPPER_TIMER_RATE (HAL_TIMER_RATE / STEPPER_TIMER_PRESCALE) // frequency of stepper timer, 2MHz
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#define STEPPER_TIMER_RATE ((HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE)) // frequency of stepper timer, 2MHz
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
#endif
#define STEP_TIMER_MIN_INTERVAL 8 // minimum time in µs between stepper interrupts
+1
View File
@@ -89,6 +89,7 @@ int freeMemory();
// ADC
#define HAL_ANALOG_SELECT(pin) HAL_adc_enable_channel(pin)
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_get_result()
#define HAL_ADC_READY() true
+3 -1
View File
@@ -30,6 +30,8 @@
#include "watchdog.h"
#endif
uint32_t HAL_adc_reading = 0;
// U8glib required functions
extern "C" void u8g_xMicroDelay(uint16_t val) {
DELAY_US(val);
@@ -61,7 +63,7 @@ int freeMemory() {
// return dval if not found or not a valid pin.
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval) {
const uint16_t val = (uint16_t)parser.intval(code, -1), port = val / 100, pin = val % 100;
const int16_t ind = (port < ((NUM_DIGITAL_PINS) >> 5) && pin < 32) ? GET_PIN_MAP_INDEX((port << 5) | pin) : -2;
const int16_t ind = (port < ((NUM_DIGITAL_PINS) >> 5) && pin < 32) ? ((port << 5) | pin) : -2;
return ind > -1 ? ind : dval;
}
+35 -4
View File
@@ -131,12 +131,43 @@ int freeMemory();
// K = 6, 565 samples, 500Hz sample rate, 1.13s convergence on full range step
// Memory usage per ADC channel (bytes): 4 (32 Bytes for 8 channels)
#define HAL_ADC_RESOLUTION 12 // 15 bit maximum, raw temperature is stored as int16_t
#define HAL_ADC_FILTERED // Disable oversampling done in Marlin as ADC values already filtered in HAL
using FilteredADC = LPC176x::ADC<ADC_LOWPASS_K_VALUE, ADC_MEDIAN_FILTER_SIZE>;
#define HAL_adc_init() FilteredADC::init()
extern uint32_t HAL_adc_reading;
[[gnu::always_inline]] inline void HAL_start_adc(const pin_t pin) {
HAL_adc_reading = FilteredADC::read(pin) >> (16 - HAL_ADC_RESOLUTION); // returns 16bit value, reduce to required bits
}
[[gnu::always_inline]] inline uint16_t HAL_read_adc() {
return HAL_adc_reading;
}
#define HAL_adc_init()
#define HAL_ANALOG_SELECT(pin) FilteredADC::enable_channel(pin)
#define HAL_START_ADC(pin) FilteredADC::start_conversion(pin)
#define HAL_READ_ADC() FilteredADC::get_result()
#define HAL_ADC_READY() FilteredADC::finished_conversion()
#define HAL_START_ADC(pin) HAL_start_adc(pin)
#define HAL_READ_ADC() HAL_read_adc()
#define HAL_ADC_READY() (true)
// Test whether the pin is valid
constexpr bool VALID_PIN(const pin_t pin) {
return LPC176x::pin_is_valid(pin);
}
// Get the analog index for a digital pin
constexpr int8_t DIGITAL_PIN_TO_ANALOG_PIN(const pin_t pin) {
return (LPC176x::pin_is_valid(pin) && LPC176x::pin_has_adc(pin)) ? pin : -1;
}
// Return the index of a pin number
constexpr int16_t GET_PIN_MAP_INDEX(const pin_t pin) {
return LPC176x::pin_index(pin);
}
// Get the pin number at the given index
constexpr pin_t GET_PIN_MAP_PIN(const int16_t index) {
return LPC176x::pin_index(index);
}
// Parse a G-code word into a pin index
int16_t PARSED_PIN_INDEX(const char code, const int16_t dval);
+7 -7
View File
@@ -56,7 +56,7 @@
// ------------------------
#if ENABLED(LPC_SOFTWARE_SPI)
#include "SoftwareSPI.h"
#include <SoftwareSPI.h>
// Software SPI
@@ -125,18 +125,18 @@
PinCfg.Funcnum = 2;
PinCfg.OpenDrain = 0;
PinCfg.Pinmode = 0;
PinCfg.Pinnum = LPC1768_PIN_PIN(SCK_PIN);
PinCfg.Portnum = LPC1768_PIN_PORT(SCK_PIN);
PinCfg.Pinnum = LPC176x::pin_bit(SCK_PIN);
PinCfg.Portnum = LPC176x::pin_port(SCK_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_OUTPUT(SCK_PIN);
PinCfg.Pinnum = LPC1768_PIN_PIN(MISO_PIN);
PinCfg.Portnum = LPC1768_PIN_PORT(MISO_PIN);
PinCfg.Pinnum = LPC176x::pin_bit(MISO_PIN);
PinCfg.Portnum = LPC176x::pin_port(MISO_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_INPUT(MISO_PIN);
PinCfg.Pinnum = LPC1768_PIN_PIN(MOSI_PIN);
PinCfg.Portnum = LPC1768_PIN_PORT(MOSI_PIN);
PinCfg.Pinnum = LPC176x::pin_bit(MOSI_PIN);
PinCfg.Portnum = LPC176x::pin_port(MOSI_PIN);
PINSEL_ConfigPin(&PinCfg);
SET_OUTPUT(MOSI_PIN);
// divide PCLK by 2 for SSP0
@@ -42,6 +42,8 @@ void endstop_ISR() { endstops.update(); }
void setup_endstop_interrupts() {
#define _ATTACH(P) attachInterrupt(digitalPinToInterrupt(P), endstop_ISR, CHANGE)
#define LPC1768_PIN_INTERRUPT_M(pin) ((pin >> 0x5 & 0x7) == 0 || (pin >> 0x5 & 0x7) == 2)
#if HAS_X_MAX
#if !LPC1768_PIN_INTERRUPT_M(X_MAX_PIN)
#error "X_MAX_PIN is not INTERRUPT-capable."
+2 -2
View File
@@ -29,11 +29,11 @@
#include <pwm.h>
void set_pwm_frequency(const pin_t pin, int f_desired) {
pwm_set_frequency(pin, f_desired);
LPC176x::pwm_set_frequency(pin, f_desired);
}
void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size/*=255*/, const bool invert/*=false*/) {
pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size);
LPC176x::pwm_write_ratio(pin, invert ? 1.0f - (float)v / v_size : (float)v / v_size);
}
#endif // FAST_PWM_FAN || SPINDLE_LASER_PWM
+10 -10
View File
@@ -37,19 +37,19 @@
#define PWM_PIN(P) true // all pins are PWM capable
#define LPC_PIN(pin) gpio_pin(pin)
#define LPC_GPIO(port) gpio_port(port)
#define LPC_PIN(pin) LPC176x::gpio_pin(pin)
#define LPC_GPIO(port) LPC176x::gpio_port(port)
#define SET_DIR_INPUT(IO) gpio_set_input(IO)
#define SET_DIR_OUTPUT(IO) gpio_set_output(IO)
#define SET_DIR_INPUT(IO) LPC176x::gpio_set_input(IO)
#define SET_DIR_OUTPUT(IO) LPC176x::gpio_set_output(IO)
#define SET_MODE(IO, mode) pinMode(IO, mode)
#define WRITE_PIN_SET(IO) gpio_set(IO)
#define WRITE_PIN_CLR(IO) gpio_clear(IO)
#define WRITE_PIN_SET(IO) LPC176x::gpio_set(IO)
#define WRITE_PIN_CLR(IO) LPC176x::gpio_clear(IO)
#define READ_PIN(IO) gpio_get(IO)
#define WRITE_PIN(IO,V) gpio_set(IO, V)
#define READ_PIN(IO) LPC176x::gpio_get(IO)
#define WRITE_PIN(IO,V) LPC176x::gpio_set(IO, V)
/**
* Magic I/O routines
@@ -81,10 +81,10 @@
#define _PULLDOWN(IO,V) pinMode(IO, (V) ? INPUT_PULLDOWN : INPUT)
/// check if pin is an input
#define _IS_INPUT(IO) (!gpio_get_dir(IO))
#define _IS_INPUT(IO) (!LPC176x::gpio_get_dir(IO))
/// check if pin is an output
#define _IS_OUTPUT(IO) (gpio_get_dir(IO))
#define _IS_OUTPUT(IO) (LPC176x::gpio_get_dir(IO))
/// Read a pin wrapper
#define READ(IO) _READ(IO)
@@ -21,6 +21,13 @@
*/
#pragma once
#if PIO_PLATFORM_VERSION < 1001
#error "nxplpc-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries. You may need to remove the platform and let it reinstall automatically."
#endif
#if PIO_FRAMEWORK_VERSION < 2002
#error "framework-arduino-lpc176x package is out of date, Please update the PlatformIO platforms, frameworks and libraries."
#endif
/**
* Test LPC176x-specific configuration values for errors at compile-time.
*/
@@ -46,7 +46,7 @@
#if ENABLED(FLASH_EEPROM_EMULATION)
extern "C" {
#include "lpc17xx_iap.h"
#include <lpc17xx_iap.h>
}
#define SECTOR_START(sector) ((sector < 16) ? (sector * 0x1000) : ((sector - 14) * 0x8000))
+7 -38
View File
@@ -33,52 +33,21 @@
#define PRINT_PORT(p)
#define GET_ARRAY_PIN(p) pin_array[p].pin
#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%d.%02d"), LPC1768_PIN_PORT(p), LPC1768_PIN_PIN(p)); SERIAL_ECHO(buffer); }while(0)
#define PRINT_PIN(p) do{ sprintf_P(buffer, PSTR("%d.%02d"), LPC176x::pin_port(p), LPC176x::pin_bit(p)); SERIAL_ECHO(buffer); }while(0)
#define MULTI_NAME_PAD 16 // space needed to be pretty if not first name assigned to a pin
// pins that will cause hang/reset/disconnect in M43 Toggle and Watch utilities
// uses pin index
#ifndef M43_NEVER_TOUCH
#define M43_NEVER_TOUCH(Q) ((Q) == 29 || (Q) == 30 || (Q) == 73) // USB pins
#define M43_NEVER_TOUCH(Q) ((Q) == P0_29 || (Q) == P0_30 || (Q) == P2_09) // USB pins
#endif
// active ADC function/mode/code values for PINSEL registers
constexpr int8_t ADC_pin_mode(pin_t pin) {
return (LPC1768_PIN_PORT(pin) == 0 && LPC1768_PIN_PIN(pin) == 2 ? 2 :
LPC1768_PIN_PORT(pin) == 0 && LPC1768_PIN_PIN(pin) == 3 ? 2 :
LPC1768_PIN_PORT(pin) == 0 && LPC1768_PIN_PIN(pin) == 23 ? 1 :
LPC1768_PIN_PORT(pin) == 0 && LPC1768_PIN_PIN(pin) == 24 ? 1 :
LPC1768_PIN_PORT(pin) == 0 && LPC1768_PIN_PIN(pin) == 25 ? 1 :
LPC1768_PIN_PORT(pin) == 0 && LPC1768_PIN_PIN(pin) == 26 ? 1 :
LPC1768_PIN_PORT(pin) == 1 && LPC1768_PIN_PIN(pin) == 30 ? 3 :
LPC1768_PIN_PORT(pin) == 1 && LPC1768_PIN_PIN(pin) == 31 ? 3 : -1);
}
int8_t get_pin_mode(pin_t pin) {
if (!VALID_PIN(pin)) return -1;
uint8_t pin_port = LPC1768_PIN_PORT(pin);
uint8_t pin_port_pin = LPC1768_PIN_PIN(pin);
//get appropriate PINSEL register
volatile uint32_t * pinsel_reg = (pin_port == 0 && pin_port_pin <= 15) ? &LPC_PINCON->PINSEL0 :
(pin_port == 0) ? &LPC_PINCON->PINSEL1 :
(pin_port == 1 && pin_port_pin <= 15) ? &LPC_PINCON->PINSEL2 :
pin_port == 1 ? &LPC_PINCON->PINSEL3 :
pin_port == 2 ? &LPC_PINCON->PINSEL4 :
pin_port == 3 ? &LPC_PINCON->PINSEL7 : &LPC_PINCON->PINSEL9;
uint8_t pinsel_start_bit = pin_port_pin > 15 ? 2 * (pin_port_pin - 16) : 2 * pin_port_pin;
int8_t pin_mode = (int8_t) ((*pinsel_reg >> pinsel_start_bit) & 0x3);
return pin_mode;
}
bool GET_PINMODE(pin_t pin) {
int8_t pin_mode = get_pin_mode(pin);
if (pin_mode == -1 || pin_mode == ADC_pin_mode(pin)) // found an invalid pin or active analog pin
bool GET_PINMODE(const pin_t pin) {
if (!LPC176x::pin_is_valid(pin) || LPC176x::pin_adc_enabled(pin)) // found an invalid pin or active analog pin
return false;
uint32_t * FIO_reg[5] PROGMEM = {(uint32_t*) 0x2009C000,(uint32_t*) 0x2009C020,(uint32_t*) 0x2009C040,(uint32_t*) 0x2009C060,(uint32_t*) 0x2009C080};
return ((*FIO_reg[LPC1768_PIN_PORT(pin)] >> LPC1768_PIN_PIN(pin) & 1) != 0); //input/output state
return LPC176x::gpio_direction(pin);
}
bool GET_ARRAY_IS_DIGITAL(pin_t pin) {
return (!IS_ANALOG(pin) || get_pin_mode(pin) != ADC_pin_mode(pin));
bool GET_ARRAY_IS_DIGITAL(const pin_t pin) {
return (!LPC176x::pin_has_adc(pin) || !LPC176x::pin_adc_enabled(pin));
}
+1 -1
View File
@@ -59,7 +59,7 @@
typedef uint32_t hal_timer_t;
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF
#define HAL_TIMER_RATE ((SystemCoreClock) / 4) // frequency of timers peripherals
#define HAL_TIMER_RATE ((F_CPU) / 4) // frequency of timers peripherals
#define STEP_TIMER_NUM 0 // Timer Index for Stepper
#define TEMP_TIMER_NUM 1 // Timer Index for Temperature
@@ -25,6 +25,8 @@
#ifdef TARGET_LPC1768
extern int millis();
#ifdef __cplusplus
extern "C" {
#endif
@@ -35,6 +37,7 @@
#include "../../../core/millis_t.h"
//////////////////////////////////////////////////////////////////////////////////////
// These two routines are exact copies of the lpc17xx_i2c.c routines. Couldn't link to
@@ -151,14 +154,13 @@ void u8g_i2c_init(uint8_t clock_option) {
u8g_i2c_start(0); // send slave address and write bit
}
volatile extern millis_t _millis;
uint8_t u8g_i2c_send_byte(uint8_t data) {
#define I2C_TIMEOUT 3
LPC_I2C1->I2DAT = data & I2C_I2DAT_BITMASK; // transmit data
LPC_I2C1->I2CONSET = I2C_I2CONSET_AA;
LPC_I2C1->I2CONCLR = I2C_I2CONCLR_SIC;
const millis_t timeout = _millis + I2C_TIMEOUT;
while ((I2C_status != I2C_I2STAT_M_TX_DAT_ACK) && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK) && PENDING(_millis, timeout)); // wait for xmit to finish
const millis_t timeout = millis() + I2C_TIMEOUT;
while ((I2C_status != I2C_I2STAT_M_TX_DAT_ACK) && (I2C_status != I2C_I2STAT_M_TX_DAT_NACK) && PENDING(millis(), timeout)); // wait for xmit to finish
// had hangs with SH1106 so added time out - have seen temporary screen corruption when this happens
return 1;
}
@@ -60,7 +60,7 @@
#if ENABLED(U8GLIB_ST7920)
#include <U8glib.h>
#include "SoftwareSPI.h"
#include <SoftwareSPI.h>
#include "../../shared/Delay.h"
#undef SPI_SPEED
@@ -59,7 +59,7 @@
#if HAS_GRAPHICAL_LCD && DISABLED(U8GLIB_ST7920)
#include "SoftwareSPI.h"
#include <SoftwareSPI.h>
#undef SPI_SPEED
#define SPI_SPEED 2 // About 2 MHz
@@ -75,25 +75,25 @@ uint8_t swSpiTransfer_mode_0(uint8_t b, const uint8_t spi_speed, const pin_t sck
for (uint8_t i = 0; i < 8; i++) {
if (spi_speed == 0) {
gpio_set(mosi_pin, !!(b & 0x80));
gpio_set(sck_pin, HIGH);
LPC176x::gpio_set(mosi_pin, !!(b & 0x80));
LPC176x::gpio_set(sck_pin, HIGH);
b <<= 1;
if (miso_pin >= 0 && gpio_get(miso_pin)) b |= 1;
gpio_set(sck_pin, LOW);
if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
LPC176x::gpio_set(sck_pin, LOW);
}
else {
const uint8_t state = (b & 0x80) ? HIGH : LOW;
for (uint8_t j = 0; j < spi_speed; j++)
gpio_set(mosi_pin, state);
LPC176x::gpio_set(mosi_pin, state);
for (uint8_t j = 0; j < spi_speed + (miso_pin >= 0 ? 0 : 1); j++)
gpio_set(sck_pin, HIGH);
LPC176x::gpio_set(sck_pin, HIGH);
b <<= 1;
if (miso_pin >= 0 && gpio_get(miso_pin)) b |= 1;
if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
for (uint8_t j = 0; j < spi_speed; j++)
gpio_set(sck_pin, LOW);
LPC176x::gpio_set(sck_pin, LOW);
}
}
@@ -105,23 +105,23 @@ uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, const pin_t sck
for (uint8_t i = 0; i < 8; i++) {
const uint8_t state = (b & 0x80) ? HIGH : LOW;
if (spi_speed == 0) {
gpio_set(sck_pin, LOW);
gpio_set(mosi_pin, state);
gpio_set(mosi_pin, state); // need some setup time
gpio_set(sck_pin, HIGH);
LPC176x::gpio_set(sck_pin, LOW);
LPC176x::gpio_set(mosi_pin, state);
LPC176x::gpio_set(mosi_pin, state); // need some setup time
LPC176x::gpio_set(sck_pin, HIGH);
}
else {
for (uint8_t j = 0; j < spi_speed + (miso_pin >= 0 ? 0 : 1); j++)
gpio_set(sck_pin, LOW);
LPC176x::gpio_set(sck_pin, LOW);
for (uint8_t j = 0; j < spi_speed; j++)
gpio_set(mosi_pin, state);
LPC176x::gpio_set(mosi_pin, state);
for (uint8_t j = 0; j < spi_speed; j++)
gpio_set(sck_pin, HIGH);
LPC176x::gpio_set(sck_pin, HIGH);
}
b <<= 1;
if (miso_pin >= 0 && gpio_get(miso_pin)) b |= 1;
if (miso_pin >= 0 && LPC176x::gpio_get(miso_pin)) b |= 1;
}
return b;
@@ -130,7 +130,7 @@ uint8_t swSpiTransfer_mode_3(uint8_t b, const uint8_t spi_speed, const pin_t sck
static uint8_t SPI_speed = 0;
static void u8g_sw_spi_HAL_LPC1768_shift_out(uint8_t dataPin, uint8_t clockPin, uint8_t val) {
#if ENABLED(FYSETC_MINI_12864)
#if EITHER(FYSETC_MINI_12864, MKS_MINI_12864)
swSpiTransfer_mode_3(val, SPI_speed, clockPin, -1, dataPin);
#else
swSpiTransfer_mode_0(val, SPI_speed, clockPin, -1, dataPin);
@@ -158,10 +158,10 @@ uint8_t u8g_com_HAL_LPC1768_sw_spi_fn(u8g_t *u8g, uint8_t msg, uint8_t arg_val,
break;
case U8G_COM_MSG_CHIP_SELECT:
#if ENABLED(FYSETC_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0
if (arg_val) { // SCK idle state needs to be set to the proper idle state before
// the next chip select goes active
u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active
#if EITHER(FYSETC_MINI_12864, MKS_MINI_12864) // LCD SPI is running mode 3 while SD card is running mode 0
if (arg_val) { // SCK idle state needs to be set to the proper idle state before
// the next chip select goes active
u8g_SetPILevel(u8g, U8G_PI_SCK, 1); // Set SCK to mode 3 idle state before CS goes active
u8g_SetPILevel(u8g, U8G_PI_CS, LOW);
}
else {
+1 -1
View File
@@ -26,7 +26,7 @@
#if ENABLED(USE_WATCHDOG)
#include "lpc17xx_wdt.h"
#include <lpc17xx_wdt.h>
#include "watchdog.h"
void watchdog_init() {
+5 -3
View File
@@ -22,8 +22,8 @@
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#include "Adafruit_ZeroDMA.h"
#include "wiring_private.h"
#include <Adafruit_ZeroDMA.h>
#include <wiring_private.h>
// ------------------------
// Local defines
@@ -442,9 +442,11 @@ void HAL_adc_init() {
// Preloaded data (fixed for all ADC instances hence not loaded by DMA)
adc->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_AREFA_Val; // VRefA pin
SYNC(adc->SYNCBUSY.bit.REFCTRL);
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_10BIT_Val;
adc->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
SYNC(adc->SYNCBUSY.bit.CTRLB);
adc->SAMPCTRL.bit.SAMPLEN = (6 - 1); // Sampling clocks
adc->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_16 | ADC_AVGCTRL_ADJRES(4); // 16 Accumulated conversions and shift 4 to get oversampled 12 bits result
SYNC(adc->SYNCBUSY.bit.AVGCTRL);
// Registers loaded by DMA
adc->DSEQCTRL.bit.INPUTCTRL = true;
+2
View File
@@ -109,6 +109,8 @@ extern uint16_t HAL_adc_result; // result of last ADC conversion
void HAL_adc_init();
#define HAL_ADC_FILTERED // Disable oversampling done in Marlin as ADC values already filtered in HAL
#define HAL_ADC_RESOLUTION 12
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
+1 -1
View File
@@ -99,7 +99,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
SYNC(tc->COUNT32.SYNCBUSY.bit.CTRLB);
// Set compare value
tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = HAL_TIMER_RATE / frequency;
tc->COUNT32.COUNT.reg = tc->COUNT32.CC[0].reg = (HAL_TIMER_RATE) / frequency;
// And start timer
tc->COUNT32.CTRLA.bit.ENABLE = true;
+16 -2
View File
@@ -28,11 +28,21 @@
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
#if (__cplusplus == 201703L) && defined(__has_include)
#define HAS_SWSERIAL __has_include(<SoftwareSerial.h>)
#else
#define HAS_SWSERIAL HAS_TMC220x
#endif
#if HAS_SWSERIAL
#include "SoftwareSerial.h"
#endif
#if ENABLED(SRAM_EEPROM_EMULATION)
#if STM32F7xx
#include "stm32f7xx_ll_pwr.h"
#include <stm32f7xx_ll_pwr.h>
#elif STM32F4xx
#include "stm32f4xx_ll_pwr.h"
#include <stm32f4xx_ll_pwr.h>
#else
#error "SRAM_EEPROM_EMULATION is currently only supported for STM32F4xx and STM32F7xx"
#endif
@@ -82,6 +92,10 @@ void HAL_init() {
// Wait until backup regulator is initialized
while (!LL_PWR_IsActiveFlag_BRR());
#endif // EEPROM_EMULATED_SRAM
#if HAS_SWSERIAL
SoftwareSerial::setInterruptPriority(SWSERIAL_TIMER_IRQ_PRIO, 0);
#endif
}
void HAL_clear_reset_source() { __HAL_RCC_CLEAR_RESET_FLAGS(); }
+1
View File
@@ -188,6 +188,7 @@ void eeprom_update_block(const void *__src, void *__dst, size_t __n);
inline void HAL_adc_init() {}
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
+395
View File
@@ -0,0 +1,395 @@
/*
* SoftwareSerial.cpp (formerly NewSoftSerial.cpp)
*
* Multi-instance software serial library for Arduino/Wiring
* -- Interrupt-driven receive and other improvements by ladyada
* (http://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 (http://www.pjrc.com)
* -- 20MHz processor support by Garrett Mace (http://www.macetech.com)
* -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
* -- STM32 support by Armin van der Togt
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The latest version of this library can always be found at
* http://arduiniana.org.
*/
//
// Includes
//
#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)
#include "SoftwareSerial.h"
#include "timers.h"
#define OVERSAMPLE 3 // in RX, Timer will generate interruption OVERSAMPLE time during a bit. Thus OVERSAMPLE ticks in a bit. (interrupt not synchonized with edge).
// defined in bit-periods
#define HALFDUPLEX_SWITCH_DELAY 5
// It's best to define TIMER_SERIAL in variant.h. If not defined, we choose one here
// The order is based on (lack of) features and compare channels, we choose the simplest available
// because we only need an update interrupt
#if !defined(TIMER_SERIAL)
#if defined (TIM18_BASE)
#define TIMER_SERIAL TIM18
#elif defined (TIM7_BASE)
#define TIMER_SERIAL TIM7
#elif defined (TIM6_BASE)
#define TIMER_SERIAL TIM6
#elif defined (TIM22_BASE)
#define TIMER_SERIAL TIM22
#elif defined (TIM21_BASE)
#define TIMER_SERIAL TIM21
#elif defined (TIM17_BASE)
#define TIMER_SERIAL TIM17
#elif defined (TIM16_BASE)
#define TIMER_SERIAL TIM16
#elif defined (TIM15_BASE)
#define TIMER_SERIAL TIM15
#elif defined (TIM14_BASE)
#define TIMER_SERIAL TIM14
#elif defined (TIM13_BASE)
#define TIMER_SERIAL TIM13
#elif defined (TIM11_BASE)
#define TIMER_SERIAL TIM11
#elif defined (TIM10_BASE)
#define TIMER_SERIAL TIM10
#elif defined (TIM12_BASE)
#define TIMER_SERIAL TIM12
#elif defined (TIM19_BASE)
#define TIMER_SERIAL TIM19
#elif defined (TIM9_BASE)
#define TIMER_SERIAL TIM9
#elif defined (TIM5_BASE)
#define TIMER_SERIAL TIM5
#elif defined (TIM4_BASE)
#define TIMER_SERIAL TIM4
#elif defined (TIM3_BASE)
#define TIMER_SERIAL TIM3
#elif defined (TIM2_BASE)
#define TIMER_SERIAL TIM2
#elif defined (TIM20_BASE)
#define TIMER_SERIAL TIM20
#elif defined (TIM8_BASE)
#define TIMER_SERIAL TIM8
#elif defined (TIM1_BASE)
#define TIMER_SERIAL TIM1
#else
#error No suitable timer found for SoftwareSerial, define TIMER_SERIAL in variant.h
#endif
#endif
//
// Statics
//
HardwareTimer SoftwareSerial::timer(TIMER_SERIAL);
const IRQn_Type SoftwareSerial::timer_interrupt_number = static_cast<IRQn_Type>(getTimerUpIrq(TIMER_SERIAL));
uint32_t SoftwareSerial::timer_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), TIM_IRQ_PRIO, TIM_IRQ_SUBPRIO);
SoftwareSerial *SoftwareSerial::active_listener = nullptr;
SoftwareSerial *volatile SoftwareSerial::active_out = nullptr;
SoftwareSerial *volatile SoftwareSerial::active_in = nullptr;
int32_t SoftwareSerial::tx_tick_cnt = 0; // OVERSAMPLE ticks needed for a bit
int32_t volatile SoftwareSerial::rx_tick_cnt = 0; // OVERSAMPLE ticks needed for a bit
uint32_t SoftwareSerial::tx_buffer = 0;
int32_t SoftwareSerial::tx_bit_cnt = 0;
uint32_t SoftwareSerial::rx_buffer = 0;
int32_t SoftwareSerial::rx_bit_cnt = -1; // rx_bit_cnt = -1 : waiting for start bit
uint32_t SoftwareSerial::cur_speed = 0;
void SoftwareSerial::setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority) {
timer_interrupt_priority = NVIC_EncodePriority(NVIC_GetPriorityGrouping(), preemptPriority, subPriority);
}
//
// Private methods
//
void SoftwareSerial::setSpeed(uint32_t speed) {
if (speed != cur_speed) {
timer.pause();
if (speed != 0) {
// Disable the timer
uint32_t clock_rate, cmp_value;
// Get timer clock
clock_rate = timer.getTimerClkFreq();
int pre = 1;
// Calculate prescale an compare value
do {
cmp_value = clock_rate / (speed * OVERSAMPLE);
if (cmp_value >= UINT16_MAX) {
clock_rate /= 2;
pre *= 2;
}
} while (cmp_value >= UINT16_MAX);
timer.setPrescaleFactor(pre);
timer.setOverflow(cmp_value);
timer.setCount(0);
timer.attachInterrupt(&handleInterrupt);
timer.resume();
NVIC_SetPriority(timer_interrupt_number, timer_interrupt_priority);
}
else
timer.detachInterrupt();
cur_speed = speed;
}
}
// This function sets the current object as the "listening"
// one and returns true if it replaces another
bool SoftwareSerial::listen() {
if (active_listener != this) {
// wait for any transmit to complete as we may change speed
while (active_out);
active_listener->stopListening();
rx_tick_cnt = 1; // 1 : next interrupt will decrease rx_tick_cnt to 0 which means RX pin level will be considered.
rx_bit_cnt = -1; // rx_bit_cnt = -1 : waiting for start bit
setSpeed(_speed);
active_listener = this;
if (!_half_duplex) active_in = this;
return true;
}
return false;
}
// Stop listening. Returns true if we were actually listening.
bool SoftwareSerial::stopListening() {
if (active_listener == this) {
// wait for any output to complete
while (active_out);
if (_half_duplex) setRXTX(false);
active_listener = nullptr;
active_in = nullptr;
// turn off ints
setSpeed(0);
return true;
}
return false;
}
inline void SoftwareSerial::setTX() {
if (_inverse_logic)
LL_GPIO_ResetOutputPin(_transmitPinPort, _transmitPinNumber);
else
LL_GPIO_SetOutputPin(_transmitPinPort, _transmitPinNumber);
pinMode(_transmitPin, OUTPUT);
}
inline void SoftwareSerial::setRX() {
pinMode(_receivePin, _inverse_logic ? INPUT_PULLDOWN : INPUT_PULLUP); // pullup for normal logic!
}
inline void SoftwareSerial::setRXTX(bool input) {
if (_half_duplex) {
if (input) {
if (active_in != this) {
setRX();
rx_bit_cnt = -1; // rx_bit_cnt = -1 : waiting for start bit
rx_tick_cnt = 2; // 2 : next interrupt will be discarded. 2 interrupts required to consider RX pin level
active_in = this;
}
}
else {
if (active_in == this) {
setTX();
active_in = nullptr;
}
}
}
}
inline void SoftwareSerial::send() {
if (--tx_tick_cnt <= 0) { // if tx_tick_cnt > 0 interrupt is discarded. Only when tx_tick_cnt reaches 0 is TX pin set.
if (tx_bit_cnt++ < 10) { // tx_bit_cnt < 10 transmission is not finished (10 = 1 start +8 bits + 1 stop)
// Send data (including start and stop bits)
if (tx_buffer & 1)
LL_GPIO_SetOutputPin(_transmitPinPort, _transmitPinNumber);
else
LL_GPIO_ResetOutputPin(_transmitPinPort, _transmitPinNumber);
tx_buffer >>= 1;
tx_tick_cnt = OVERSAMPLE; // Wait OVERSAMPLE ticks to send next bit
}
else { // Transmission finished
tx_tick_cnt = 1;
if (_output_pending) {
active_out = nullptr;
// In half-duplex mode wait HALFDUPLEX_SWITCH_DELAY bit-periods after the byte has
// been transmitted before allowing the switch to RX mode
}
else if (tx_bit_cnt > 10 + OVERSAMPLE * HALFDUPLEX_SWITCH_DELAY) {
if (_half_duplex && active_listener == this) setRXTX(true);
active_out = nullptr;
}
}
}
}
//
// The receive routine called by the interrupt handler
//
inline void SoftwareSerial::recv() {
if (--rx_tick_cnt <= 0) { // if rx_tick_cnt > 0 interrupt is discarded. Only when rx_tick_cnt reaches 0 is RX pin considered
bool inbit = LL_GPIO_IsInputPinSet(_receivePinPort, _receivePinNumber) ^ _inverse_logic;
if (rx_bit_cnt == -1) { // rx_bit_cnt = -1 : waiting for start bit
if (!inbit) {
// got start bit
rx_bit_cnt = 0; // rx_bit_cnt == 0 : start bit received
rx_tick_cnt = OVERSAMPLE + 1; // Wait 1 bit (OVERSAMPLE ticks) + 1 tick in order to sample RX pin in the middle of the edge (and not too close to the edge)
rx_buffer = 0;
}
else
rx_tick_cnt = 1; // Waiting for start bit, but wrong level. Wait for next Interrupt to check RX pin level
}
else if (rx_bit_cnt >= 8) { // rx_bit_cnt >= 8 : waiting for stop bit
if (inbit) {
// Stop-bit read complete. Add to buffer.
uint8_t next = (_receive_buffer_tail + 1) % _SS_MAX_RX_BUFF;
if (next != _receive_buffer_head) {
// save new data in buffer: tail points to byte destination
_receive_buffer[_receive_buffer_tail] = rx_buffer; // save new byte
_receive_buffer_tail = next;
}
else // rx_bit_cnt = x with x = [0..7] correspond to new bit x received
_buffer_overflow = true;
}
// Full trame received. Restart waiting for start bit at next interrupt
rx_tick_cnt = 1;
rx_bit_cnt = -1;
}
else {
// data bits
rx_buffer >>= 1;
if (inbit) rx_buffer |= 0x80;
rx_bit_cnt++; // Prepare for next bit
rx_tick_cnt = OVERSAMPLE; // Wait OVERSAMPLE ticks before sampling next bit
}
}
}
//
// Interrupt handling
//
/* static */
inline void SoftwareSerial::handleInterrupt(HardwareTimer*) {
if (active_in) active_in->recv();
if (active_out) active_out->send();
}
//
// Constructor
//
SoftwareSerial::SoftwareSerial(uint16_t receivePin, uint16_t transmitPin, bool inverse_logic /* = false */) :
_receivePin(receivePin),
_transmitPin(transmitPin),
_receivePinPort(digitalPinToPort(receivePin)),
_receivePinNumber(STM_LL_GPIO_PIN(digitalPinToPinName(receivePin))),
_transmitPinPort(digitalPinToPort(transmitPin)),
_transmitPinNumber(STM_LL_GPIO_PIN(digitalPinToPinName(transmitPin))),
_speed(0),
_buffer_overflow(false),
_inverse_logic(inverse_logic),
_half_duplex(receivePin == transmitPin),
_output_pending(0),
_receive_buffer_tail(0),
_receive_buffer_head(0)
{
if ((receivePin < NUM_DIGITAL_PINS) || (transmitPin < NUM_DIGITAL_PINS)) {
/* Enable GPIO clock for tx and rx pin*/
set_GPIO_Port_Clock(STM_PORT(digitalPinToPinName(transmitPin)));
set_GPIO_Port_Clock(STM_PORT(digitalPinToPinName(receivePin)));
}
else
_Error_Handler("ERROR: invalid pin number\n", -1);
}
//
// Destructor
//
SoftwareSerial::~SoftwareSerial() { end(); }
//
// Public methods
//
void SoftwareSerial::begin(long speed) {
#ifdef FORCE_BAUD_RATE
speed = FORCE_BAUD_RATE;
#endif
_speed = speed;
if (!_half_duplex) {
setTX();
setRX();
listen();
}
else
setTX();
}
void SoftwareSerial::end() {
stopListening();
}
// Read data from buffer
int SoftwareSerial::read() {
// Empty buffer?
if (_receive_buffer_head == _receive_buffer_tail) return -1;
// Read from "head"
uint8_t d = _receive_buffer[_receive_buffer_head]; // grab next byte
_receive_buffer_head = (_receive_buffer_head + 1) % _SS_MAX_RX_BUFF;
return d;
}
int SoftwareSerial::available() {
return (_receive_buffer_tail + _SS_MAX_RX_BUFF - _receive_buffer_head) % _SS_MAX_RX_BUFF;
}
size_t SoftwareSerial::write(uint8_t b) {
// wait for previous transmit to complete
_output_pending = 1;
while (active_out) { /* nada */ }
// add start and stop bits.
tx_buffer = b << 1 | 0x200;
if (_inverse_logic) tx_buffer = ~tx_buffer;
tx_bit_cnt = 0;
tx_tick_cnt = OVERSAMPLE;
setSpeed(_speed);
if (_half_duplex) setRXTX(false);
_output_pending = 0;
// make us active
active_out = this;
return 1;
}
void SoftwareSerial::flush() {
noInterrupts();
_receive_buffer_head = _receive_buffer_tail = 0;
interrupts();
}
int SoftwareSerial::peek() {
// Empty buffer?
if (_receive_buffer_head == _receive_buffer_tail) return -1;
// Read from "head"
return _receive_buffer[_receive_buffer_head];
}
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
+119
View File
@@ -0,0 +1,119 @@
/**
* SoftwareSerial.h (formerly NewSoftSerial.h)
*
* Multi-instance software serial library for Arduino/Wiring
* -- Interrupt-driven receive and other improvements by ladyada
* (http://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 (http://www.pjrc.com)
* -- 20MHz processor support by Garrett Mace (http://www.macetech.com)
* -- ATmega1280/2560 support by Brett Hagman (http://www.roguerobotics.com/)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* The latest version of this library can always be found at
* http://arduiniana.org.
*/
#ifndef SOFTWARESERIAL_H
#define SOFTWARESERIAL_H
#include <Arduino.h>
/******************************************************************************
* Definitions
******************************************************************************/
#define _SS_MAX_RX_BUFF 64 // RX buffer size
class SoftwareSerial : public Stream {
private:
// per object data
uint16_t _receivePin;
uint16_t _transmitPin;
GPIO_TypeDef *_receivePinPort;
uint32_t _receivePinNumber;
GPIO_TypeDef *_transmitPinPort;
uint32_t _transmitPinNumber;
uint32_t _speed;
uint16_t _buffer_overflow: 1;
uint16_t _inverse_logic: 1;
uint16_t _half_duplex: 1;
uint16_t _output_pending: 1;
unsigned char _receive_buffer[_SS_MAX_RX_BUFF];
volatile uint8_t _receive_buffer_tail;
volatile uint8_t _receive_buffer_head;
uint32_t delta_start = 0;
// static data
static bool initialised;
static HardwareTimer timer;
static const IRQn_Type timer_interrupt_number;
static uint32_t timer_interrupt_priority;
static SoftwareSerial *active_listener;
static SoftwareSerial *volatile active_out;
static SoftwareSerial *volatile active_in;
static int32_t tx_tick_cnt;
static volatile int32_t rx_tick_cnt;
static uint32_t tx_buffer;
static int32_t tx_bit_cnt;
static uint32_t rx_buffer;
static int32_t rx_bit_cnt;
static uint32_t cur_speed;
// private methods
void send();
void recv();
void setTX();
void setRX();
void setSpeed(uint32_t speed);
void setRXTX(bool input);
static void handleInterrupt(HardwareTimer *timer);
public:
// public methods
SoftwareSerial(uint16_t receivePin, uint16_t transmitPin, bool inverse_logic = false);
virtual ~SoftwareSerial();
void begin(long speed);
bool listen();
void end();
bool isListening() { return active_listener == this; }
bool stopListening();
bool overflow() {
bool ret = _buffer_overflow;
if (ret) _buffer_overflow = false;
return ret;
}
int peek();
virtual size_t write(uint8_t byte);
virtual int read();
virtual int available();
virtual void flush();
operator bool() { return true; }
static void setInterruptPriority(uint32_t preemptPriority, uint32_t subPriority);
using Print::write;
};
#endif // SOFTWARESERIAL_H
+73 -27
View File
@@ -32,62 +32,108 @@
#define NUM_HARDWARE_TIMERS 2
#define __TIMER_DEV(X) TIM##X
#define _TIMER_DEV(X) __TIMER_DEV(X)
#define STEP_TIMER_DEV _TIMER_DEV(STEP_TIMER)
#define TEMP_TIMER_DEV _TIMER_DEV(TEMP_TIMER)
// ------------------------
// Private Variables
// ------------------------
stm32_timer_t TimerHandle[NUM_HARDWARE_TIMERS];
HardwareTimer *timer_instance[NUM_HARDWARE_TIMERS] = { NULL };
bool timer_enabled[NUM_HARDWARE_TIMERS] = { false };
// ------------------------
// Public functions
// ------------------------
bool timers_initialized[NUM_HARDWARE_TIMERS] = { false };
// frequency is in Hertz
void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
if (!HAL_timer_initialized(timer_num)) {
switch (timer_num) {
case STEP_TIMER_NUM: // STEPPER TIMER - use a 32bit timer if possible
timer_instance[timer_num] = new HardwareTimer(STEP_TIMER_DEV);
/* Set the prescaler to the final desired value.
* This will change the effective ISR callback frequency but when
* HAL_timer_start(timer_num=0) is called in the core for the first time
* the real frequency isn't important as long as, after boot, the ISR
* gets called with the correct prescaler and count register. So here
* we set the prescaler to the correct, final value and ignore the frequency
* asked. We will call back the ISR in 1 second to start at full speed.
*
* The proper fix, however, would be a correct initialization OR a
* HAL_timer_change(const uint8_t timer_num, const uint32_t frequency)
* which changes the prescaler when an IRQ frequency change is needed
* (for example when steppers are turned on)
*/
timer_instance[timer_num]->setPrescaleFactor(STEPPER_TIMER_PRESCALE); //the -1 is done internally
timer_instance[timer_num]->setOverflow(_MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (HAL_TIMER_RATE) / (STEPPER_TIMER_PRESCALE) /* /frequency */), TICK_FORMAT);
break;
case TEMP_TIMER_NUM: // TEMP TIMER - any available 16bit timer
timer_instance[timer_num] = new HardwareTimer(TEMP_TIMER_DEV);
// The prescale factor is computed automatically for HERTZ_FORMAT
timer_instance[timer_num]->setOverflow(frequency, HERTZ_FORMAT);
break;
}
if (!timers_initialized[timer_num]) {
uint32_t step_prescaler = STEPPER_TIMER_PRESCALE - 1,
temp_prescaler = TEMP_TIMER_PRESCALE - 1;
HAL_timer_enable_interrupt(timer_num);
/*
* Initializes (and unfortunately starts) the timer.
* This is needed to set correct IRQ priority at the moment but causes
* no harm since every call to HAL_timer_start() is actually followed by
* a call to HAL_timer_enable_interrupt() which means that there isn't
* a case in which you want the timer to run without a callback.
*/
timer_instance[timer_num]->resume(); // First call to resume() MUST follow the attachInterrupt()
// This is fixed in Arduino_Core_STM32 1.8.
// These calls can be removed and replaced with
// timer_instance[timer_num]->setInterruptPriority
switch (timer_num) {
case STEP_TIMER_NUM:
// STEPPER TIMER - use a 32bit timer if possible
TimerHandle[timer_num].timer = STEP_TIMER_DEV;
TimerHandle[timer_num].irqHandle = Step_Handler;
TimerHandleInit(&TimerHandle[timer_num], (((HAL_TIMER_RATE) / step_prescaler) / frequency) - 1, step_prescaler);
HAL_NVIC_SetPriority(STEP_TIMER_IRQ_NAME, STEP_TIMER_IRQ_PRIO, 0);
break;
case TEMP_TIMER_NUM:
// TEMP TIMER - any available 16bit Timer
TimerHandle[timer_num].timer = TEMP_TIMER_DEV;
TimerHandle[timer_num].irqHandle = Temp_Handler;
TimerHandleInit(&TimerHandle[timer_num], (((HAL_TIMER_RATE) / temp_prescaler) / frequency) - 1, temp_prescaler);
HAL_NVIC_SetPriority(TEMP_TIMER_IRQ_NAME, TEMP_TIMER_IRQ_PRIO, 0);
break;
}
timers_initialized[timer_num] = true;
}
}
void HAL_timer_enable_interrupt(const uint8_t timer_num) {
const IRQn_Type IRQ_Id = IRQn_Type(getTimerIrq(TimerHandle[timer_num].timer));
HAL_NVIC_EnableIRQ(IRQ_Id);
if (HAL_timer_initialized(timer_num) && !timer_enabled[timer_num]) {
timer_enabled[timer_num] = true;
switch (timer_num) {
case STEP_TIMER_NUM:
timer_instance[timer_num]->attachInterrupt(Step_Handler);
break;
case TEMP_TIMER_NUM:
timer_instance[timer_num]->attachInterrupt(Temp_Handler);
break;
}
}
}
void HAL_timer_disable_interrupt(const uint8_t timer_num) {
const IRQn_Type IRQ_Id = IRQn_Type(getTimerIrq(TimerHandle[timer_num].timer));
HAL_NVIC_DisableIRQ(IRQ_Id);
// We NEED memory barriers to ensure Interrupts are actually disabled!
// ( https://dzone.com/articles/nvic-disabling-interrupts-on-arm-cortex-m-and-the )
__DSB();
__ISB();
if (HAL_timer_interrupt_enabled(timer_num)) {
timer_instance[timer_num]->detachInterrupt();
timer_enabled[timer_num] = false;
}
}
bool HAL_timer_interrupt_enabled(const uint8_t timer_num) {
const uint32_t IRQ_Id = getTimerIrq(TimerHandle[timer_num].timer);
return NVIC->ISER[IRQ_Id >> 5] & _BV32(IRQ_Id & 0x1F);
return HAL_timer_initialized(timer_num) && timer_enabled[timer_num];
}
// Only for use within the HAL
TIM_TypeDef * HAL_timer_device(const uint8_t timer_num) {
switch (timer_num) {
case STEP_TIMER_NUM: return STEP_TIMER_DEV;
case TEMP_TIMER_NUM: return TEMP_TIMER_DEV;
}
return nullptr;
}
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
+33 -38
View File
@@ -33,6 +33,7 @@
#define hal_timer_t uint32_t
#define HAL_TIMER_TYPE_MAX 0xFFFFFFFF // Timers can be 16 or 32 bit
#ifdef STM32F0xx
#define HAL_TIMER_RATE (F_CPU) // frequency of timer peripherals
@@ -66,27 +67,30 @@
#endif
#ifndef TEMP_TIMER
#define TEMP_TIMER 7
#define TEMP_TIMER 14 // TIM7 is consumed by Software Serial if used.
#endif
#endif
#ifndef SWSERIAL_TIMER_IRQ_PRIO
#define SWSERIAL_TIMER_IRQ_PRIO 1
#endif
#ifndef STEP_TIMER_IRQ_PRIO
#define STEP_TIMER_IRQ_PRIO 1
#define STEP_TIMER_IRQ_PRIO 2
#endif
#ifndef TEMP_TIMER_IRQ_PRIO
#define TEMP_TIMER_IRQ_PRIO 2
#define TEMP_TIMER_IRQ_PRIO 14 //14 = after hardware ISRs
#endif
#define STEP_TIMER_NUM 0 // index of timer to use for stepper
#define TEMP_TIMER_NUM 1 // index of timer to use for temperature
#define PULSE_TIMER_NUM STEP_TIMER_NUM
#define TEMP_TIMER_RATE 72000 // 72 Khz
#define TEMP_TIMER_PRESCALE ((HAL_TIMER_RATE)/(TEMP_TIMER_RATE))
#define TEMP_TIMER_FREQUENCY 1000
#define TEMP_TIMER_FREQUENCY 1000 //Temperature::isr() is expected to be called at around 1kHz
//TODO: get rid of manual rate/prescale/ticks/cycles taken for procedures in stepper.cpp
#define STEPPER_TIMER_RATE 2000000 // 2 Mhz
#define STEPPER_TIMER_PRESCALE ((HAL_TIMER_RATE)/(STEPPER_TIMER_RATE))
#define STEPPER_TIMER_TICKS_PER_US ((STEPPER_TIMER_RATE) / 1000000) // stepper timer ticks per µs
@@ -95,17 +99,6 @@
#define PULSE_TIMER_PRESCALE STEPPER_TIMER_PRESCALE
#define PULSE_TIMER_TICKS_PER_US STEPPER_TIMER_TICKS_PER_US
#define __TIMER_DEV(X) TIM##X
#define _TIMER_DEV(X) __TIMER_DEV(X)
#define STEP_TIMER_DEV _TIMER_DEV(STEP_TIMER)
#define TEMP_TIMER_DEV _TIMER_DEV(TEMP_TIMER)
#define __TIMER_CALLBACK(X) TIM##X##_IRQHandler
#define _TIMER_CALLBACK(X) __TIMER_CALLBACK(X)
#define STEP_TIMER_CALLBACK _TIMER_CALLBACK(STEP_TIMER)
#define TEMP_TIMER_CALLBACK _TIMER_CALLBACK(TEMP_TIMER)
#define __TIMER_IRQ_NAME(X) TIM##X##_IRQn
#define _TIMER_IRQ_NAME(X) __TIMER_IRQ_NAME(X)
@@ -119,22 +112,16 @@
#define ENABLE_TEMPERATURE_INTERRUPT() HAL_timer_enable_interrupt(TEMP_TIMER_NUM)
#define DISABLE_TEMPERATURE_INTERRUPT() HAL_timer_disable_interrupt(TEMP_TIMER_NUM)
extern void Step_Handler(stimer_t *htim);
extern void Temp_Handler(stimer_t *htim);
#define HAL_STEP_TIMER_ISR() void Step_Handler(stimer_t *htim)
#define HAL_TEMP_TIMER_ISR() void Temp_Handler(stimer_t *htim)
// ------------------------
// Types
// ------------------------
typedef stimer_t stm32_timer_t;
extern void Step_Handler(HardwareTimer *htim);
extern void Temp_Handler(HardwareTimer *htim);
#define HAL_STEP_TIMER_ISR() void Step_Handler(HardwareTimer *htim)
#define HAL_TEMP_TIMER_ISR() void Temp_Handler(HardwareTimer *htim)
// ------------------------
// Public Variables
// ------------------------
extern stm32_timer_t TimerHandle[];
extern HardwareTimer *timer_instance[];
// ------------------------
// Public functions
@@ -145,18 +132,26 @@ void HAL_timer_enable_interrupt(const uint8_t timer_num);
void HAL_timer_disable_interrupt(const uint8_t timer_num);
bool HAL_timer_interrupt_enabled(const uint8_t timer_num);
FORCE_INLINE static uint32_t HAL_timer_get_count(const uint8_t timer_num) {
return __HAL_TIM_GET_COUNTER(&TimerHandle[timer_num].handle);
//TIM_TypeDef* HAL_timer_device(const uint8_t timer_num); no need to be public for now. not public = not used externally
// FORCE_INLINE because these are used in performance-critical situations
FORCE_INLINE bool HAL_timer_initialized(const uint8_t timer_num) {
return timer_instance[timer_num] != NULL;
}
FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_num) {
return HAL_timer_initialized(timer_num) ? timer_instance[timer_num]->getCount() : 0;
}
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const uint32_t compare) {
__HAL_TIM_SET_AUTORELOAD(&TimerHandle[timer_num].handle, compare);
if (HAL_timer_get_count(timer_num) >= compare)
TimerHandle[timer_num].handle.Instance->EGR |= TIM_EGR_UG; // Generate an immediate update interrupt
}
FORCE_INLINE static hal_timer_t HAL_timer_get_compare(const uint8_t timer_num) {
return __HAL_TIM_GET_AUTORELOAD(&TimerHandle[timer_num].handle);
// NOTE: Method name may be misleading.
// STM32 has an Auto-Reload Register (ARR) as opposed to a "compare" register
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_num, const hal_timer_t overflow) {
if (HAL_timer_initialized(timer_num)) {
timer_instance[timer_num]->setOverflow(overflow + 1, TICK_FORMAT); // Value decremented by setOverflow()
// wiki: "force all registers (Autoreload, prescaler, compare) to be taken into account"
// So, if the new overflow value is less than the count it will trigger a rollover interrupt.
if (overflow < timer_instance[timer_num]->getCount()) // Added 'if' here because reports say it won't boot without it
timer_instance[timer_num]->refresh();
}
}
#define HAL_timer_isr_prologue(TIMER_NUM)
+1 -1
View File
@@ -272,7 +272,7 @@ extern "C" {
// return free memory between end of heap (or end bss) and whatever is current
/*
#include "wirish/syscalls.c"
#include <wirish/syscalls.c>
//extern caddr_t _sbrk(int incr);
#ifndef CONFIG_HEAP_END
extern char _lm_heap_end;
+9
View File
@@ -51,6 +51,14 @@
// Defines
// ------------------------
#ifndef STM32_FLASH_SIZE
#ifdef MCU_STM32F103RE
#define STM32_FLASH_SIZE 512
#else
#define STM32_FLASH_SIZE 256
#endif
#endif
#ifdef SERIAL_USB
#ifndef USE_USB_COMPOSITE
#define UsbSerial Serial
@@ -238,6 +246,7 @@ void eeprom_update_block(const void *__src, void *__dst, size_t __n);
void HAL_adc_init();
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
+1 -1
View File
@@ -53,7 +53,7 @@ static const spi_pins* dev_to_spi_pins(spi_dev *dev);
static void configure_gpios(spi_dev *dev, bool as_master);
static spi_baud_rate determine_baud_rate(spi_dev *dev, uint32_t freq);
#if (BOARD_NR_SPI >= 3) && !defined(STM32_HIGH_DENSITY)
#if BOARD_NR_SPI >= 3 && !defined(STM32_HIGH_DENSITY)
#error "The SPI library is misconfigured: 3 SPI ports only available on high density STM32 devices"
#endif
+3 -1
View File
@@ -20,7 +20,9 @@
#include <stdint.h>
#define SW_SERIAL_PLACEHOLDER 1
#ifndef HAVE_SW_SERIAL
#define SW_SERIAL_PLACEHOLDER 1
#endif
class SoftwareSerial {
public:
@@ -36,3 +36,8 @@
#if ENABLED(FAST_PWM_FAN)
#error "FAST_PWM_FAN is not yet implemented for this platform."
#endif
#if !defined(HAVE_SW_SERIAL) && HAS_TMC220x
#warning "With TMC2208/9 consider using SoftwareSerialM with HAVE_SW_SERIAL and appropriate SS_TIMER."
#error "Missing SoftwareSerial implementation."
#endif
+3 -3
View File
@@ -57,7 +57,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
case 3: irq_num = NVIC_TIMER3; break;
case 4: irq_num = NVIC_TIMER4; break;
case 5: irq_num = NVIC_TIMER5; break;
#if ENABLED(STM32_HIGH_DENSITY)
#ifdef STM32_HIGH_DENSITY
// 6 & 7 are basic timers, avoid them
case 8: irq_num = NVIC_TIMER8_CC; break;
#endif
@@ -82,7 +82,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
timer_set_prescaler(STEP_TIMER_DEV, (uint16_t)(STEPPER_TIMER_PRESCALE - 1));
timer_set_reload(STEP_TIMER_DEV, 0xFFFF);
timer_oc_set_mode(STEP_TIMER_DEV, STEP_TIMER_CHAN, TIMER_OC_MODE_FROZEN, TIMER_OC_NO_PRELOAD); // no output pin change
timer_set_compare(STEP_TIMER_DEV, STEP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (STEPPER_TIMER_RATE / frequency)));
timer_set_compare(STEP_TIMER_DEV, STEP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (STEPPER_TIMER_RATE) / frequency));
timer_no_ARR_preload_ARPE(STEP_TIMER_DEV); // Need to be sure no preload on ARR register
timer_attach_interrupt(STEP_TIMER_DEV, STEP_TIMER_CHAN, stepTC_Handler);
nvic_irq_set_priority(irq_num, STEP_TIMER_IRQ_PRIO);
@@ -95,7 +95,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
timer_set_count(TEMP_TIMER_DEV, 0);
timer_set_prescaler(TEMP_TIMER_DEV, (uint16_t)(TEMP_TIMER_PRESCALE - 1));
timer_set_reload(TEMP_TIMER_DEV, 0xFFFF);
timer_set_compare(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), ((F_CPU / TEMP_TIMER_PRESCALE) / frequency)));
timer_set_compare(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, _MIN(hal_timer_t(HAL_TIMER_TYPE_MAX), (F_CPU) / (TEMP_TIMER_PRESCALE) / frequency));
timer_attach_interrupt(TEMP_TIMER_DEV, TEMP_TIMER_CHAN, tempTC_Handler);
nvic_irq_set_priority(irq_num, TEMP_TIMER_IRQ_PRIO);
timer_generate_update(TEMP_TIMER_DEV);
+19 -1
View File
@@ -47,6 +47,20 @@ typedef uint16_t hal_timer_t;
#define STEP_TIMER_CHAN 1 // Channel of the timer to use for compare and interrupts
#define TEMP_TIMER_CHAN 1 // Channel of the timer to use for compare and interrupts
/**
* Note: Timers may be used by platforms and libraries
*
* FAN PWMs:
* With FAN_SOFT_PWM disabled the Temperature class uses
* FANx_PIN timers to generate FAN PWM signals.
*
* Speaker:
* When SPEAKER is enabled, one timer is allocated by maple/tone.cpp.
* - If BEEPER_PIN has a timer channel (and USE_PIN_TIMER is
* defined in tone.cpp) it uses the pin's own timer.
* - Otherwise it uses Timer 8 on boards with STM32_HIGH_DENSITY
* or Timer 4 on other boards.
*/
#if defined(MCU_STM32F103CB) || defined(MCU_STM32F103C8)
#define STEP_TIMER_NUM 4 // For C8/CB boards, use timer 4
#else
@@ -58,7 +72,11 @@ typedef uint16_t hal_timer_t;
#if MB(BIGTREE_SKR_MINI_E3, BIGTREE_SKR_E3_DIP, BTT_SKR_MINI_E3_V1_2, MKS_ROBIN_LITE)
// SKR Mini E3 boards use PA8 as FAN_PIN, so TIMER 1 is used for Fan PWM.
#define SERVO0_TIMER_NUM 8
#ifdef STM32_HIGH_DENSITY
#define SERVO0_TIMER_NUM 8 // tone.cpp uses Timer 4
#else
#define SERVO0_TIMER_NUM 3 // tone.cpp uses Timer 8
#endif
#else
#define SERVO0_TIMER_NUM 1 // SERVO0 or BLTOUCH
#endif
+1 -1
View File
@@ -64,7 +64,7 @@ extern "C" {
// return free memory between end of heap (or end bss) and whatever is current
/*
#include "wirish/syscalls.c"
#include <wirish/syscalls.c>
//extern caddr_t _sbrk(int incr);
#ifndef CONFIG_HEAP_END
extern char _lm_heap_end;
+4 -4
View File
@@ -24,16 +24,15 @@
#define CPU_32_BIT
#include "../../inc/MarlinConfigPre.h"
#include "../shared/Marduino.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
#include "watchdog.h"
#include "timers.h"
#include "../../inc/MarlinConfigPre.h"
#include "watchdog.h"
#include <stdint.h>
@@ -208,6 +207,7 @@ void eeprom_update_block (const void *__src, void *__dst, size_t __n);
inline void HAL_adc_init() {}
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_result
#define HAL_ADC_READY() true
+1 -1
View File
@@ -38,7 +38,7 @@
//Error_Handler();
}
else {
#if PIN_EXISTS(LED) && !ENABLED(PINS_DEBUGGING)
#if PIN_EXISTS(LED) && DISABLED(PINS_DEBUGGING)
TOGGLE(LED_PIN); // heartbeat indicator
#endif
}
+1
View File
@@ -109,6 +109,7 @@ extern "C" {
void HAL_adc_init();
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_get_result()
#define HAL_ADC_READY() true
+2 -2
View File
@@ -53,7 +53,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
FTM0_SC = 0x00; // Set this to zero before changing the modulus
FTM0_CNT = 0x0000; // Reset the count to zero
FTM0_MOD = 0xFFFF; // max modulus = 65535
FTM0_C0V = FTM0_TIMER_RATE / frequency; // Initial FTM Channel 0 compare value
FTM0_C0V = (FTM0_TIMER_RATE) / frequency; // Initial FTM Channel 0 compare value
FTM0_SC = (FTM_SC_CLKS(0b1) & FTM_SC_CLKS_MASK) | (FTM_SC_PS(FTM0_TIMER_PRESCALE_BITS) & FTM_SC_PS_MASK); // Bus clock 60MHz divided by prescaler 8
FTM0_C0SC = FTM_CSC_CHIE | FTM_CSC_MSA | FTM_CSC_ELSA;
break;
@@ -62,7 +62,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
FTM1_SC = 0x00; // Set this to zero before changing the modulus
FTM1_CNT = 0x0000; // Reset the count to zero
FTM1_MOD = 0xFFFF; // max modulus = 65535
FTM1_C0V = FTM1_TIMER_RATE / frequency; // Initial FTM Channel 0 compare value 65535
FTM1_C0V = (FTM1_TIMER_RATE) / frequency; // Initial FTM Channel 0 compare value 65535
FTM1_SC = (FTM_SC_CLKS(0b1) & FTM_SC_CLKS_MASK) | (FTM_SC_PS(FTM1_TIMER_PRESCALE_BITS) & FTM_SC_PS_MASK); // Bus clock 60MHz divided by prescaler 4
FTM1_C0SC = FTM_CSC_CHIE | FTM_CSC_MSA | FTM_CSC_ELSA;
break;
+1
View File
@@ -115,6 +115,7 @@ extern "C" {
void HAL_adc_init();
#define HAL_START_ADC(pin) HAL_adc_start_conversion(pin)
#define HAL_ADC_RESOLUTION 10
#define HAL_READ_ADC() HAL_adc_get_result()
#define HAL_ADC_READY() true
+2 -2
View File
@@ -54,7 +54,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
FTM0_SC = 0x00; // Set this to zero before changing the modulus
FTM0_CNT = 0x0000; // Reset the count to zero
FTM0_MOD = 0xFFFF; // max modulus = 65535
FTM0_C0V = FTM0_TIMER_RATE / frequency; // Initial FTM Channel 0 compare value
FTM0_C0V = (FTM0_TIMER_RATE) / frequency; // Initial FTM Channel 0 compare value
FTM0_SC = (FTM_SC_CLKS(0b1) & FTM_SC_CLKS_MASK) | (FTM_SC_PS(FTM0_TIMER_PRESCALE_BITS) & FTM_SC_PS_MASK); // Bus clock 60MHz divided by prescaler 8
FTM0_C0SC = FTM_CSC_CHIE | FTM_CSC_MSA | FTM_CSC_ELSA;
break;
@@ -63,7 +63,7 @@ void HAL_timer_start(const uint8_t timer_num, const uint32_t frequency) {
FTM1_SC = 0x00; // Set this to zero before changing the modulus
FTM1_CNT = 0x0000; // Reset the count to zero
FTM1_MOD = 0xFFFF; // max modulus = 65535
FTM1_C0V = FTM1_TIMER_RATE / frequency; // Initial FTM Channel 0 compare value 65535
FTM1_C0V = (FTM1_TIMER_RATE) / frequency; // Initial FTM Channel 0 compare value 65535
FTM1_SC = (FTM_SC_CLKS(0b1) & FTM_SC_CLKS_MASK) | (FTM_SC_PS(FTM1_TIMER_PRESCALE_BITS) & FTM_SC_PS_MASK); // Bus clock 60MHz divided by prescaler 4
FTM1_C0SC = FTM_CSC_CHIE | FTM_CSC_MSA | FTM_CSC_ELSA;
break;
+4 -3
View File
@@ -36,14 +36,15 @@
#if __CORTEX_M == 7
// Cortex-M7 can use the cycle counter of the DWT unit
// Cortex-M3 through M7 can use the cycle counter of the DWT unit
// http://www.anthonyvh.com/2017/05/18/cortex_m-cycle_counter/
FORCE_INLINE static void enableCycleCounter() {
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
// Unlock DWT.
DWT->LAR = 0xC5ACCE55;
#if __CORTEX_M == 7
DWT->LAR = 0xC5ACCE55; // Unlock DWT on the M7
#endif
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
@@ -20,10 +20,9 @@
*
*/
#include "backtrace.h"
#if defined(__arm__) || defined(__thumb__)
#include "backtrace.h"
#include "unwinder.h"
#include "unwmemaccess.h"
+61 -71
View File
@@ -181,6 +181,12 @@
#include "libs/L6470/L6470_Marlin.h"
#endif
const char G28_STR[] PROGMEM = "G28",
M21_STR[] PROGMEM = "M21",
M23_STR[] PROGMEM = "M23 %s",
M24_STR[] PROGMEM = "M24",
NUL_STR[] PROGMEM = "";
bool Running = true;
// For M109 and M190, this flag may be cleared (by M108) to exit the wait loop
@@ -280,7 +286,8 @@ void quickstop_stepper() {
}
void enable_e_steppers() {
enable_E0(); enable_E1(); enable_E2(); enable_E3(); enable_E4(); enable_E5();
#define _ENA_E(N) enable_E##N();
REPEAT(E_STEPPERS, _ENA_E)
}
void enable_all_steppers() {
@@ -294,17 +301,14 @@ void enable_all_steppers() {
}
void disable_e_steppers() {
disable_E0(); disable_E1(); disable_E2(); disable_E3(); disable_E4(); disable_E5();
#define _DIS_E(N) disable_E##N();
REPEAT(E_STEPPERS, _DIS_E)
}
void disable_e_stepper(const uint8_t e) {
#define _CASE_DIS_E(N) case N: disable_E##N(); break;
switch (e) {
case 0: disable_E0(); break;
case 1: disable_E1(); break;
case 2: disable_E2(); break;
case 3: disable_E3(); break;
case 4: disable_E4(); break;
case 5: disable_E5(); break;
REPEAT(EXTRUDERS, _CASE_DIS_E)
}
}
@@ -367,12 +371,46 @@ bool printingIsPaused() {
}
void startOrResumeJob() {
#if ENABLED(CANCEL_OBJECTS)
if (!printingIsPaused()) cancelable.reset();
#endif
if (!printingIsPaused()) {
#if ENABLED(CANCEL_OBJECTS)
cancelable.reset();
#endif
#if ENABLED(LCD_SHOW_E_TOTAL)
e_move_accumulator = 0;
#endif
#if BOTH(LCD_SET_PROGRESS_MANUALLY, USE_M73_REMAINING_TIME)
ui.reset_remaining_time();
#endif
}
print_job_timer.start();
}
#if ENABLED(SDSUPPORT)
void abortSDPrinting() {
card.stopSDPrint(
#if SD_RESORT
true
#endif
);
queue.clear();
quickstop_stepper();
print_job_timer.stop();
#if DISABLED(SD_ABORT_NO_COOLDOWN)
thermalManager.disable_all_heaters();
#endif
thermalManager.zero_fan_speeds();
wait_for_heatup = false;
#if ENABLED(POWER_LOSS_RECOVERY)
card.removeJobRecoveryFile();
#endif
#ifdef EVENT_GCODE_SD_STOP
queue.inject_P(PSTR(EVENT_GCODE_SD_STOP));
#endif
}
#endif
/**
* Manage several activities:
* - Check for Filament Runout
@@ -478,7 +516,7 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) {
if (ELAPSED(ms, next_home_key_ms)) {
next_home_key_ms = ms + HOME_DEBOUNCE_DELAY;
LCD_MESSAGEPGM(MSG_AUTO_HOME);
queue.enqueue_now_P(PSTR("G28"));
queue.enqueue_now_P(G28_STR);
}
}
#endif
@@ -510,24 +548,11 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) {
#else // !SWITCHING_EXTRUDER
bool oldstatus;
switch (active_extruder) {
default: oldstatus = E0_ENABLE_READ(); enable_E0(); break;
#if E_STEPPERS > 1
case 1: oldstatus = E1_ENABLE_READ(); enable_E1(); break;
#if E_STEPPERS > 2
case 2: oldstatus = E2_ENABLE_READ(); enable_E2(); break;
#if E_STEPPERS > 3
case 3: oldstatus = E3_ENABLE_READ(); enable_E3(); break;
#if E_STEPPERS > 4
case 4: oldstatus = E4_ENABLE_READ(); enable_E4(); break;
#if E_STEPPERS > 5
case 5: oldstatus = E5_ENABLE_READ(); enable_E5(); break;
#endif // E_STEPPERS > 5
#endif // E_STEPPERS > 4
#endif // E_STEPPERS > 3
#endif // E_STEPPERS > 2
#endif // E_STEPPERS > 1
default:
#define _CASE_EN(N) case N: oldstatus = E##N_ENABLE_READ(); enable_E##N(); break;
REPEAT(E_STEPPERS, _CASE_EN);
}
#endif // !SWITCHING_EXTRUDER
#endif
const float olde = current_position.e;
current_position.e += EXTRUDER_RUNOUT_EXTRUDE;
@@ -548,22 +573,8 @@ void manage_inactivity(const bool ignore_stepper_queue/*=false*/) {
}
#else // !SWITCHING_EXTRUDER
switch (active_extruder) {
case 0: E0_ENABLE_WRITE(oldstatus); break;
#if E_STEPPERS > 1
case 1: E1_ENABLE_WRITE(oldstatus); break;
#if E_STEPPERS > 2
case 2: E2_ENABLE_WRITE(oldstatus); break;
#if E_STEPPERS > 3
case 3: E3_ENABLE_WRITE(oldstatus); break;
#if E_STEPPERS > 4
case 4: E4_ENABLE_WRITE(oldstatus); break;
#if E_STEPPERS > 5
case 5: E5_ENABLE_WRITE(oldstatus); break;
#endif // E_STEPPERS > 5
#endif // E_STEPPERS > 4
#endif // E_STEPPERS > 3
#endif // E_STEPPERS > 2
#endif // E_STEPPERS > 1
#define _CASE_RESTORE(N) case N: E##N##_ENABLE_WRITE(oldstatus); break;
REPEAT(E_STEPPERS, _CASE_RESTORE);
}
#endif // !SWITCHING_EXTRUDER
@@ -709,7 +720,8 @@ void kill(PGM_P const lcd_error/*=nullptr*/, PGM_P const lcd_component/*=nullptr
SERIAL_ERROR_MSG(MSG_ERR_KILLED);
#if HAS_DISPLAY
ui.kill_screen(lcd_error ?: GET_TEXT(MSG_KILLED), lcd_component);
extern const char NUL_STR[];
ui.kill_screen(lcd_error ?: GET_TEXT(MSG_KILLED), lcd_component ?: NUL_STR);
#else
UNUSED(lcd_error);
UNUSED(lcd_component);
@@ -1119,34 +1131,12 @@ void loop() {
idle(); // Do an idle first so boot is slightly faster
#if ENABLED(SDSUPPORT)
card.checkautostart();
if (card.flag.abort_sd_printing) {
card.stopSDPrint(
#if SD_RESORT
true
#endif
);
queue.clear();
quickstop_stepper();
print_job_timer.stop();
#if DISABLED(SD_ABORT_NO_COOLDOWN)
thermalManager.disable_all_heaters();
#endif
thermalManager.zero_fan_speeds();
wait_for_heatup = false;
#if ENABLED(POWER_LOSS_RECOVERY)
card.removeJobRecoveryFile();
#endif
#ifdef EVENT_GCODE_SD_STOP
queue.inject_P(PSTR(EVENT_GCODE_SD_STOP));
#endif
}
#endif // SDSUPPORT
if (card.flag.abort_sd_printing) abortSDPrinting();
#endif
queue.advance();
endstops.event_handler();
}
}
+108 -106
View File
@@ -51,96 +51,96 @@ void manage_inactivity(const bool ignore_stepper_queue=false);
//
#if AXIS_DRIVER_TYPE_X(L6470)
extern L6470 stepperX;
#define X_enable NOOP
#define X_disable stepperX.free()
#define X_enable() NOOP
#define X_disable() stepperX.free()
#elif HAS_X_ENABLE
#define X_enable X_ENABLE_WRITE( X_ENABLE_ON)
#define X_disable X_ENABLE_WRITE(!X_ENABLE_ON)
#define X_enable() X_ENABLE_WRITE( X_ENABLE_ON)
#define X_disable() X_ENABLE_WRITE(!X_ENABLE_ON)
#else
#define X_enable NOOP
#define X_disable NOOP
#define X_enable() NOOP
#define X_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_X2(L6470)
extern L6470 stepperX2;
#define X2_enable NOOP
#define X2_disable stepperX2.free()
#define X2_enable() NOOP
#define X2_disable() stepperX2.free()
#elif HAS_X2_ENABLE
#define X2_enable X2_ENABLE_WRITE( X_ENABLE_ON)
#define X2_disable X2_ENABLE_WRITE(!X_ENABLE_ON)
#define X2_enable() X2_ENABLE_WRITE( X_ENABLE_ON)
#define X2_disable() X2_ENABLE_WRITE(!X_ENABLE_ON)
#else
#define X2_enable NOOP
#define X2_disable NOOP
#define X2_enable() NOOP
#define X2_disable() NOOP
#endif
#define enable_X() do{ X_enable; X2_enable; }while(0)
#define disable_X() do{ X_disable; X2_disable; CBI(axis_known_position, X_AXIS); }while(0)
#define enable_X() do{ X_enable(); X2_enable(); }while(0)
#define disable_X() do{ X_disable(); X2_disable(); CBI(axis_known_position, X_AXIS); }while(0)
#if AXIS_DRIVER_TYPE_Y(L6470)
extern L6470 stepperY;
#define Y_enable NOOP
#define Y_disable stepperY.free()
#define Y_enable() NOOP
#define Y_disable() stepperY.free()
#elif HAS_Y_ENABLE
#define Y_enable Y_ENABLE_WRITE( Y_ENABLE_ON)
#define Y_disable Y_ENABLE_WRITE(!Y_ENABLE_ON)
#define Y_enable() Y_ENABLE_WRITE( Y_ENABLE_ON)
#define Y_disable() Y_ENABLE_WRITE(!Y_ENABLE_ON)
#else
#define Y_enable NOOP
#define Y_disable NOOP
#define Y_enable() NOOP
#define Y_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_Y2(L6470)
extern L6470 stepperY2;
#define Y2_enable NOOP
#define Y2_disable stepperY2.free()
#define Y2_enable() NOOP
#define Y2_disable() stepperY2.free()
#elif HAS_Y2_ENABLE
#define Y2_enable Y2_ENABLE_WRITE( Y_ENABLE_ON)
#define Y2_disable Y2_ENABLE_WRITE(!Y_ENABLE_ON)
#define Y2_enable() Y2_ENABLE_WRITE( Y_ENABLE_ON)
#define Y2_disable() Y2_ENABLE_WRITE(!Y_ENABLE_ON)
#else
#define Y2_enable NOOP
#define Y2_disable NOOP
#define Y2_enable() NOOP
#define Y2_disable() NOOP
#endif
#define enable_Y() do{ Y_enable; Y2_enable; }while(0)
#define disable_Y() do{ Y_disable; Y2_disable; CBI(axis_known_position, Y_AXIS); }while(0)
#define enable_Y() do{ Y_enable(); Y2_enable(); }while(0)
#define disable_Y() do{ Y_disable(); Y2_disable(); CBI(axis_known_position, Y_AXIS); }while(0)
#if AXIS_DRIVER_TYPE_Z(L6470)
extern L6470 stepperZ;
#define Z_enable NOOP
#define Z_disable stepperZ.free()
#define Z_enable() NOOP
#define Z_disable() stepperZ.free()
#elif HAS_Z_ENABLE
#define Z_enable Z_ENABLE_WRITE( Z_ENABLE_ON)
#define Z_disable Z_ENABLE_WRITE(!Z_ENABLE_ON)
#define Z_enable() Z_ENABLE_WRITE( Z_ENABLE_ON)
#define Z_disable() Z_ENABLE_WRITE(!Z_ENABLE_ON)
#else
#define Z_enable NOOP
#define Z_disable NOOP
#define Z_enable() NOOP
#define Z_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_Z2(L6470)
extern L6470 stepperZ2;
#define Z2_enable NOOP
#define Z2_disable stepperZ2.free()
#define Z2_enable() NOOP
#define Z2_disable() stepperZ2.free()
#elif HAS_Z2_ENABLE
#define Z2_enable Z2_ENABLE_WRITE( Z_ENABLE_ON)
#define Z2_disable Z2_ENABLE_WRITE(!Z_ENABLE_ON)
#define Z2_enable() Z2_ENABLE_WRITE( Z_ENABLE_ON)
#define Z2_disable() Z2_ENABLE_WRITE(!Z_ENABLE_ON)
#else
#define Z2_enable NOOP
#define Z2_disable NOOP
#define Z2_enable() NOOP
#define Z2_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_Z3(L6470)
extern L6470 stepperZ3;
#define Z3_enable NOOP
#define Z3_disable stepperZ3.free()
#define Z3_enable() NOOP
#define Z3_disable() stepperZ3.free()
#elif HAS_Z3_ENABLE
#define Z3_enable Z3_ENABLE_WRITE( Z_ENABLE_ON)
#define Z3_disable Z3_ENABLE_WRITE(!Z_ENABLE_ON)
#define Z3_enable() Z3_ENABLE_WRITE( Z_ENABLE_ON)
#define Z3_disable() Z3_ENABLE_WRITE(!Z_ENABLE_ON)
#else
#define Z3_enable NOOP
#define Z3_disable NOOP
#define Z3_enable() NOOP
#define Z3_disable() NOOP
#endif
#define enable_Z() do{ Z_enable; Z2_enable; Z3_enable; }while(0)
#define disable_Z() do{ Z_disable; Z2_disable; Z3_disable; CBI(axis_known_position, Z_AXIS); }while(0)
#define enable_Z() do{ Z_enable(); Z2_enable(); Z3_enable(); }while(0)
#define disable_Z() do{ Z_disable(); Z2_disable(); Z3_disable(); CBI(axis_known_position, Z_AXIS); }while(0)
//
// Extruder Stepper enable / disable
@@ -149,74 +149,74 @@ void manage_inactivity(const bool ignore_stepper_queue=false);
// define the individual enables/disables
#if AXIS_DRIVER_TYPE_E0(L6470)
extern L6470 stepperE0;
#define E0_enable NOOP
#define E0_disable do{ stepperE0.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define E0_enable() NOOP
#define E0_disable() do{ stepperE0.free(); CBI(axis_known_position, E_AXIS); }while(0)
#elif HAS_E0_ENABLE
#define E0_enable E0_ENABLE_WRITE( E_ENABLE_ON)
#define E0_disable E0_ENABLE_WRITE(!E_ENABLE_ON)
#define E0_enable() E0_ENABLE_WRITE( E_ENABLE_ON)
#define E0_disable() E0_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define E0_enable NOOP
#define E0_disable NOOP
#define E0_enable() NOOP
#define E0_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_E1(L6470)
extern L6470 stepperE1;
#define E1_enable NOOP
#define E1_disable do{ stepperE1.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define E1_enable() NOOP
#define E1_disable() do{ stepperE1.free(); CBI(axis_known_position, E_AXIS); }while(0)
#elif E_STEPPERS > 1 && HAS_E1_ENABLE
#define E1_enable E1_ENABLE_WRITE( E_ENABLE_ON)
#define E1_disable E1_ENABLE_WRITE(!E_ENABLE_ON)
#define E1_enable() E1_ENABLE_WRITE( E_ENABLE_ON)
#define E1_disable() E1_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define E1_enable NOOP
#define E1_disable NOOP
#define E1_enable() NOOP
#define E1_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_E2(L6470)
extern L6470 stepperE2;
#define E2_enable NOOP
#define E2_disable do{ stepperE2.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define E2_enable() NOOP
#define E2_disable() do{ stepperE2.free(); CBI(axis_known_position, E_AXIS); }while(0)
#elif E_STEPPERS > 2 && HAS_E2_ENABLE
#define E2_enable E2_ENABLE_WRITE( E_ENABLE_ON)
#define E2_disable E2_ENABLE_WRITE(!E_ENABLE_ON)
#define E2_enable() E2_ENABLE_WRITE( E_ENABLE_ON)
#define E2_disable() E2_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define E2_enable NOOP
#define E2_disable NOOP
#define E2_enable() NOOP
#define E2_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_E3(L6470)
extern L6470 stepperE3;
#define E3_enable NOOP
#define E3_disable do{ stepperE3.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define E3_enable() NOOP
#define E3_disable() do{ stepperE3.free(); CBI(axis_known_position, E_AXIS); }while(0)
#elif E_STEPPERS > 3 && HAS_E3_ENABLE
#define E3_enable E3_ENABLE_WRITE( E_ENABLE_ON)
#define E3_disable E3_ENABLE_WRITE(!E_ENABLE_ON)
#define E3_enable() E3_ENABLE_WRITE( E_ENABLE_ON)
#define E3_disable() E3_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define E3_enable NOOP
#define E3_disable NOOP
#define E3_enable() NOOP
#define E3_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_E4(L6470)
extern L6470 stepperE4;
#define E4_enable NOOP
#define E4_disable do{ stepperE4.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define E4_enable() NOOP
#define E4_disable() do{ stepperE4.free(); CBI(axis_known_position, E_AXIS); }while(0)
#elif E_STEPPERS > 4 && HAS_E4_ENABLE
#define E4_enable E4_ENABLE_WRITE( E_ENABLE_ON)
#define E4_disable E4_ENABLE_WRITE(!E_ENABLE_ON)
#define E4_enable() E4_ENABLE_WRITE( E_ENABLE_ON)
#define E4_disable() E4_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define E4_enable NOOP
#define E4_disable NOOP
#define E4_enable() NOOP
#define E4_disable() NOOP
#endif
#if AXIS_DRIVER_TYPE_E5(L6470)
extern L6470 stepperE5;
#define E5_enable NOOP
#define E5_disable do{ stepperE5.free(); CBI(axis_known_position, E_AXIS); }while(0)
#define E5_enable() NOOP
#define E5_disable() do{ stepperE5.free(); CBI(axis_known_position, E_AXIS); }while(0)
#elif E_STEPPERS > 5 && HAS_E5_ENABLE
#define E5_enable E5_ENABLE_WRITE( E_ENABLE_ON)
#define E5_disable E5_ENABLE_WRITE(!E_ENABLE_ON)
#define E5_enable() E5_ENABLE_WRITE( E_ENABLE_ON)
#define E5_disable() E5_ENABLE_WRITE(!E_ENABLE_ON)
#else
#define E5_enable NOOP
#define E5_disable NOOP
#define E5_enable() NOOP
#define E5_disable() NOOP
#endif
#if ENABLED(MIXING_EXTRUDER)
@@ -225,20 +225,20 @@ void manage_inactivity(const bool ignore_stepper_queue=false);
* Mixing steppers synchronize their enable (and direction) together
*/
#if MIXING_STEPPERS > 5
#define enable_E0() { E0_enable; E1_enable; E2_enable; E3_enable; E4_enable; E5_enable; }
#define disable_E0() { E0_disable; E1_disable; E2_disable; E3_disable; E4_disable; E5_disable; }
#define enable_E0() { E0_enable(); E1_enable(); E2_enable(); E3_enable(); E4_enable(); E5_enable(); }
#define disable_E0() { E0_disable(); E1_disable(); E2_disable(); E3_disable(); E4_disable(); E5_disable(); }
#elif MIXING_STEPPERS > 4
#define enable_E0() { E0_enable; E1_enable; E2_enable; E3_enable; E4_enable; }
#define disable_E0() { E0_disable; E1_disable; E2_disable; E3_disable; E4_disable; }
#define enable_E0() { E0_enable(); E1_enable(); E2_enable(); E3_enable(); E4_enable(); }
#define disable_E0() { E0_disable(); E1_disable(); E2_disable(); E3_disable(); E4_disable(); }
#elif MIXING_STEPPERS > 3
#define enable_E0() { E0_enable; E1_enable; E2_enable; E3_enable; }
#define disable_E0() { E0_disable; E1_disable; E2_disable; E3_disable; }
#define enable_E0() { E0_enable(); E1_enable(); E2_enable(); E3_enable(); }
#define disable_E0() { E0_disable(); E1_disable(); E2_disable(); E3_disable(); }
#elif MIXING_STEPPERS > 2
#define enable_E0() { E0_enable; E1_enable; E2_enable; }
#define disable_E0() { E0_disable; E1_disable; E2_disable; }
#define enable_E0() { E0_enable(); E1_enable(); E2_enable(); }
#define disable_E0() { E0_disable(); E1_disable(); E2_disable(); }
#else
#define enable_E0() { E0_enable; E1_enable; }
#define disable_E0() { E0_disable; E1_disable; }
#define enable_E0() { E0_enable(); E1_enable(); }
#define disable_E0() { E0_disable(); E1_disable(); }
#endif
#define enable_E1() NOOP
#define disable_E1() NOOP
@@ -254,48 +254,48 @@ void manage_inactivity(const bool ignore_stepper_queue=false);
#else // !MIXING_EXTRUDER
#if HAS_E0_ENABLE
#define enable_E0() E0_enable
#define disable_E0() E0_disable
#define enable_E0() E0_enable()
#define disable_E0() E0_disable()
#else
#define enable_E0() NOOP
#define disable_E0() NOOP
#endif
#if E_STEPPERS > 1 && HAS_E1_ENABLE
#define enable_E1() E1_enable
#define disable_E1() E1_disable
#define enable_E1() E1_enable()
#define disable_E1() E1_disable()
#else
#define enable_E1() NOOP
#define disable_E1() NOOP
#endif
#if E_STEPPERS > 2 && HAS_E2_ENABLE
#define enable_E2() E2_enable
#define disable_E2() E2_disable
#define enable_E2() E2_enable()
#define disable_E2() E2_disable()
#else
#define enable_E2() NOOP
#define disable_E2() NOOP
#endif
#if E_STEPPERS > 3 && HAS_E3_ENABLE
#define enable_E3() E3_enable
#define disable_E3() E3_disable
#define enable_E3() E3_enable()
#define disable_E3() E3_disable()
#else
#define enable_E3() NOOP
#define disable_E3() NOOP
#endif
#if E_STEPPERS > 4 && HAS_E4_ENABLE
#define enable_E4() E4_enable
#define disable_E4() E4_disable
#define enable_E4() E4_enable()
#define disable_E4() E4_disable()
#else
#define enable_E4() NOOP
#define disable_E4() NOOP
#endif
#if E_STEPPERS > 5 && HAS_E5_ENABLE
#define enable_E5() E5_enable
#define disable_E5() E5_disable
#define enable_E5() E5_enable()
#define disable_E5() E5_disable()
#else
#define enable_E5() NOOP
#define disable_E5() NOOP
@@ -376,3 +376,5 @@ void protected_pin_err();
void event_probe_recover();
void event_probe_failure();
#endif
extern const char G28_STR[], M21_STR[], M23_STR[], M24_STR[], NUL_STR[];
+2
View File
@@ -99,6 +99,8 @@
#define BOARD_OVERLORD 1143 // Overlord/Overlord Pro
#define BOARD_HJC2560C_REV1 1144 // ADIMLab Gantry v1
#define BOARD_HJC2560C_REV2 1145 // ADIMLab Gantry v2
#define BOARD_TANGO 1146 // BIQU Tango V1
#define BOARD_MKS_GEN_L_V2 1147 // MKS GEN L V2
//
// RAMBo and derivatives
+13
View File
@@ -121,6 +121,19 @@
|| AXIS_DRIVER_TYPE(A,TMC5130) \
|| AXIS_DRIVER_TYPE(A,TMC5160) )
#define HAS_TMC_E_DRIVER ( HAS_E_DRIVER(TMC2130) \
|| HAS_E_DRIVER(TMC2160) \
|| HAS_E_DRIVER(TMC2660) \
|| HAS_E_DRIVER(TMC2209) \
|| HAS_E_DRIVER(TMC5130) \
|| HAS_E_DRIVER(TMC5160) )
#define HAS_TMC_STANDALONE_E_DRIVER ( HAS_E_DRIVER(TMC2130_STANDALONE) \
|| HAS_E_DRIVER(TMC2160_STANDALONE) \
|| HAS_E_DRIVER(TMC2660_STANDALONE) \
|| HAS_E_DRIVER(TMC2209_STANDALONE) \
|| HAS_E_DRIVER(TMC5130_STANDALONE) \
|| HAS_E_DRIVER(TMC5160_STANDALONE) )
//
// Stretching 'drivers.h' to include LPC/SAMD51 SD options
//
+6 -4
View File
@@ -258,9 +258,9 @@
#define MSG_KILL_BUTTON "KILL caused by KILL button/pin"
// temperature.cpp strings
#define MSG_PID_AUTOTUNE "PID Autotune"
#define MSG_PID_AUTOTUNE_START MSG_PID_AUTOTUNE " start"
#define MSG_PID_AUTOTUNE_FAILED MSG_PID_AUTOTUNE " failed!"
#define MSG_PID_AUTOTUNE_PREFIX "PID Autotune"
#define MSG_PID_AUTOTUNE_START MSG_PID_AUTOTUNE_PREFIX " start"
#define MSG_PID_AUTOTUNE_FAILED MSG_PID_AUTOTUNE_PREFIX " failed!"
#define MSG_PID_BAD_EXTRUDER_NUM MSG_PID_AUTOTUNE_FAILED " Bad extruder number"
#define MSG_PID_TEMP_TOO_HIGH MSG_PID_AUTOTUNE_FAILED " Temperature too high"
#define MSG_PID_TIMEOUT MSG_PID_AUTOTUNE_FAILED " timeout"
@@ -275,7 +275,7 @@
#define MSG_KI " Ki: "
#define MSG_KD " Kd: "
#define MSG_AT " @:"
#define MSG_PID_AUTOTUNE_FINISHED MSG_PID_AUTOTUNE " finished! Put the last Kp, Ki and Kd constants from below into Configuration.h"
#define MSG_PID_AUTOTUNE_FINISHED MSG_PID_AUTOTUNE_PREFIX " finished! Put the last Kp, Ki and Kd constants from below into Configuration.h"
#define MSG_PID_DEBUG " PID_DEBUG "
#define MSG_PID_DEBUG_INPUT ": Input "
#define MSG_PID_DEBUG_OUTPUT " Output "
@@ -349,6 +349,7 @@
*
*/
#if ENABLED(NUMBER_TOOLS_FROM_0)
#define LCD_FIRST_TOOL '0'
#define LCD_STR_N0 "0"
#define LCD_STR_N1 "1"
#define LCD_STR_N2 "2"
@@ -356,6 +357,7 @@
#define LCD_STR_N4 "4"
#define LCD_STR_N5 "5"
#else
#define LCD_FIRST_TOOL '1'
#define LCD_STR_N0 "1"
#define LCD_STR_N1 "2"
#define LCD_STR_N2 "3"
+125 -26
View File
@@ -165,6 +165,7 @@
// Macros to support option testing
#define _CAT(a,V...) a##V
#define CAT(a,V...) _CAT(a,V)
#define SWITCH_ENABLED_false 0
#define SWITCH_ENABLED_true 1
#define SWITCH_ENABLED_0 0
@@ -229,32 +230,6 @@
#define _JOIN_1(O) (O)
#define JOIN_N(N,C,V...) (DO(JOIN,C,LIST_N(N,V)))
// Macros for adding
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INCREMENT_(n) INC_##n
#define INCREMENT(n) INCREMENT_(n)
// Macros for subtracting
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
#define DECREMENT_(n) DEC_##n
#define DECREMENT(n) DECREMENT_(n)
#define NOOP (void(0))
#define CEILING(x,y) (((x) + (y) - 1) / (y))
@@ -346,3 +321,127 @@
#define _MAX(V...) _MAX_N(NUM_ARGS(V), V)
#endif
// Macros for adding
#define INC_0 1
#define INC_1 2
#define INC_2 3
#define INC_3 4
#define INC_4 5
#define INC_5 6
#define INC_6 7
#define INC_7 8
#define INC_8 9
#define INCREMENT_(n) INC_##n
#define INCREMENT(n) INCREMENT_(n)
#define ADD0(N) N
#define ADD1(N) INCREMENT_(N)
#define ADD2(N) ADD1(ADD1(N))
#define ADD3(N) ADD1(ADD2(N))
#define ADD4(N) ADD2(ADD2(N))
#define ADD5(N) ADD2(ADD3(N))
#define ADD6(N) ADD3(ADD3(N))
#define ADD7(N) ADD3(ADD4(N))
#define ADD8(N) ADD4(ADD4(N))
#define ADD9(N) ADD4(ADD5(N))
#define ADD10(N) ADD5(ADD5(N))
// Macros for subtracting
#define DEC_0 0
#define DEC_1 0
#define DEC_2 1
#define DEC_3 2
#define DEC_4 3
#define DEC_5 4
#define DEC_6 5
#define DEC_7 6
#define DEC_8 7
#define DEC_9 8
#define DECREMENT_(n) DEC_##n
#define DECREMENT(n) DECREMENT_(n)
#define SUB0(N) N
#define SUB1(N) DECREMENT_(N)
#define SUB2(N) SUB1(SUB1(N))
#define SUB3(N) SUB1(SUB2(N))
#define SUB4(N) SUB2(SUB2(N))
#define SUB5(N) SUB2(SUB3(N))
#define SUB6(N) SUB3(SUB3(N))
#define SUB7(N) SUB3(SUB4(N))
#define SUB8(N) SUB4(SUB4(N))
#define SUB9(N) SUB4(SUB5(N))
#define SUB10(N) SUB5(SUB5(N))
//
// Primitives supporting precompiler REPEAT
//
#define FIRST(a,...) a
#define SECOND(a,b,...) b
// Defer expansion
#define EMPTY()
#define DEFER(M) M EMPTY()
#define DEFER2(M) M EMPTY EMPTY()()
#define DEFER3(M) M EMPTY EMPTY EMPTY()()()
#define DEFER4(M) M EMPTY EMPTY EMPTY EMPTY()()()()
// Force define expansion
#define EVAL(V...) EVAL16(V)
#define EVAL1024(V...) EVAL512(EVAL512(V))
#define EVAL512(V...) EVAL256(EVAL256(V))
#define EVAL256(V...) EVAL128(EVAL128(V))
#define EVAL128(V...) EVAL64(EVAL64(V))
#define EVAL64(V...) EVAL32(EVAL32(V))
#define EVAL32(V...) EVAL16(EVAL16(V))
#define EVAL16(V...) EVAL8(EVAL8(V))
#define EVAL8(V...) EVAL4(EVAL4(V))
#define EVAL4(V...) EVAL2(EVAL2(V))
#define EVAL2(V...) EVAL1(EVAL1(V))
#define EVAL1(V...) V
#define IS_PROBE(V...) SECOND(V, 0) // Get the second item passed, or 0
#define PROBE() ~, 1 // Second item will be 1 if this is passed
#define _NOT_0 PROBE()
#define NOT(x) IS_PROBE(_CAT(_NOT_, x)) // NOT('0') gets '1'. Anything else gets '0'.
#define _BOOL(x) NOT(NOT(x)) // NOT('0') gets '0'. Anything else gets '1'.
#define IF_ELSE(TF) _IF_ELSE(_BOOL(TF))
#define _IF_ELSE(TF) _CAT(_IF_, TF)
#define _IF_1(V...) V _IF_1_ELSE
#define _IF_0(...) _IF_0_ELSE
#define _IF_1_ELSE(...)
#define _IF_0_ELSE(V...) V
#define HAS_ARGS(V...) _BOOL(FIRST(_END_OF_ARGUMENTS_ V)())
#define _END_OF_ARGUMENTS_() 0
//
// REPEAT core macros. Recurse N times with ascending I.
//
// Call OP(I) N times with ascending counter.
#define _REPEAT(_RPT_I,_RPT_N,_RPT_OP) \
_RPT_OP(_RPT_I) \
IF_ELSE(SUB1(_RPT_N)) \
( DEFER2(__REPEAT)()(ADD1(_RPT_I),SUB1(_RPT_N),_RPT_OP) ) \
( /* Do nothing */ )
#define __REPEAT() _REPEAT
// Call OP(I, ...) N times with ascending counter.
#define _REPEAT2(_RPT_I,_RPT_N,_RPT_OP,V...) \
_RPT_OP(_RPT_I,V) \
IF_ELSE(SUB1(_RPT_N)) \
( DEFER2(__REPEAT2)()(ADD1(_RPT_I),SUB1(_RPT_N),_RPT_OP,V) ) \
( /* Do nothing */ )
#define __REPEAT2() _REPEAT2
// Repeat a macro passing S...N-1.
#define REPEAT_S(S,N,OP) EVAL(_REPEAT(S,SUB##S(N),OP))
#define REPEAT(N,OP) REPEAT_S(0,N,OP)
// Repeat a macro passing 0...N-1 plus additional arguments.
#define REPEAT2_S(S,N,OP,V...) EVAL(_REPEAT2(S,SUB##S(N),OP,V))
#define REPEAT2(N,OP,V...) REPEAT2_S(0,N,OP,V)
+3
View File
@@ -26,6 +26,9 @@
#include "millis_t.h"
class __FlashStringHelper;
typedef const __FlashStringHelper *progmem_str;
//
// Enumerated axis indices
//
+4 -4
View File
@@ -338,7 +338,7 @@
}
z_values[cpos.x][cpos.y] = NAN;
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(closest, 0);
ExtUI::onMeshUpdate(cpos, 0.0f);
#endif
cnt++;
}
@@ -541,7 +541,7 @@
else {
z_values[cpos.x][cpos.y] = g29_constant;
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(closest, g29_constant);
ExtUI::onMeshUpdate(cpos, g29_constant);
#endif
}
}
@@ -783,7 +783,7 @@
);
z_values[best.pos.x][best.pos.y] = measured_z;
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(best, measured_z);
ExtUI::onMeshUpdate(best.pos, measured_z);
#endif
}
SERIAL_FLUSH(); // Prevent host M105 buffer overrun.
@@ -1335,7 +1335,7 @@
if (!isnan(v2)) {
z_values[x][y] = v1 < v2 ? v1 : v1 + v1 - v2;
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(x, y, z_values[pos.x][pos.y]);
ExtUI::onMeshUpdate(x, y, z_values[x][y]);
#endif
return true;
}
+7
View File
@@ -42,6 +42,13 @@ void CancelObject::set_active_object(const int8_t obj) {
}
else
skipping = false;
#if HAS_DISPLAY
if (active_object >= 0)
ui.status_printf_P(0, PSTR(S_FMT " %i"), GET_TEXT(MSG_PRINTING_OBJECT), int(active_object + 1));
else
ui.reset_status();
#endif
}
void CancelObject::cancel_object(const int8_t obj) {
+1
View File
@@ -32,6 +32,7 @@ public:
static void cancel_object(const int8_t obj);
static void uncancel_object(const int8_t obj);
static void report();
static inline bool is_canceled(const int8_t obj) { return TEST(canceled, obj); }
static inline void clear_active_object() { set_active_object(-1); }
static inline void cancel_active_object() { cancel_object(active_object); }
static inline void reset() { canceled = 0x0000; object_count = 0; clear_active_object(); }
+3 -17
View File
@@ -56,23 +56,9 @@ void controllerfan_update() {
|| Z3_ENABLE_READ() == Z_ENABLE_ON
#endif
#if E_STEPPERS
|| E0_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 1
|| E1_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 2
|| E2_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 3
|| E3_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 4
|| E4_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 5
|| E5_ENABLE_READ() == E_ENABLE_ON
#endif // E_STEPPERS > 5
#endif // E_STEPPERS > 4
#endif // E_STEPPERS > 3
#endif // E_STEPPERS > 2
#endif // E_STEPPERS > 1
#endif // E_STEPPERS
#define _OR_ENABLED_E(N) || E##N##_ENABLE_READ() == E_ENABLE_ON
REPEAT(E_STEPPERS, _OR_ENABLED_E)
#endif
) {
lastMotorOn = ms; //... set time to NOW so the fan will turn on
}
+2 -1
View File
@@ -23,6 +23,7 @@
#include "../inc/MarlinConfig.h"
#include "../module/planner.h"
#include "../module/thermistor/thermistors.h"
class FilamentWidthSensor {
public:
@@ -66,7 +67,7 @@ public:
}
// Convert raw measurement to mm
static inline float raw_to_mm(const uint16_t v) { return v * 5.0f * RECIPROCAL(16383.0f); }
static inline float raw_to_mm(const uint16_t v) { return v * 5.0f * RECIPROCAL(float(MAX_RAW_THERMISTOR_VALUE)); }
static inline float raw_to_mm() { return raw_to_mm(raw); }
// A scaled reading is ready
+2 -1
View File
@@ -151,7 +151,8 @@ void host_action(const char * const pstr, const bool eol) {
case PROMPT_PAUSE_RESUME:
msg = PSTR("LCD_PAUSE_RESUME");
#if ENABLED(ADVANCED_PAUSE_FEATURE)
queue.inject_P(PSTR("M24"));
extern const char M24_STR[];
queue.inject_P(M24_STR);
#endif
break;
case PROMPT_INFO:
+1 -1
View File
@@ -148,7 +148,7 @@ Joystick joystick;
float hypot2 = 0;
LOOP_XYZ(i) if (norm_jog[i]) {
move_dist[i] = seg_time * norm_jog[i] *
#if EITHER(ULTIPANEL, EXTENSIBLE_UI)
#if ENABLED(EXTENSIBLE_UI)
MMM_TO_MMS(manual_feedrate_mm_m[i]);
#else
planner.settings.max_feedrate_mm_s[i];
+2 -2
View File
@@ -464,7 +464,7 @@ bool pause_print(const float &retract, const xyz_pos_t &park_point, const float
#endif
if (unload_length) // Unload the filament
unload_filament(unload_length, show_lcd);
unload_filament(unload_length, show_lcd, PAUSE_MODE_CHANGE_FILAMENT);
#if ENABLED(DUAL_X_CARRIAGE)
active_extruder = saved_ext;
@@ -637,7 +637,7 @@ void resume_print(const float &slow_load_length/*=0*/, const float &fast_load_le
}
if (nozzle_timed_out || thermalManager.hotEnoughToExtrude(active_extruder)) // Load the new filament
load_filament(slow_load_length, fast_load_length, purge_length, max_beep_count, true, nozzle_timed_out, PAUSE_MODE_PAUSE_PRINT DXC_PASS);
load_filament(slow_load_length, fast_load_length, purge_length, max_beep_count, true, nozzle_timed_out, PAUSE_MODE_SAME DXC_PASS);
#if HAS_LCD_MENU
lcd_pause_show_message(PAUSE_MESSAGE_RESUME);
+13 -27
View File
@@ -59,33 +59,19 @@ bool Power::is_power_needed() {
#if HAS_HEATED_BED
|| thermalManager.temp_bed.soft_pwm_amount > 0
#endif
#if HAS_X2_ENABLE
|| X2_ENABLE_READ() == X_ENABLE_ON
#endif
#if HAS_Y2_ENABLE
|| Y2_ENABLE_READ() == Y_ENABLE_ON
#endif
#if HAS_Z2_ENABLE
|| Z2_ENABLE_READ() == Z_ENABLE_ON
#endif
#if E_STEPPERS
|| E0_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 1
|| E1_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 2
|| E2_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 3
|| E3_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 4
|| E4_ENABLE_READ() == E_ENABLE_ON
#if E_STEPPERS > 5
|| E5_ENABLE_READ() == E_ENABLE_ON
#endif // E_STEPPERS > 5
#endif // E_STEPPERS > 4
#endif // E_STEPPERS > 3
#endif // E_STEPPERS > 2
#endif // E_STEPPERS > 1
#endif // E_STEPPERS
#if HAS_X2_ENABLE
|| X2_ENABLE_READ() == X_ENABLE_ON
#endif
#if HAS_Y2_ENABLE
|| Y2_ENABLE_READ() == Y_ENABLE_ON
#endif
#if HAS_Z2_ENABLE
|| Z2_ENABLE_READ() == Z_ENABLE_ON
#endif
#if E_STEPPERS
#define _OR_ENABLED_E(N) || E##N##_ENABLE_READ() == E_ENABLE_ON
REPEAT(E_STEPPERS, _OR_ENABLED_E)
#endif
) return true;
HOTEND_LOOP() if (thermalManager.degTargetHotend(e) > 0) return true;
+32 -1
View File
@@ -183,6 +183,15 @@ void PrintJobRecovery::save(const bool force/*=false*/, const bool save_queue/*=
info.active_extruder = active_extruder;
#endif
#if DISABLED(NO_VOLUMETRICS)
info.volumetric_enabled = parser.volumetric_enabled;
#if EXTRUDERS > 1
for (int8_t e = 0; e < EXTRUDERS; e++) info.filament_size[e] = planner.filament_size[e];
#else
if (parser.volumetric_enabled) info.filament_size = planner.filament_size[active_extruder];
#endif
#endif
#if EXTRUDERS
HOTEND_LOOP() info.target_temperature[e] = thermalManager.temp_hotend[e].target;
#endif
@@ -291,6 +300,27 @@ void PrintJobRecovery::resume() {
gcode.process_subcommands_now(cmd);
#endif
// Recover volumetric extrusion state
#if DISABLED(NO_VOLUMETRICS)
#if EXTRUDERS > 1
for (int8_t e = 0; e < EXTRUDERS; e++) {
dtostrf(info.filament_size[e], 1, 3, str_1);
sprintf_P(cmd, PSTR("M200 T%i D%s"), e, str_1);
gcode.process_subcommands_now(cmd);
}
if (!info.volumetric_enabled) {
sprintf_P(cmd, PSTR("M200 T%i D0"), info.active_extruder);
gcode.process_subcommands_now(cmd);
}
#else
if (info.volumetric_enabled) {
dtostrf(info.filament_size, 1, 3, str_1);
sprintf_P(cmd, PSTR("M200 D%s"), str_1);
gcode.process_subcommands_now(cmd);
}
#endif
#endif
#if HAS_HEATED_BED
const int16_t bt = info.target_temperature_bed;
if (bt) {
@@ -407,7 +437,8 @@ void PrintJobRecovery::resume() {
// Resume the SD file from the last position
char *fn = info.sd_filename;
sprintf_P(cmd, PSTR("M23 %s"), fn);
extern const char M23_STR[];
sprintf_P(cmd, M23_STR, fn);
gcode.process_subcommands_now(cmd);
sprintf_P(cmd, PSTR("M24 S%ld T%ld"), resume_sdpos, info.print_job_elapsed);
gcode.process_subcommands_now(cmd);
+9
View File
@@ -59,6 +59,15 @@ typedef struct {
uint8_t active_extruder;
#endif
#if DISABLED(NO_VOLUMETRICS)
bool volumetric_enabled;
#if EXTRUDERS > 1
float filament_size[EXTRUDERS];
#else
float filament_size;
#endif
#endif
#if HOTENDS
int16_t target_temperature[HOTENDS];
#endif
+1 -1
View File
@@ -169,7 +169,7 @@ template<char AXIS_LETTER, char DRIVER_ID, AxisEnum AXIS_ID>
class TMCMarlin<TMC2208Stepper, AXIS_LETTER, DRIVER_ID, AXIS_ID> : public TMC2208Stepper, public TMCStorage<AXIS_LETTER, DRIVER_ID> {
public:
TMCMarlin(Stream * SerialPort, const float RS, const uint8_t) :
TMC2208Stepper(SerialPort, RS, /*has_rx=*/true)
TMC2208Stepper(SerialPort, RS)
{}
TMCMarlin(const uint16_t RX, const uint16_t TX, const float RS, const uint8_t, const bool has_rx=true) :
TMC2208Stepper(RX, TX, RS, has_rx)
+1 -1
View File
@@ -62,7 +62,7 @@ class TWIBus {
* @brief Internal buffer
* @details A fixed buffer. TWI commands can be no longer than this.
*/
char buffer[TWIBUS_BUFFER_SIZE];
uint8_t buffer[TWIBUS_BUFFER_SIZE];
public:
+6 -6
View File
@@ -225,7 +225,7 @@ G29_TYPE GcodeSuite::G29() {
#if ABL_GRID
#if ENABLED(PROBE_MANUALLY)
ABL_VAR xy_int8_t meshCount;
ABL_VAR xy_uint8_t meshCount;
#endif
ABL_VAR xy_int_t probe_position_lf, probe_position_rb;
@@ -678,13 +678,13 @@ G29_TYPE GcodeSuite::G29() {
measured_z = 0;
xy_int8_t meshCount;
xy_uint8_t meshCount;
// Outer loop is X with PROBE_Y_FIRST enabled
// Outer loop is Y with PROBE_Y_FIRST disabled
for (PR_OUTER_VAR = 0; PR_OUTER_VAR < PR_OUTER_END && !isnan(measured_z); PR_OUTER_VAR++) {
int8_t inStart, inStop, inInc;
uint8_t inStart, inStop, inInc;
if (zig) { // away from origin
inStart = 0;
@@ -693,8 +693,8 @@ G29_TYPE GcodeSuite::G29() {
}
else { // towards origin
inStart = PR_INNER_END - 1;
inStop = -1;
inInc = -1;
inStop = 0xFF;
inInc = 0xFF;
}
zig ^= true; // zag
@@ -746,7 +746,7 @@ G29_TYPE GcodeSuite::G29() {
z_values[meshCount.x][meshCount.y] = measured_z + zoffset;
#if ENABLED(EXTENSIBLE_UI)
ExtUI::onMeshUpdate(meshCount.x, meshCount.y, z_values[meshCount.x][meshCount.y]);
ExtUI::onMeshUpdate(meshCount, z_values[meshCount.x][meshCount.y]);
#endif
#endif
+57 -3
View File
@@ -230,6 +230,7 @@ void GcodeSuite::G28(const bool always_home_all) {
}
#endif
// Home (O)nly if position is unknown
if (!homing_needed() && parser.boolval('O')) {
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("> homing not needed, skip\n<<< G28");
return;
@@ -256,6 +257,40 @@ void GcodeSuite::G28(const bool always_home_all) {
workspace_plane = PLANE_XY;
#endif
#define HAS_CURRENT_HOME(N) (defined(N##_CURRENT_HOME) && N##_CURRENT_HOME != N##_CURRENT)
#define HAS_HOMING_CURRENT (HAS_CURRENT_HOME(X) || HAS_CURRENT_HOME(X2) || HAS_CURRENT_HOME(Y) || HAS_CURRENT_HOME(Y2))
#if HAS_HOMING_CURRENT
auto debug_current = [](const char * const s, const int16_t a, const int16_t b){
DEBUG_ECHO(s); DEBUG_ECHOLNPGM(" current: ", a, " -> ", b);
};
#if HAS_CURRENT_HOME(X)
const int16_t tmc_save_current_X = stepperX.getMilliamps();
stepperX.rms_current(X_CURRENT_HOME);
if (DEBUGGING(LEVELING)) debug_current("X", tmc_save_current_X, X_CURRENT_HOME);
#endif
#if HAS_CURRENT_HOME(X2)
const int16_t tmc_save_current_X2 = stepperX2.getMilliamps();
stepperX2.rms_current(X2_CURRENT_HOME);
if (DEBUGGING(LEVELING)) debug_current("X2", tmc_save_current_X2, X2_CURRENT_HOME);
#endif
#if HAS_CURRENT_HOME(Y)
const int16_t tmc_save_current_Y = stepperY.getMilliamps();
stepperY.rms_current(Y_CURRENT_HOME);
if (DEBUGGING(LEVELING)) debug_current("Y", tmc_save_current_Y, Y_CURRENT_HOME);
#endif
#if HAS_CURRENT_HOME(Y2)
const int16_t tmc_save_current_Y2 = stepperY2.getMilliamps();
stepperY2.rms_current(Y2_CURRENT_HOME);
if (DEBUGGING(LEVELING)) debug_current("Y2", tmc_save_current_Y2, Y2_CURRENT_HOME);
#endif
#endif
#if BOTH(STEALTHCHOP_XY, HOME_USING_SPREADCYCLE)
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Set XY to spreadCycle...");
process_subcommands_now_P(PSTR("M569S0XY"));
#endif
#if ENABLED(IMPROVE_HOMING_RELIABILITY)
slow_homing_t slow_homing = begin_slow_homing();
#endif
@@ -308,7 +343,7 @@ void GcodeSuite::G28(const bool always_home_all) {
if (z_homing_height && (doX || doY)) {
// Raise Z before homing any other axes and z is not already high enough (never lower z)
destination.z = z_homing_height;
destination.z = z_homing_height + (TEST(axis_known_position, Z_AXIS) ? 0.0f : current_position.z);
if (destination.z > current_position.z) {
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPAIR("Raise Z (before homing) to ", destination.z);
do_blocking_move_to_z(destination.z);
@@ -426,8 +461,6 @@ void GcodeSuite::G28(const bool always_home_all) {
delayed_move_time = 0;
active_extruder_parked = true;
extruder_duplication_enabled = IDEX_saved_duplication_state;
extruder_duplication_enabled = false;
dual_x_carriage_mode = IDEX_saved_mode;
stepper.set_directions();
@@ -466,6 +499,27 @@ void GcodeSuite::G28(const bool always_home_all) {
tool_change(old_tool_index, NO_FETCH);
#endif
#if HAS_HOMING_CURRENT
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Restore driver current...");
#if HAS_CURRENT_HOME(X)
stepperX.rms_current(tmc_save_current_X);
#endif
#if HAS_CURRENT_HOME(X2)
stepperX2.rms_current(tmc_save_current_X2);
#endif
#if HAS_CURRENT_HOME(Y)
stepperY.rms_current(tmc_save_current_Y);
#endif
#if HAS_CURRENT_HOME(Y2)
stepperY2.rms_current(tmc_save_current_Y2);
#endif
#endif
#if BOTH(STEALTHCHOP_XY, HOME_USING_SPREADCYCLE)
if (DEBUGGING(LEVELING)) DEBUG_ECHOLNPGM("Set XY to StealthChop...");
process_subcommands_now_P(PSTR("M569S1XY"));
#endif
ui.refresh();
report_current_position();
+2 -2
View File
@@ -108,7 +108,7 @@ void L6470_report_current(L6470 &motor, const uint8_t axis) {
SERIAL_ECHO(temp_buf);
SERIAL_ECHOPGM(" Motor Status: ");
const char * const stat_str;
const char *stat_str;
switch (motor_status) {
default:
case 0: stat_str = PSTR("stopped"); break;
@@ -124,7 +124,7 @@ void L6470_report_current(L6470 &motor, const uint8_t axis) {
SERIAL_ECHOPGM(" Vs_compensation: ");
serialprintPGM((motor.GetParam(L6470_CONFIG) & CONFIG_EN_VSCOMP) ? PSTR("ENABLED ") : PSTR("DISABLED"));
SERIAL_ECHOLNPGM(" Compensation coefficient: ", dtostrf(comp_coef * 0.01f, 7, 2, numstr));
SERIAL_ECHOLNPAIR(" Compensation coefficient: ", dtostrf(comp_coef * 0.01f, 7, 2, numstr));
SERIAL_ECHOPAIR("...KVAL_HOLD: ", motor.GetParam(L6470_KVAL_HOLD));
SERIAL_ECHOPAIR(" KVAL_RUN : ", motor.GetParam(L6470_KVAL_RUN));
SERIAL_ECHOPAIR(" KVAL_ACC: ", motor.GetParam(L6470_KVAL_ACC));
+3 -3
View File
@@ -36,11 +36,11 @@ static void jiggle_axis(const char axis_char, const float &min, const float &max
char gcode_string[30], str1[11], str2[11];
// Turn the motor(s) both directions
sprintf_P(gcode_string, PSTR("G0 %c%s F%s"), axis_char, dtostrf(min, 1, 3, str1), dtostrf(rate, 1, 3, str2));
process_subcommands_now(gcode_string);
sprintf_P(gcode_string, PSTR("G0 %c%s F%s"), axis_char, dtostrf(min, 1, 3, str1), dtostrf(fr_mm_m, 1, 3, str2));
gcode.process_subcommands_now(gcode_string);
sprintf_P(gcode_string, PSTR("G0 %c%s F%s"), axis_char, dtostrf(max, 1, 3, str1), str2);
process_subcommands_now(gcode_string);
gcode.process_subcommands_now(gcode_string);
planner.synchronize();
}
+7 -2
View File
@@ -31,6 +31,10 @@
millis_t chdk_timeout; // = 0
#endif
#ifdef PHOTO_POSITION && PHOTO_DELAY_MS > 0
#include "../../../Marlin.h" // for idle()
#endif
#ifdef PHOTO_RETRACT_MM
#define _PHOTO_RETRACT_MM (PHOTO_RETRACT_MM + 0)
@@ -148,7 +152,7 @@ void GcodeSuite::M240() {
#if PIN_EXISTS(CHDK)
OUT_WRITE(CHDK_PIN, HIGH);
chdk_timeout = millis() + PHOTO_SWITCH_MS;
chdk_timeout = millis() + parser.intval('D', PHOTO_SWITCH_MS);
#elif HAS_PHOTOGRAPH
@@ -160,7 +164,8 @@ void GcodeSuite::M240() {
#ifdef PHOTO_POSITION
#if PHOTO_DELAY_MS > 0
safe_delay(parser.intval('P', PHOTO_DELAY_MS));
const millis_t timeout = millis() + parser.intval('P', PHOTO_DELAY_MS);
while (PENDING(millis(), timeout)) idle();
#endif
do_blocking_move_to(old_pos, fr_mm_s);
#ifdef PHOTO_RETRACT_MM
+1 -14
View File
@@ -79,20 +79,7 @@ void GcodeSuite::M164() {
// Get mixing parameters from the GCode
// The total "must" be 1.0 (but it will be normalized)
// If no mix factors are given, the old mix is preserved
const char mixing_codes[] = { 'A', 'B'
#if MIXING_STEPPERS > 2
, 'C'
#if MIXING_STEPPERS > 3
, 'D'
#if MIXING_STEPPERS > 4
, 'H'
#if MIXING_STEPPERS > 5
, 'I'
#endif // MIXING_STEPPERS > 5
#endif // MIXING_STEPPERS > 4
#endif // MIXING_STEPPERS > 3
#endif // MIXING_STEPPERS > 2
};
const char mixing_codes[] = { LIST_N(MIXING_STEPPERS, 'A', 'B', 'C', 'D', 'H', 'I') };
uint8_t mix_bits = 0;
MIXER_STEPPER_LOOP(i) {
if (parser.seenval(mixing_codes[i])) {
@@ -28,6 +28,7 @@
#include "../../../Marlin.h"
#include "../../../module/motion.h"
#include "../../../module/temperature.h"
#include "../../../feature/pause.h"
#if EXTRUDERS > 1
#include "../../../module/tool_change.h"
+4 -1
View File
@@ -340,7 +340,10 @@ public:
static void process_subcommands_now_P(PGM_P pgcode);
static void process_subcommands_now(char * gcode);
static inline void home_all_axes() { process_subcommands_now_P(PSTR("G28")); }
static inline void home_all_axes() {
extern const char G28_STR[];
process_subcommands_now_P(G28_STR);
}
#if ENABLED(HOST_KEEPALIVE_FEATURE)
/**
+1 -1
View File
@@ -77,7 +77,7 @@ void GcodeSuite::G92() {
#elif HAS_POSITION_SHIFT
if (i == E_AXIS) {
sync_E = true;
current_position.e = v; // When using coordinate spaces, only E is set directly
current_position.e = v; // When using coordinate spaces, only E is set directly
}
else {
position_shift[i] += d; // Other axes simply offset the coordinate space
+1 -1
View File
@@ -28,6 +28,6 @@
*/
void GcodeSuite::M119() {
endstops.M119();
endstops.report_states();
}
+3
View File
@@ -43,6 +43,9 @@ void GcodeSuite::M73() {
? parser.value_float() * (PROGRESS_SCALE)
: parser.value_byte()
);
#if BOTH(LCD_SET_PROGRESS_MANUALLY, USE_M73_REMAINING_TIME)
if (parser.seen('R')) ui.set_remaining_time(60 * parser.value_ulong());
#endif
}
#endif // LCD_SET_PROGRESS_MANUALLY
+1 -1
View File
@@ -44,7 +44,7 @@ void GcodeSuite::M76() {
* M77: Stop print timer
*/
void GcodeSuite::M77() {
print_job_timer.stop();
print_job_timer.stop();
}
#if ENABLED(PRINTCOUNTER)
+2 -2
View File
@@ -59,7 +59,7 @@ void GcodeSuite::M191() {
if (no_wait_for_cooling || parser.seenval('R')) {
thermalManager.setTargetChamber(parser.value_celsius());
#if ENABLED(PRINTJOB_TIMER_AUTOSTART)
if (parser.value_celsius() > BED_MINTEMP)
if (parser.value_celsius() > CHAMBER_MINTEMP)
startOrResumeJob();
#endif
}
@@ -67,7 +67,7 @@ void GcodeSuite::M191() {
const bool is_heating = thermalManager.isHeatingChamber();
if (is_heating || !no_wait_for_cooling) {
lcd_setstatusPGM(is_heating ? GET_TEXT(MSG_CHAMBER_HEATING) : GET_TEXT(MSG_CHAMBER_COOLING));
ui.set_status_P(is_heating ? GET_TEXT(MSG_CHAMBER_HEATING) : GET_TEXT(MSG_CHAMBER_COOLING));
thermalManager.wait_for_chamber(false);
}
}
+29 -17
View File
@@ -578,9 +578,13 @@
#define MINIMUM_STEPPER_PULSE 2
#elif HAS_DRIVER(A4988) || HAS_DRIVER(A5984)
#define MINIMUM_STEPPER_PULSE 1
#elif HAS_DRIVER(LV8729)
#define MINIMUM_STEPPER_PULSE 0
#elif TRINAMICS
#if ENABLED(LIN_ADVANCE) && (HAS_TMC_STANDALONE_E_DRIVER || (HAS_TMC_E_DRIVER && DISABLED(SQUARE_WAVE_STEPPING)))
#define MINIMUM_STEPPER_PULSE 1
#else
#define MINIMUM_STEPPER_PULSE 0
#endif
#elif HAS_DRIVER(LV8729)
#define MINIMUM_STEPPER_PULSE 0
#else
#define MINIMUM_STEPPER_PULSE 2
@@ -1017,7 +1021,7 @@
#define HAS_TEMP_ADC_BED HAS_ADC_TEST(BED)
#define HAS_TEMP_ADC_CHAMBER HAS_ADC_TEST(CHAMBER)
#define HAS_TEMP_HOTEND (HAS_TEMP_ADC_0 || ENABLED(HEATER_0_USES_MAX6675))
#define HAS_TEMP_HOTEND (HOTENDS > 0 && (HAS_TEMP_ADC_0 || ENABLED(HEATER_0_USES_MAX6675)))
#define HAS_TEMP_BED HAS_TEMP_ADC_BED
#define HAS_TEMP_CHAMBER HAS_TEMP_ADC_CHAMBER
#define HAS_HEATED_CHAMBER (HAS_TEMP_CHAMBER && PIN_EXISTS(HEATER_CHAMBER))
@@ -1302,8 +1306,15 @@
/**
* MIN/MAX fan PWM scaling
*/
#ifndef FAN_OFF_PWM
#define FAN_OFF_PWM 0
#endif
#ifndef FAN_MIN_PWM
#define FAN_MIN_PWM 0
#if FAN_OFF_PWM > 0
#define FAN_MIN_PWM (FAN_OFF_PWM + 1)
#else
#define FAN_MIN_PWM 0
#endif
#endif
#ifndef FAN_MAX_PWM
#define FAN_MAX_PWM 255
@@ -1314,6 +1325,8 @@
#error "FAN_MAX_PWM must be a value from 0 to 255."
#elif FAN_MIN_PWM > FAN_MAX_PWM
#error "FAN_MIN_PWM must be less than or equal to FAN_MAX_PWM."
#elif FAN_OFF_PWM > FAN_MIN_PWM
#error "FAN_OFF_PWM must be less than or equal to FAN_MIN_PWM."
#endif
/**
@@ -1354,6 +1367,9 @@
#define XY_PROBE_SPEED 4000
#endif
#endif
#ifndef NOZZLE_TO_PROBE_OFFSET
#define NOZZLE_TO_PROBE_OFFSET { 0, 0, 0 }
#endif
#else
#undef NOZZLE_TO_PROBE_OFFSET
#endif
@@ -1464,18 +1480,14 @@
#define MIN_PROBE_EDGE_BACK MIN_PROBE_EDGE
#endif
#ifndef NOZZLE_TO_PROBE_OFFSET
#define NOZZLE_TO_PROBE_OFFSET { 0, 0, 0 }
#endif
#if ENABLED(DELTA)
/**
* Delta radius/rod trimmers/angle trimmers
*/
#define _PROBE_RADIUS (DELTA_PRINTABLE_RADIUS - (MIN_PROBE_EDGE))
#ifndef DELTA_CALIBRATION_RADIUS
#ifdef NOZZLE_TO_PROBE_OFFSET
#define DELTA_CALIBRATION_RADIUS (DELTA_PRINTABLE_RADIUS - _MAX(ABS(nozzle_to_probe_offset.x), ABS(nozzle_to_probe_offset.y), ABS(MIN_PROBE_EDGE)))
#if HAS_BED_PROBE
#define DELTA_CALIBRATION_RADIUS (DELTA_PRINTABLE_RADIUS - _MAX(ABS(probe_offset.x), ABS(probe_offset.y), ABS(MIN_PROBE_EDGE)))
#else
#define DELTA_CALIBRATION_RADIUS _PROBE_RADIUS
#endif
@@ -1530,16 +1542,16 @@
#define _MESH_MAX_Y (Y_MAX_BED - (MESH_INSET))
#else
// Boundaries for Cartesian probing based on set limits
#if EITHER(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL)
#if ANY(MESH_BED_LEVELING, AUTO_BED_LEVELING_UBL, PROBE_MANUALLY)
#define _MESH_MIN_X (_MAX(X_MIN_BED + MESH_INSET, X_MIN_POS)) // UBL is careful not to probe off the bed. It does not
#define _MESH_MIN_Y (_MAX(Y_MIN_BED + MESH_INSET, Y_MIN_POS)) // need NOZZLE_TO_PROBE_OFFSET in the mesh dimensions
#define _MESH_MAX_X (_MIN(X_MAX_BED - (MESH_INSET), X_MAX_POS))
#define _MESH_MAX_Y (_MIN(Y_MAX_BED - (MESH_INSET), Y_MAX_POS))
#else
#define _MESH_MIN_X (_MAX(X_MIN_BED + MESH_INSET, X_MIN_POS + nozzle_to_probe_offset.x))
#define _MESH_MIN_Y (_MAX(Y_MIN_BED + MESH_INSET, Y_MIN_POS + nozzle_to_probe_offset.y))
#define _MESH_MAX_X (_MIN(X_MAX_BED - (MESH_INSET), X_MAX_POS + nozzle_to_probe_offset.x))
#define _MESH_MAX_Y (_MIN(Y_MAX_BED - (MESH_INSET), Y_MAX_POS + nozzle_to_probe_offset.y))
#define _MESH_MIN_X (_MAX(X_MIN_BED + MESH_INSET, X_MIN_POS + probe_offset.x))
#define _MESH_MIN_Y (_MAX(Y_MIN_BED + MESH_INSET, Y_MIN_POS + probe_offset.y))
#define _MESH_MAX_X (_MIN(X_MAX_BED - (MESH_INSET), X_MAX_POS + probe_offset.x))
#define _MESH_MAX_Y (_MIN(Y_MAX_BED - (MESH_INSET), Y_MAX_POS + probe_offset.y))
#endif
#endif
@@ -1559,8 +1571,8 @@
#endif // MESH_BED_LEVELING || AUTO_BED_LEVELING_UBL
#if ALL(PROBE_PT_1_X, PROBE_PT_2_X, PROBE_PT_3_X, PROBE_PT_1_Y, PROBE_PT_2_Y, PROBE_PT_3_Y)
#define HAS_FIXED_3POINT;
#if (defined(PROBE_PT_1_X) && defined(PROBE_PT_2_X) && defined(PROBE_PT_3_X) && defined(PROBE_PT_1_Y) && defined(PROBE_PT_2_Y) && defined(PROBE_PT_3_Y))
#define HAS_FIXED_3POINT
#endif
#if EITHER(AUTO_BED_LEVELING_UBL, AUTO_BED_LEVELING_3POINT) && IS_KINEMATIC
-1
View File
@@ -36,7 +36,6 @@
#include "../core/macros.h"
#include "../../Configuration.h"
#ifdef CUSTOM_VERSION_FILE
#if defined(__has_include)
#if __has_include(XSTR(../../CUSTOM_VERSION_FILE))
+14 -2
View File
@@ -408,6 +408,8 @@
#error "Z_STEPPER_ALIGN_X and Z_STEPPER_ALIGN_Y are now combined as Z_STEPPER_ALIGN_XY. Please update your Configuration_adv.h."
#elif defined(JUNCTION_DEVIATION)
#error "JUNCTION_DEVIATION is no longer required. (See CLASSIC_JERK). Please remove it from Configuration.h."
#elif defined(BABYSTEP_MULTIPLICATOR)
#error "BABYSTEP_MULTIPLICATOR is now BABYSTEP_MULTIPLICATOR_[XY|Z]. Please update Configuration_adv.h."
#endif
#define BOARD_MKS_13 -1000
@@ -596,8 +598,10 @@ static_assert(Y_MAX_LENGTH >= Y_BED_SIZE, "Movement bounds (Y_MIN_POS, Y_MAX_POS
/**
* Custom Boot and Status screens
*/
#if EITHER(SHOW_CUSTOM_BOOTSCREEN, CUSTOM_STATUS_SCREEN_IMAGE) && !HAS_GRAPHICAL_LCD
#error "Graphical LCD is required for SHOW_CUSTOM_BOOTSCREEN and CUSTOM_STATUS_SCREEN_IMAGE."
#if ENABLED(SHOW_CUSTOM_BOOTSCREEN) && !HAS_GRAPHICAL_LCD && !ENABLED(LULZBOT_TOUCH_UI)
#error "SHOW_CUSTOM_BOOTSCREEN requires Graphical LCD or LULZBOT_TOUCH_UI."
#elif ENABLED(CUSTOM_STATUS_SCREEN_IMAGE) && !HAS_GRAPHICAL_LCD
#error "CUSTOM_STATUS_SCREEN_IMAGE requires a Graphical LCD."
#endif
/**
@@ -2542,3 +2546,11 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#error "SHOW_REMAINING_TIME currently requires a Graphical LCD."
#endif
#endif
#if ENABLED(LIN_ADVANCE) && MINIMUM_STEPPER_PULSE < 1
#if HAS_TMC_STANDALONE_E_DRIVER
#error "LIN_ADVANCE with TMC standalone driver on extruder requires MIMIMUM_STEPPER_PULSE >= 1"
#elif HAS_TMC_E_DRIVER && DISABLED(SQUARE_WAVE_STEPPING)
#error "LIN_ADVANCE with TMC driver on extruder requires SQUARE_WAVE_STEPPING or MINIMUM_STEPPER_PULSE >= 1"
#endif
#endif
+1 -1
View File
@@ -42,7 +42,7 @@
* version was tagged.
*/
#ifndef STRING_DISTRIBUTION_DATE
#define STRING_DISTRIBUTION_DATE "2019-10-25"
#define STRING_DISTRIBUTION_DATE "2019-11-17"
#endif
/**
+58 -29
View File
@@ -111,6 +111,12 @@ static void createChar_P(const char c, const byte * const ptr) {
#define LCD_STR_PROGRESS "\x03\x04\x05"
#endif
#if ENABLED(LCD_USE_I2C_BUZZER)
void MarlinUI::buzz(const long duration, const uint16_t freq) {
lcd.buzz(duration, freq);
}
#endif
void MarlinUI::set_custom_characters(const HD44780CharSet screen_charset/*=CHARSET_INFO*/) {
#if NONE(LCD_PROGRESS_BAR, SHOW_BOOTSCREEN)
UNUSED(screen_charset);
@@ -464,7 +470,8 @@ void MarlinUI::clear_lcd() { lcd.clear(); }
// Show the Marlin logo and short build version
// After a delay show the website URL
//
logo_lines(PSTR(""));
extern const char NUL_STR[];
logo_lines(NUL_STR);
CENTER_OR_SCROLL(SHORT_BUILD_VERSION, 1500);
CENTER_OR_SCROLL(MARLIN_WEBSITE_URL, 1500);
#ifdef STRING_SPLASH_LINE3
@@ -815,14 +822,28 @@ void MarlinUI::draw_status_screen() {
sprintf_P(mixer_messages, PSTR("%s %d;%d%% "), mix_label, int(mixer.mix[0]), int(mixer.mix[1]));
lcd_put_u8str(mixer_messages);
#else
#else // !DUAL_MIXING_EXTRUDER
xy_pos_t lpos = current_position; toLogical(lpos);
_draw_axis_value(X_AXIS, ftostr4sign(lpos.x), blink);
lcd_put_wchar(' ');
_draw_axis_value(Y_AXIS, ftostr4sign(lpos.y), blink);
if (true
#if ENABLED(LCD_SHOW_E_TOTAL)
&& !printingIsActive()
#endif
) {
xy_pos_t lpos = current_position; toLogical(lpos);
_draw_axis_value(X_AXIS, ftostr4sign(lpos.x), blink);
lcd_put_wchar(' ');
_draw_axis_value(Y_AXIS, ftostr4sign(lpos.y), blink);
}
else {
#if ENABLED(LCD_SHOW_E_TOTAL)
char tmp[20];
const uint8_t escale = e_move_accumulator >= 100000.0f ? 10 : 1; // After 100m switch to cm
sprintf_P(tmp, PSTR("E %ld%cm "), uint32_t(_MAX(e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
lcd_put_u8str(tmp);
#endif
}
#endif
#endif // !DUAL_MIXING_EXTRUDER
#endif // HOTENDS <= 2 && (HOTENDS <= 1 || !HAS_HEATED_BED)
@@ -977,49 +998,55 @@ void MarlinUI::draw_status_screen() {
#endif // ADVANCED_PAUSE_FEATURE
void draw_menu_item_static(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const valstr/*=nullptr*/) {
// Draw a static item with no left-right margin required. Centered by default.
void MenuItem_static::draw(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const valstr/*=nullptr*/) {
int8_t n = LCD_WIDTH;
lcd_moveto(0, row);
if ((style & SS_CENTER) && !valstr) {
int8_t pad = (LCD_WIDTH - utf8_strlen_P(pstr)) / 2;
while (--pad >= 0) { lcd_put_wchar(' '); n--; }
}
n -= lcd_put_u8str_max_P(pstr, n);
n = lcd_put_u8str_ind_P(pstr, itemIndex, n);
if (valstr) n -= lcd_put_u8str_max(valstr, n);
for (; n > 0; --n) lcd_put_wchar(' ');
}
void draw_menu_item(const bool sel, const uint8_t row, PGM_P pstr, const char pre_char, const char post_char) {
uint8_t n = LCD_WIDTH - 2;
// Draw a generic menu item with pre_char (if selected) and post_char
void MenuItemBase::_draw(const bool sel, const uint8_t row, PGM_P const pstr, const char pre_char, const char post_char) {
lcd_put_wchar(0, row, sel ? pre_char : ' ');
n -= lcd_put_u8str_max_P(pstr, n);
uint8_t n = lcd_put_u8str_ind_P(pstr, itemIndex, LCD_WIDTH - 2);
for (; n; --n) lcd_put_wchar(' ');
lcd_put_wchar(post_char);
}
void _draw_menu_item_edit(const bool sel, const uint8_t row, PGM_P pstr, const char* const data, const bool pgm) {
uint8_t n = LCD_WIDTH - 2 - (pgm ? utf8_strlen_P(data) : utf8_strlen(data));
// Draw a menu item with a (potentially) editable value
void MenuEditItemBase::draw(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) {
const uint8_t vlen = data ? (pgm ? utf8_strlen_P(data) : utf8_strlen(data)) : 0;
lcd_put_wchar(0, row, sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
n -= lcd_put_u8str_max_P(pstr, n);
lcd_put_wchar(':');
for (; n; --n) lcd_put_wchar(' ');
if (pgm) lcd_put_u8str_P(data); else lcd_put_u8str(data);
uint8_t n = lcd_put_u8str_ind_P(pstr, itemIndex, LCD_WIDTH - 2 - vlen);
if (vlen) {
lcd_put_wchar(':');
for (; n; --n) lcd_put_wchar(' ');
if (pgm) lcd_put_u8str_P(data); else lcd_put_u8str(data);
}
}
void draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) {
// Low-level draw_edit_screen can be used to draw an edit screen from anyplace
void MenuEditItemBase::draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) {
ui.encoder_direction_normal();
lcd_put_u8str_P(0, 1, pstr);
uint8_t n = lcd_put_u8str_ind_P(0, 1, pstr, itemIndex, LCD_WIDTH - 1);
if (value != nullptr) {
lcd_put_wchar(':');
int len = utf8_strlen(value);
const lcd_uint_t valrow = (utf8_strlen_P(pstr) + 1 + len + 1) > (LCD_WIDTH - 2) ? 2 : 1; // Value on the next row if it won't fit
lcd_put_wchar((LCD_WIDTH - 1) - (len + 1), valrow, ' '); // Right-justified, padded, add a leading space
const lcd_uint_t valrow = (n < len + 1) ? 2 : 1; // Value on the next row if it won't fit
lcd_put_wchar((LCD_WIDTH - 1) - (len + 1), valrow, ' '); // Right-justified, padded, leading space
lcd_put_u8str(value);
}
}
void draw_select_screen(PGM_P const yes, PGM_P const no, const bool yesno, PGM_P const pref, const char * const string, PGM_P const suff) {
// The Select Screen presents a prompt and two "buttons"
void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const bool yesno, PGM_P const pref, const char * const string/*=nullptr*/, PGM_P const suff/*=nullptr*/) {
ui.draw_select_screen_prompt(pref, string, suff);
SETCURSOR(0, LCD_HEIGHT - 1);
lcd_put_wchar(yesno ? ' ' : '['); lcd_put_u8str_P(no); lcd_put_wchar(yesno ? ' ' : ']');
@@ -1029,9 +1056,7 @@ void MarlinUI::draw_status_screen() {
#if ENABLED(SDSUPPORT)
void draw_sd_menu_item(const bool sel, const uint8_t row, PGM_P const pstr, CardReader &theCard, const bool isDir) {
UNUSED(pstr);
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) {
lcd_put_wchar(0, row, sel ? LCD_STR_ARROW_RIGHT[0] : ' ');
constexpr uint8_t maxlen = LCD_WIDTH - 2;
uint8_t n = maxlen - lcd_put_u8str_max(ui.scrolled_filename(theCard, maxlen, row, sel), maxlen);
@@ -1039,7 +1064,7 @@ void MarlinUI::draw_status_screen() {
lcd_put_wchar(isDir ? LCD_STR_FOLDER[0] : ' ');
}
#endif // SDSUPPORT
#endif
#if ENABLED(LCD_HAS_STATUS_INDICATORS)
@@ -1048,9 +1073,13 @@ void MarlinUI::draw_status_screen() {
static uint8_t ledsprev = 0;
uint8_t leds = 0;
if (thermalManager.degTargetBed() > 0) leds |= LED_A;
#if HAS_HEATED_BED
if (thermalManager.degTargetBed() > 0) leds |= LED_A;
#endif
if (thermalManager.degTargetHotend(0) > 0) leds |= LED_B;
#if HOTENDS
if (thermalManager.degTargetHotend(0) > 0) leds |= LED_B;
#endif
#if FAN_COUNT > 0
if (0
+55 -16
View File
@@ -298,8 +298,14 @@ FORCE_INLINE void _draw_heater_status(const heater_ind_t heater, const bool blin
// Homed and known, display constantly.
//
FORCE_INLINE void _draw_axis_value(const AxisEnum axis, const char *value, const bool blink) {
const uint8_t offs = (XYZ_SPACING) * axis;
lcd_put_wchar(X_LABEL_POS + offs, XYZ_BASELINE, 'X' + axis);
const AxisEnum a = (
#if ENABLED(LCD_SHOW_E_TOTAL)
axis == E_AXIS ? X_AXIS :
#endif
axis
);
const uint8_t offs = (XYZ_SPACING) * a;
lcd_put_wchar(X_LABEL_POS + offs, XYZ_BASELINE, axis_codes[axis]);
lcd_moveto(X_VALUE_POS + offs, XYZ_BASELINE);
if (blink)
lcd_put_u8str(value);
@@ -328,7 +334,11 @@ void MarlinUI::draw_status_screen() {
if (first_page) count_renders++;
#endif
static char xstring[5], ystring[5], zstring[8];
static char xstring[5
#if ENABLED(LCD_SHOW_E_TOTAL)
+ 7
#endif
], ystring[5], zstring[8];
#if ENABLED(FILAMENT_LCD_DISPLAY)
static char wstring[5], mstring[4];
#endif
@@ -357,6 +367,12 @@ void MarlinUI::draw_status_screen() {
#endif
#endif
const bool showxy = (true
#if ENABLED(LCD_SHOW_E_TOTAL)
&& !printingIsActive()
#endif
);
// At the first page, generate new display values
if (first_page) {
#if ANIM_HBC
@@ -372,10 +388,21 @@ void MarlinUI::draw_status_screen() {
#endif
heat_bits = new_bits;
#endif
const xyz_pos_t lpos = current_position.asLogical();
strcpy(xstring, ftostr4sign(lpos.x));
strcpy(ystring, ftostr4sign(lpos.y));
strcpy(zstring, ftostr52sp( lpos.z));
strcpy(zstring, ftostr52sp(lpos.z));
if (showxy) {
strcpy(xstring, ftostr4sign(lpos.x));
strcpy(ystring, ftostr4sign(lpos.y));
}
else {
#if ENABLED(LCD_SHOW_E_TOTAL)
const uint8_t escale = e_move_accumulator >= 100000.0f ? 10 : 1; // After 100m switch to cm
sprintf_P(xstring, PSTR("%ld%cm"), uint32_t(_MAX(e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
#endif
}
#if ENABLED(FILAMENT_LCD_DISPLAY)
strcpy(wstring, ftostr12ns(filwidth.measured_mm));
strcpy(mstring, i16tostr3(planner.volumetric_percent(parser.volumetric_enabled)));
@@ -415,7 +442,7 @@ void MarlinUI::draw_status_screen() {
));
}
#if BOTH(SHOW_REMAINING_TIME, ROTATE_PROGRESS_DISPLAY) // Tri-state progress display mode
progress_x_pos = _SD_INFO_X(strlen(progress_string));
progress_x_pos = _SD_INFO_X(strlen(progress_string) + 1);
#endif
#endif
}
@@ -428,19 +455,25 @@ void MarlinUI::draw_status_screen() {
#if ENABLED(SHOW_REMAINING_TIME)
if (!(ev & 0x3)) {
duration_t estimation = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress;
if (estimation.value == 0) {
uint32_t timeval = (0
#if BOTH(LCD_SET_PROGRESS_MANUALLY, USE_M73_REMAINING_TIME)
+ get_remaining_time()
#endif
);
if (!timeval) timeval = elapsed.value * (100 * (PROGRESS_SCALE) - progress) / progress;
if (!timeval) {
estimation_string[0] = '\0';
estimation_x_pos = _SD_INFO_X(0);
}
else {
duration_t estimation = timeval;
const bool has_days = (estimation.value >= 60*60*24L);
const uint8_t len = estimation.toDigital(estimation_string, has_days);
#if BOTH(DOGM_SD_PERCENT, ROTATE_PROGRESS_DISPLAY)
estimation_x_pos = _SD_INFO_X(len);
#else
estimation_x_pos = _SD_INFO_X(len + 1);
#endif
estimation_x_pos = _SD_INFO_X(len
#if !BOTH(DOGM_SD_PERCENT, ROTATE_PROGRESS_DISPLAY)
+ 1
#endif
);
}
}
#endif
@@ -692,8 +725,14 @@ void MarlinUI::draw_status_screen() {
#else
_draw_axis_value(X_AXIS, xstring, blink);
_draw_axis_value(Y_AXIS, ystring, blink);
if (showxy) {
_draw_axis_value(X_AXIS, xstring, blink);
_draw_axis_value(Y_AXIS, ystring, blink);
}
else {
_draw_axis_value(E_AXIS, xstring, true);
lcd_put_u8str_P(PSTR(" "));
}
#endif
@@ -59,6 +59,10 @@
#include "../../sd/cardreader.h"
#endif
#if ENABLED(LCD_SHOW_E_TOTAL)
#include "../../Marlin.h" // for printingIsActive
#endif
#define TEXT_MODE_LCD_WIDTH 16
#define BUFFER_WIDTH 256
@@ -660,7 +664,7 @@ void ST7920_Lite_Status_Screen::draw_status_message() {
#endif
}
void ST7920_Lite_Status_Screen::draw_position(const xyz_pos_t &pos, const bool position_known) {
void ST7920_Lite_Status_Screen::draw_position(const xyze_pos_t &pos, const bool position_known) {
char str[7];
set_ddram_address(DDRAM_LINE_4);
begin_data();
@@ -668,11 +672,25 @@ void ST7920_Lite_Status_Screen::draw_position(const xyz_pos_t &pos, const bool p
// If position is unknown, flash the labels.
const unsigned char alt_label = position_known ? 0 : (ui.get_blink() ? ' ' : 0);
write_byte(alt_label ? alt_label : 'X');
write_str(dtostrf(pos.x, -4, 0, str), 4);
if (true
#if ENABLED(LCD_SHOW_E_TOTAL)
&& !printingIsActive()
#endif
) {
write_byte(alt_label ? alt_label : 'X');
write_str(dtostrf(pos.x, -4, 0, str), 4);
write_byte(alt_label ? alt_label : 'Y');
write_str(dtostrf(pos.y, -4, 0, str), 4);
write_byte(alt_label ? alt_label : 'Y');
write_str(dtostrf(pos.y, -4, 0, str), 4);
}
else {
#if ENABLED(LCD_SHOW_E_TOTAL)
char tmp[15];
const uint8_t escale = e_move_accumulator >= 100000.0f ? 10 : 1; // After 100m switch to cm
sprintf_P(tmp, PSTR("E%-7ld%cm "), uint32_t(_MAX(e_move_accumulator, 0.0f)) / escale, escale == 10 ? 'c' : 'm'); // 1234567mm
write_str(tmp);
#endif
}
write_byte(alt_label ? alt_label : 'Z');
write_str(dtostrf(pos.z, -5, 1, str), 5);
@@ -87,7 +87,7 @@ class ST7920_Lite_Status_Screen {
static void draw_print_time(const duration_t &elapsed);
static void draw_feedrate_percentage(const uint16_t percentage);
static void draw_status_message();
static void draw_position(const xyz_pos_t &pos, bool position_known = true);
static void draw_position(const xyze_pos_t &pos, bool position_known = true);
static bool indicators_changed();
static bool position_changed();
+40 -44
View File
@@ -363,7 +363,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
}
// Draw a static line of text in the same idiom as a menu item
void draw_menu_item_static(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const valstr/*=nullptr*/) {
void MenuItem_static::draw(const uint8_t row, PGM_P const pstr, const uint8_t style/*=SS_DEFAULT*/, const char * const valstr/*=nullptr*/) {
if (mark_as_selected(row, style & SS_INVERT)) {
@@ -373,19 +373,16 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
int8_t pad = (LCD_WIDTH - utf8_strlen_P(pstr)) / 2;
while (--pad >= 0) { lcd_put_wchar(' '); n--; }
}
n -= lcd_put_u8str_max_P(pstr, n);
n = lcd_put_u8str_ind_P(pstr, itemIndex, LCD_WIDTH) * (MENU_FONT_WIDTH);
if (valstr) n -= lcd_put_u8str_max(valstr, n);
while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' ');
}
}
// Draw a generic menu item
void draw_menu_item(const bool sel, const uint8_t row, PGM_P const pstr, const char pre_char, const char post_char) {
UNUSED(pre_char);
void MenuItemBase::_draw(const bool sel, const uint8_t row, PGM_P const pstr, const char, const char post_char) {
if (mark_as_selected(row, sel)) {
u8g_uint_t n = (LCD_WIDTH - 2) * (MENU_FONT_WIDTH);
n -= lcd_put_u8str_max_P(pstr, n);
u8g_uint_t n = lcd_put_u8str_ind_P(pstr, itemIndex, LCD_WIDTH - 2) * (MENU_FONT_WIDTH);
while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' ');
lcd_put_wchar(LCD_PIXEL_WIDTH - (MENU_FONT_WIDTH), row_y2, post_char);
lcd_put_wchar(' ');
@@ -393,19 +390,20 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
}
// Draw a menu item with an editable value
void _draw_menu_item_edit(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) {
void MenuEditItemBase::draw(const bool sel, const uint8_t row, PGM_P const pstr, const char* const data, const bool pgm) {
if (mark_as_selected(row, sel)) {
const uint8_t vallen = (pgm ? utf8_strlen_P(data) : utf8_strlen((char*)data));
u8g_uint_t n = (LCD_WIDTH - 2 - vallen) * (MENU_FONT_WIDTH);
n -= lcd_put_u8str_max_P(pstr, n);
lcd_put_wchar(':');
while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' ');
lcd_moveto(LCD_PIXEL_WIDTH - (MENU_FONT_WIDTH) * vallen, row_y2);
if (pgm) lcd_put_u8str_P(data); else lcd_put_u8str((char*)data);
u8g_uint_t n = lcd_put_u8str_ind_P(pstr, itemIndex, LCD_WIDTH - 2 - vallen) * (MENU_FONT_WIDTH);
if (vallen) {
lcd_put_wchar(':');
while (n > MENU_FONT_WIDTH) n -= lcd_put_wchar(' ');
lcd_moveto(LCD_PIXEL_WIDTH - (MENU_FONT_WIDTH) * vallen, row_y2);
if (pgm) lcd_put_u8str_P(data); else lcd_put_u8str((char*)data);
}
}
}
void draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) {
void MenuEditItemBase::draw_edit_screen(PGM_P const pstr, const char* const value/*=nullptr*/) {
ui.encoder_direction_normal();
const u8g_uint_t labellen = utf8_strlen_P(pstr), vallen = utf8_strlen(value);
@@ -437,7 +435,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
// Assume the label is alpha-numeric (with a descender)
bool onpage = PAGE_CONTAINS(baseline - (EDIT_FONT_ASCENT - 1), baseline + EDIT_FONT_DESCENT);
if (onpage) lcd_put_u8str_P(0, baseline, pstr);
if (onpage) lcd_put_u8str_ind_P(0, baseline, pstr, itemIndex);
// If a value is included, print a colon, then print the value right-justified
if (value != nullptr) {
@@ -466,7 +464,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
if (inv) u8g.setColorIndex(1);
}
void draw_select_screen(PGM_P const yes, PGM_P const no, const bool yesno, PGM_P const pref, const char * const string, PGM_P const suff) {
void MenuItem_confirm::draw_select_screen(PGM_P const yes, PGM_P const no, const bool yesno, PGM_P const pref, const char * const string/*=nullptr*/, PGM_P const suff/*=nullptr*/) {
ui.draw_select_screen_prompt(pref, string, suff);
draw_boxed_string(1, LCD_HEIGHT - 1, no, !yesno);
draw_boxed_string(LCD_WIDTH - (utf8_strlen_P(yes) + 1), LCD_HEIGHT - 1, yes, yesno);
@@ -474,9 +472,7 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
#if ENABLED(SDSUPPORT)
void draw_sd_menu_item(const bool sel, const uint8_t row, PGM_P const pstr, CardReader &theCard, const bool isDir) {
UNUSED(pstr);
void MenuItem_sdbase::draw(const bool sel, const uint8_t row, PGM_P const, CardReader &theCard, const bool isDir) {
if (mark_as_selected(row, sel)) {
if (isDir) lcd_put_wchar(LCD_STR_FOLDER[0]);
constexpr uint8_t maxlen = LCD_WIDTH - 1;
@@ -578,20 +574,20 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
#if EITHER(BABYSTEP_ZPROBE_GFX_OVERLAY, MESH_EDIT_GFX_OVERLAY)
const unsigned char cw_bmp[] PROGMEM = {
B00000001,B11111100,B00000000,
B00000111,B11111111,B00000000,
B00001111,B00000111,B10000000,
B00001110,B00000001,B11000000,
B00000000,B00000001,B11000000,
B00000000,B11111110,B00000000,
B00000011,B11111111,B10000000,
B00000111,B11000111,B11000000,
B00000111,B00000001,B11100000,
B00000000,B00000000,B11100000,
B00001000,B00000000,B11100000,
B00011100,B00000000,B11100000,
B00111110,B00000000,B11100000,
B01111111,B00000000,B11100000,
B00011100,B00000000,B11100000,
B00000000,B00000000,B11110000,
B00000000,B00000000,B01110000,
B00000100,B00000000,B01110000,
B00001110,B00000000,B01110000,
B00011111,B00000000,B01110000,
B00111111,B10000000,B11110000,
B00001110,B00000000,B11100000,
B00001110,B00000001,B11000000,
B00000111,B10000011,B11000000,
B00001111,B00000001,B11100000,
B00000111,B11000111,B11000000,
B00000011,B11111111,B10000000,
B00000000,B11111110,B00000000
};
@@ -599,20 +595,20 @@ void MarlinUI::clear_lcd() { } // Automatically cleared by Picture Loop
const unsigned char ccw_bmp[] PROGMEM = {
B00000000,B11111110,B00000000,
B00000011,B11111111,B10000000,
B00000111,B10000011,B11000000,
B00001110,B00000001,B11000000,
B00000111,B11000111,B11000000,
B00001111,B00000001,B11100000,
B00001110,B00000000,B11100000,
B00011100,B00000000,B11100000,
B01111111,B00000000,B11100000,
B00111110,B00000000,B11100000,
B00011100,B00000000,B11100000,
B00001000,B00000000,B11100000,
B00111111,B10000000,B11110000,
B00011111,B00000000,B01110000,
B00001110,B00000000,B01110000,
B00000100,B00000000,B01110000,
B00000000,B00000000,B01110000,
B00000000,B00000000,B11110000,
B00000000,B00000000,B11100000,
B00000000,B00000001,B11000000,
B00001110,B00000001,B11000000,
B00001111,B00000111,B10000000,
B00000111,B11111111,B00000000,
B00000001,B11111100,B00000000
B00000111,B00000001,B11100000,
B00000111,B11000111,B11000000,
B00000011,B11111111,B10000000,
B00000000,B11111110,B00000000
};
const unsigned char up_arrow_bmp[] PROGMEM = {
@@ -68,7 +68,7 @@ class UIFlashStorage : private SPIFlash {
static void set_media_file_size(uint8_t slot, uint32_t size);
static uint32_t get_media_file_size(uint8_t slot);
static constexpr uint32_t delimiter = 0x4C554C5A; // 'LULZ'
static constexpr uint32_t delimiter = 0x4D524C4E; // 'MRLN'
public:
enum error_t {
SUCCESS,
@@ -1015,8 +1015,8 @@ template <class T> bool CLCD::CommandFifo::write(T data, uint16_t len) {
if (Command_Space < (len + padding)) {
#if ENABLED(TOUCH_UI_DEBUG)
SERIAL_ECHO_START();
SERIAL_ECHOPAIR("Waiting for ", len + padding,
" bytes in command queue, now free: ", Command_Space);
SERIAL_ECHOPAIR("Waiting for ", len + padding);
SERIAL_ECHOLNPAIR(" bytes in command queue, now free: ", Command_Space);
#endif
do {
Command_Space = mem_read_32(REG::CMDB_SPACE) & 0x0FFF;
@@ -197,6 +197,7 @@
#define SERIAL_ECHO_START()
#define SERIAL_ECHOLNPGM(str) Serial.println(F(str))
#define SERIAL_ECHOPGM(str) Serial.print(F(str))
#define SERIAL_ECHO_MSG(str) Serial.println(str)
#define SERIAL_ECHOLNPAIR(str, val) {Serial.print(F(str)); Serial.println(val);}
#define SERIAL_ECHOPAIR(str, val) {Serial.print(F(str)); Serial.print(val);}

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