Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions Marlin/src/MarlinCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ PGMSTR(M112_KILL_STR, "M112 Shutdown");
KEEPALIVE_STATE(PAUSED_FOR_USER);
wait_start();
if (ms) ms += millis(); // expire time
while (wait_for_user && !(ms && ELAPSED(millis(), ms)))
const MTimeout24 expiration(ms);
while (wait_for_user && (!ms || expiration.pending()))
idle(TERN_(ADVANCED_PAUSE_FEATURE, no_sleep));
user_resume();
while (ui.button_pressed()) safe_delay(50);
Expand Down Expand Up @@ -484,9 +485,9 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {

#if ENABLED(PHOTO_GCODE) && PIN_EXISTS(CHDK)
// Check if CHDK should be set to LOW (after M240 set it HIGH)
extern millis_t chdk_timeout;
if (chdk_timeout && ELAPSED(ms, chdk_timeout)) {
chdk_timeout = 0;
extern TTimeout<uint16_t> chdk_timeout;
if (chdk_timeout.on_elapsed(ms)) {
chdk_timeout.cancel();
WRITE(CHDK_PIN, LOW);
}
#endif
Expand Down Expand Up @@ -531,10 +532,10 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
#if HAS_HOME
// Handle a standalone HOME button
constexpr millis_t HOME_DEBOUNCE_DELAY = 1000UL;
static millis_t next_home_key_ms; // = 0
static millis_t prev_home_key_ms; // = 0
if (!card.isStillPrinting() && !READ(HOME_PIN)) { // HOME_PIN goes LOW when pressed
if (ELAPSED(ms, next_home_key_ms)) {
next_home_key_ms = ms + HOME_DEBOUNCE_DELAY;
if (ELAPSED(ms, prev_home_key_ms, HOME_DEBOUNCE_DELAY)) {
prev_home_key_ms = ms;
LCD_MESSAGE(MSG_AUTO_HOME);
queue.inject_P(G28_STR);
}
Expand All @@ -547,13 +548,12 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
#define HAS_CUSTOM_USER_BUTTON(N) (PIN_EXISTS(BUTTON##N) && defined(BUTTON##N##_HIT_STATE) && defined(BUTTON##N##_GCODE))
#define HAS_BETTER_USER_BUTTON(N) HAS_CUSTOM_USER_BUTTON(N) && defined(BUTTON##N##_DESC)
#define _CHECK_CUSTOM_USER_BUTTON(N, CODE) do{ \
constexpr millis_t CUB_DEBOUNCE_DELAY_##N = 250UL; \
static millis_t next_cub_ms_##N; \
static millis_t prev_cub_ms_##N; \
if (BUTTON##N##_HIT_STATE == READ(BUTTON##N##_PIN) \
&& (ENABLED(BUTTON##N##_WHEN_PRINTING) || printer_not_busy) \
) { \
if (ELAPSED(ms, next_cub_ms_##N)) { \
next_cub_ms_##N = ms + CUB_DEBOUNCE_DELAY_##N; \
if (ELAPSED(ms, prev_cub_ms_##N, CUB_DEBOUNCE_DELAY_##N)) { \
prev_cub_ms_##N = ms; \
CODE; \
if (ENABLED(BUTTON##N##_IMMEDIATE)) \
gcode.process_subcommands_now(F(BUTTON##N##_GCODE)); \
Expand Down Expand Up @@ -698,6 +698,8 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {

TERN_(USE_CONTROLLER_FAN, controllerFan.update()); // Check if fan should be turned on to cool stepper drivers down

// Check for power needing to be turned on or off
// Send a bool to pause the power-off timer for ongoing activities
TERN_(AUTO_POWER_CONTROL, powerManager.check(!ui.on_status_screen() || printJobOngoing() || printingIsPaused()));

TERN_(HOTEND_IDLE_TIMEOUT, hotend_idle.check());
Expand Down Expand Up @@ -731,12 +733,11 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
#endif // EXTRUDER_RUNOUT_PREVENT

#if ENABLED(DUAL_X_CARRIAGE)
// handle delayed move timeout
if (motion.delayed_move_time && ELAPSED(ms, motion.delayed_move_time) && isRunning()) {
// travel moves have been received so enact them
motion.delayed_move_time = UINT32_MAX; // force moves to be done
// Add a delayed move when the proper time arrives, or always add it
if (motion.delayed_move_interval > 1 && IsRunning() && ELAPSED(ms, motion.delayed_move_start_ms, motion.delayed_move_interval)) {
motion.delayed_move_interval = 1; // Force moves to be done in dual_x_carriage_unpark
motion.destination = motion.position;
motion.prepare_line_to_destination();
motion.prepare_line_to_destination(); // Also calls dual_x_carriage_unpark
planner.synchronize();
}
#endif
Expand All @@ -746,16 +747,16 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
TERN_(MONITOR_DRIVER_STATUS, monitor_tmc_drivers());

// Limit check_axes_activity frequency to 10Hz
static millis_t next_check_axes_ms = 0;
if (ELAPSED(ms, next_check_axes_ms)) {
static millis_t prev_check_axes_ms = 0;
if (ELAPSED(ms, prev_check_axes_ms, 100UL)) {
planner.check_axes_activity();
next_check_axes_ms = ms + 100UL;
prev_check_axes_ms = ms;
}

#if PIN_EXISTS(FET_SAFETY)
static millis_t FET_next;
if (ELAPSED(ms, FET_next)) {
FET_next = ms + FET_SAFETY_DELAY; // 2µs pulse every FET_SAFETY_DELAY mS
static millis_t prev_FET = 0;
if (ELAPSED(ms, prev_FET, FET_SAFETY_DELAY)) { // 2µs pulse every FET_SAFETY_DELAY mS
prev_FET = ms;
OUT_WRITE(FET_SAFETY_PIN, !FET_SAFETY_INVERTED);
DELAY_US(2);
WRITE(FET_SAFETY_PIN, FET_SAFETY_INVERTED);
Expand All @@ -768,6 +769,9 @@ void Marlin::manage_inactivity(const bool no_stepper_sleep/*=false*/) {
#include "feature/babystep.h"
#endif

// For millis_t.h
void marlin_idle(const bool no_stepper_sleep/*=false*/) { marlin.idle(no_stepper_sleep); }

/**
* Standard idle routine keeps the machine alive:
* - Core Marlin activities
Expand Down Expand Up @@ -837,7 +841,7 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {

// Run StallGuard endstop checks
#if ENABLED(SPI_ENDSTOPS)
if (endstops.tmc_spi_homing.any && TERN1(IMPROVE_HOMING_RELIABILITY, ELAPSED(millis(), sg_guard_period)))
if (endstops.tmc_spi_homing.any && TERN1(IMPROVE_HOMING_RELIABILITY, ELAPSED(millis(), sg_guard_start_ms, default_sg_guard_duration)))
for (uint8_t i = 0; i < 4; ++i) if (endstops.tmc_spi_homing_check()) break; // Read SGT 4 times per idle loop
#endif

Expand Down Expand Up @@ -874,12 +878,12 @@ void Marlin::idle(const bool no_stepper_sleep/*=false*/) {
// Run i2c Position Encoders
#if ENABLED(I2C_POSITION_ENCODERS)
{
static millis_t i2cpem_next_update_ms;
static MTimeout24 i2c_encoder_timer;
if (planner.has_blocks_queued()) {
const millis_t ms = millis();
if (ELAPSED(ms, i2cpem_next_update_ms)) {
if (i2c_encoder_timer.elapsed(ms)) {
i2c_encoder_timer.start(I2CPE_MIN_UPD_TIME_MS, ms);
I2CPEM.update();
i2cpem_next_update_ms = ms + I2CPE_MIN_UPD_TIME_MS;
}
}
}
Expand Down Expand Up @@ -1194,29 +1198,25 @@ void setup() {
#define SETUP_RUN(C) do{ SETUP_LOG(STRINGIFY(C)); C; }while(0)

MYSERIAL1.begin(BAUDRATE);
millis_t serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL1.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
MTimeout24(1000).wait_until([]{ return MYSERIAL1.connected(); });

#if ENABLED(SOVOL_SV06_RTS)
LCD_SERIAL.begin(BAUDRATE);
serial_connect_timeout = millis() + 1000UL;
while (!LCD_SERIAL.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
MTimeout24(1000).wait_until([]{ return LCD_SERIAL.connected(); });
#endif

#if HAS_MULTI_SERIAL && !HAS_ETHERNET
#ifndef BAUDRATE_2
#define BAUDRATE_2 BAUDRATE
#endif
MYSERIAL2.begin(BAUDRATE_2);
serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL2.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
MTimeout24(1000).wait_until([]{ return MYSERIAL2.connected(); });
#ifdef SERIAL_PORT_3
#ifndef BAUDRATE_3
#define BAUDRATE_3 BAUDRATE
#endif
MYSERIAL3.begin(BAUDRATE_3);
serial_connect_timeout = millis() + 1000UL;
while (!MYSERIAL3.connected() && PENDING(millis(), serial_connect_timeout)) { /*nada*/ }
MTimeout24(1000).wait_until([]{ return MYSERIAL3.connected(); });
#endif
#endif
SERIAL_ECHOLNPGM("start");
Expand Down
106 changes: 105 additions & 1 deletion Marlin/src/core/millis_t.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
*/
#pragma once

#include <stdint.h>
#include "../HAL/shared/Marduino.h"

typedef uint32_t millis_t;

Expand All @@ -34,3 +34,107 @@ constexpr bool _PENDING(const millis_t now, const millis_t when) { return int32_
constexpr bool _PENDING(const millis_t now, const millis_t start, const millis_t interval) { return (now - start) < interval; }
#define PENDING(V...) _PENDING(V)
#define ELAPSED(V...) !_PENDING(V)

inline millis_t nz_millis() { const millis_t now = millis(); return now + !now; }
inline uint16_t millis16() { return uint16_t(millis()); }
inline uint16_t nz_millis16() { return uint16_t(nz_millis()); }

#define FI FORCE_INLINE

void marlin_idle(const bool no_stepper_sleep=false);

// A function to call continually the from run(fn) method
typedef void (*timeoutFunc_t)();

// Pass a test function to the wait_while(fn) / idle_while(fn) methods
typedef bool (*testFunc_t)();

// Single-use instant delay up to 65535 milliseconds. Example: TDelay<500> halfsec; halfsec.idle();
template<uint16_t DELAY_MS>
struct TDelay {
uint16_t start_ms;
TDelay(const uint16_t ms=millis16()) { prime(ms); }
FI void prime(const uint16_t ms=millis16()) { start_ms = millis16(); }
FI bool pending(const uint16_t ms=millis16()) const { return age() < DELAY_MS; }
FI bool elapsed(const uint16_t ms=millis16()) const { return age() >= DELAY_MS; }
FI void wait() const { while (pending()) { /* wait */ } }
FI void idle(const bool nss=false) const { while (pending()) marlin_idle(nss); }
FI void wait_while(testFunc_t fn) const { while (pending() && fn()) { /* wait */ }; }
FI void wait_until(testFunc_t fn) const { while (pending() && !fn()) { /* wait */ }; }
FI void idle_while(testFunc_t fn, const bool nss=false) const { while (pending() && fn()) marlin_idle(nss); }
FI void run(timeoutFunc_t fn) const { while (pending()) fn(); }
FI uint16_t age(const uint16_t ms=millis16()) const { return ms - start_ms; }
FI uint16_t remaining(const uint16_t ms=millis16()) const { return pending(ms) ? DELAY_MS - age() : 0; }
};

// Reusable timeout in milliseconds units up to 24 days of duration.
template<typename T=millis_t>
struct TTimeout24 {
T end_ms = 0;
TTimeout24() {}
TTimeout24(const T interval, const T ms=millis()) { start(interval, ms); }
FI void start(const T interval, const T ms=millis()) { end_ms = ms + interval; }
FI bool pending(const T ms=millis()) const { return _remaining() > 0; }
FI bool elapsed(const T ms=millis()) const { return _remaining() <= 0; }
FI void wait() const { while (pending()) { /* wait */ } }
FI void idle(const bool nss=false) const { while (pending()) marlin_idle(nss); }
FI void wait_while(testFunc_t fn) const { while (pending() && fn()) { /* wait */ }; }
FI void wait_until(testFunc_t fn) const { while (pending() && !fn()) { /* wait */ }; }
FI void idle_while(testFunc_t fn, const bool nss=false) const { while (pending() && fn()) marlin_idle(nss); }
FI void run(timeoutFunc_t fn) const { while (pending()) fn(); }
FI signed _remaining(const T ms=millis()) const { return end_ms - ms; }
FI T remaining(const T ms=millis()) const { return pending(ms) ? _remaining() : 0; }
};

// Reusable timeout in milliseconds units up to 48 days of duration.
template<typename T=millis_t>
struct TTimeout {
T start_ms = 0, delay_ms = 0;
TTimeout() {}
TTimeout(const T interval, const T ms=millis()) { start(interval, ms); }
FI void prime(const T ms=millis()) { start_ms = ms; }
FI void cancel() { delay_ms = 0; }
FI bool enabled() const { return delay_ms != 0; }
FI void start(const T interval, const T ms=millis()) { delay_ms = interval; prime(ms); }
FI bool pending(const T ms=millis()) const { return age() < delay_ms; }
FI bool elapsed(const T ms=millis()) const { return age() >= delay_ms; }
FI bool on_pending(const T ms=millis()) const { return enabled() && pending(ms); }
FI bool on_elapsed(const T ms=millis()) const { return enabled() && elapsed(ms); }
FI void wait() const { while (pending()) { /* wait */ } }
FI void idle(const bool nss=false) const { while (pending()) marlin_idle(nss); }
FI void wait_while(testFunc_t fn) const { while (pending() && fn()) { /* wait */ }; }
FI void wait_until(testFunc_t fn) const { while (pending() && !fn()) { /* wait */ }; }
FI void idle_while(testFunc_t fn, const bool nss=false) const { while (pending() && fn()) marlin_idle(nss); }
FI void run(timeoutFunc_t fn) const { while (on_pending()) fn(); }
FI T age(const T ms=millis()) const { return ms - start_ms; }
FI T remaining(const T ms=millis()) const { return on_pending(ms) ? delay_ms - age() : 0; }
};

// Reusable timeout in seconds units up to 48 days of duration.
template<typename T=millis_t>
struct TSeconds {
T start_ms = 0;
uint8_t delay_sec = 0;
TSeconds() {}
TSeconds(const T seconds, const T ms=millis()) { start(seconds, ms); }
FI void prime(const T ms=millis()) { start_ms = ms; }
FI void cancel() { delay_sec = 0; }
FI bool enabled() const { return delay_sec != 0; }
FI void start(const T seconds, const T ms=millis()) { delay_sec = seconds; prime(ms); }
FI bool pending(const T ms=millis()) const { return age() < delay_sec; }
FI bool elapsed(const T ms=millis()) const { return age() >= delay_sec; }
FI bool on_pending(const T ms=millis()) const { return enabled() && pending(ms); }
FI bool on_elapsed(const T ms=millis()) const { return enabled() && elapsed(ms); }
FI void wait() const { while (pending()) { /* wait */ } }
FI void idle(const bool nss=false) const { while (pending()) marlin_idle(nss); }
FI void wait_while(testFunc_t fn) const { while (pending() && fn()) { /* wait */ }; }
FI void wait_until(testFunc_t fn) const { while (pending() && !fn()) { /* wait */ }; }
FI void idle_while(testFunc_t fn, const bool nss=false) const { while (pending() && fn()) marlin_idle(nss); }
FI void run(timeoutFunc_t fn) const { while (on_pending()) fn(); }
FI uint8_t age(const T ms=millis()) const { return MS_TO_SEC(ms - start_ms); }
FI uint8_t remaining(const T ms=millis()) const { return on_pending(ms) ? delay_sec - age() : 0; }
};

typedef TTimeout24<> MTimeout24;
typedef TTimeout<> MTimeout;
typedef TSeconds<> MSeconds;
2 changes: 1 addition & 1 deletion Marlin/src/core/mstring.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,5 +318,5 @@ class MString {
#ifndef TS_SIZE
#define TS_SIZE 63
#endif
typedef MString<TS_SIZE, DISABLED(UNSAFE_MSTRING)> TString;
typedef MString<TS_SIZE> TString;
#define TS(V...) TString(V)
3 changes: 2 additions & 1 deletion Marlin/src/feature/binary_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@
#include "binary_stream.h"

char* SDFileTransferProtocol::Packet::Open::data = nullptr;
size_t SDFileTransferProtocol::data_waiting, SDFileTransferProtocol::transfer_timeout, SDFileTransferProtocol::idle_timeout;
size_t SDFileTransferProtocol::data_waiting;
TDelay<SDFileTransferProtocol::TIMEOUT> SDFileTransferProtocol::transfer_timeout;
bool SDFileTransferProtocol::transfer_active, SDFileTransferProtocol::dummy_transfer, SDFileTransferProtocol::compression;

BinaryStream binaryStream[NUM_SERIAL];
Expand Down
Loading
Loading