diff --git a/Marlin/src/Marlin.cpp b/Marlin/src/Marlin.cpp index 167339ec6..b8c025536 100644 --- a/Marlin/src/Marlin.cpp +++ b/Marlin/src/Marlin.cpp @@ -730,11 +730,7 @@ void setup() { // Load data from EEPROM if available (or use defaults) // This also updates variables in the planner, elsewhere (void)settings.load(); - - #if ENABLED(PRINTCOUNTER) - print_job_timer.init(); - #endif - + #if HAS_M206_COMMAND // Initialize current position based on home_offset COPY(current_position, home_offset); @@ -747,6 +743,8 @@ void setup() { thermalManager.init(); // Initialize temperature loop + print_job_timer.init(); // Initial setup of print job timer + stepper.init(); // Initialize stepper, this enables interrupts! #if HAS_SERVOS diff --git a/Marlin/src/libs/stopwatch.cpp b/Marlin/src/libs/stopwatch.cpp index 29f84099a..cc9268645 100644 --- a/Marlin/src/libs/stopwatch.cpp +++ b/Marlin/src/libs/stopwatch.cpp @@ -20,21 +20,23 @@ * */ -#include "../Marlin.h" #include "stopwatch.h" -Stopwatch::Stopwatch() { - this->reset(); -} +#include "../inc/MarlinConfig.h" + +Stopwatch::State Stopwatch::state; +millis_t Stopwatch::accumulator; +millis_t Stopwatch::startTimestamp; +millis_t Stopwatch::stopTimestamp; bool Stopwatch::stop() { #if ENABLED(DEBUG_STOPWATCH) Stopwatch::debug(PSTR("stop")); #endif - if (this->isRunning() || this->isPaused()) { - this->state = STOPPED; - this->stopTimestamp = millis(); + if (isRunning() || isPaused()) { + state = STOPPED; + stopTimestamp = millis(); return true; } else return false; @@ -45,9 +47,9 @@ bool Stopwatch::pause() { Stopwatch::debug(PSTR("pause")); #endif - if (this->isRunning()) { - this->state = PAUSED; - this->stopTimestamp = millis(); + if (isRunning()) { + state = PAUSED; + stopTimestamp = millis(); return true; } else return false; @@ -58,12 +60,12 @@ bool Stopwatch::start() { Stopwatch::debug(PSTR("start")); #endif - if (!this->isRunning()) { - if (this->isPaused()) this->accumulator = this->duration(); - else this->reset(); + if (!isRunning()) { + if (isPaused()) accumulator = duration(); + else reset(); - this->state = RUNNING; - this->startTimestamp = millis(); + state = RUNNING; + startTimestamp = millis(); return true; } else return false; @@ -74,23 +76,23 @@ void Stopwatch::reset() { Stopwatch::debug(PSTR("reset")); #endif - this->state = STOPPED; - this->startTimestamp = 0; - this->stopTimestamp = 0; - this->accumulator = 0; + state = STOPPED; + startTimestamp = 0; + stopTimestamp = 0; + accumulator = 0; } bool Stopwatch::isRunning() { - return (this->state == RUNNING) ? true : false; + return (state == RUNNING) ? true : false; } bool Stopwatch::isPaused() { - return (this->state == PAUSED) ? true : false; + return (state == PAUSED) ? true : false; } millis_t Stopwatch::duration() { - return (((this->isRunning()) ? millis() : this->stopTimestamp) - - this->startTimestamp) / 1000UL + this->accumulator; + return (((isRunning()) ? millis() : stopTimestamp) + - startTimestamp) / 1000UL + accumulator; } #if ENABLED(DEBUG_STOPWATCH) diff --git a/Marlin/src/libs/stopwatch.h b/Marlin/src/libs/stopwatch.h index 4a1cdcfcf..c39288c29 100644 --- a/Marlin/src/libs/stopwatch.h +++ b/Marlin/src/libs/stopwatch.h @@ -23,11 +23,12 @@ #ifndef STOPWATCH_H #define STOPWATCH_H -#include "../core/types.h" - // Print debug messages with M111 S2 (Uses 156 bytes of PROGMEM) //#define DEBUG_STOPWATCH +#include "../core/macros.h" +#include "../core/types.h" + /** * @brief Stopwatch class * @details This class acts as a timer proving stopwatch functionality including @@ -41,21 +42,16 @@ class Stopwatch { PAUSED }; - Stopwatch::State state; - millis_t accumulator; - millis_t startTimestamp; - millis_t stopTimestamp; + static Stopwatch::State state; + static millis_t accumulator; + static millis_t startTimestamp; + static millis_t stopTimestamp; public: - /** - * @brief Class constructor - */ - Stopwatch(); - /** * @brief Initialize the stopwatch */ - inline void init() {} + FORCE_INLINE static void init() { reset(); } /** * @brief Stops the stopwatch @@ -63,56 +59,56 @@ class Stopwatch { * no timer is currently running. * @return true is method was successful */ - bool stop(); + static bool stop(); /** * @brief Pause the stopwatch - * @details Pauses the running timer, it will silently ignore the request if + * @details Pause the running timer, it will silently ignore the request if * no timer is currently running. * @return true is method was successful */ - bool pause(); + static bool pause(); /** - * @brief Starts the stopwatch - * @details Starts the timer, it will silently ignore the request if the + * @brief Start the stopwatch + * @details Start the timer, it will silently ignore the request if the * timer is already running. * @return true is method was successful */ - bool start(); + static bool start(); /** - * @brief Resets the stopwatch - * @details Resets all settings to their default values. + * @brief Reset the stopwatch + * @details Reset all settings to their default values. */ - void reset(); + static void reset(); /** - * @brief Checks if the timer is running - * @details Returns true if the timer is currently running, false otherwise. + * @brief Check if the timer is running + * @details Return true if the timer is currently running, false otherwise. * @return true if stopwatch is running */ - bool isRunning(); + static bool isRunning(); /** - * @brief Checks if the timer is paused - * @details Returns true if the timer is currently paused, false otherwise. + * @brief Check if the timer is paused + * @details Return true if the timer is currently paused, false otherwise. * @return true if stopwatch is paused */ - bool isPaused(); + static bool isPaused(); /** - * @brief Gets the running time - * @details Returns the total number of seconds the timer has been running. + * @brief Get the running time + * @details Return the total number of seconds the timer has been running. * @return the delta since starting the stopwatch */ - millis_t duration(); + static millis_t duration(); #ifdef DEBUG_STOPWATCH /** - * @brief Prints a debug message - * @details Prints a simple debug message "Stopwatch::function" + * @brief Print a debug message + * @details Print a simple debug message "Stopwatch::function" */ static void debug(const char func[]); diff --git a/Marlin/src/module/printcounter.cpp b/Marlin/src/module/printcounter.cpp index 32e4d8321..66c6f2fbc 100644 --- a/Marlin/src/module/printcounter.cpp +++ b/Marlin/src/module/printcounter.cpp @@ -22,74 +22,84 @@ #include "../inc/MarlinConfig.h" -#if ENABLED(PRINTCOUNTER) +#if DISABLED(PRINTCOUNTER) -#include "printcounter.h" +#include "../libs/stopwatch.h" +Stopwatch print_job_timer; // Global Print Job Timer instance +#else // PRINTCOUNTER + +#include "printcounter.h" #include "../Marlin.h" +PrintCounter print_job_timer; // Global Print Job Timer instance + +printStatistics PrintCounter::data; + +const PrintCounter::promdress PrintCounter::address = STATS_EEPROM_ADDRESS; + +const uint16_t PrintCounter::updateInterval = 10; +const uint16_t PrintCounter::saveInterval = 3600; +millis_t PrintCounter::lastDuration; +bool PrintCounter::loaded = false; + millis_t PrintCounter::deltaDuration() { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("deltaDuration")); + debug(PSTR("deltaDuration")); #endif - millis_t tmp = this->lastDuration; - this->lastDuration = this->duration(); - return this->lastDuration - tmp; -} - -bool PrintCounter::isLoaded() { - return this->loaded; + millis_t tmp = lastDuration; + lastDuration = duration(); + return lastDuration - tmp; } void PrintCounter::incFilamentUsed(double const &amount) { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("incFilamentUsed")); + debug(PSTR("incFilamentUsed")); #endif // Refuses to update data if object is not loaded - if (!this->isLoaded()) return; + if (!isLoaded()) return; - this->data.filamentUsed += amount; // mm + data.filamentUsed += amount; // mm } - void PrintCounter::initStats() { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("initStats")); + debug(PSTR("initStats")); #endif - this->loaded = true; - this->data = { 0, 0, 0, 0, 0.0 }; + loaded = true; + data = { 0, 0, 0, 0, 0.0 }; - this->saveStats(); - eeprom_write_byte((uint8_t *) this->address, 0x16); + saveStats(); + eeprom_write_byte((uint8_t*)address, 0x16); } void PrintCounter::loadStats() { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("loadStats")); + debug(PSTR("loadStats")); #endif // Checks if the EEPROM block is initialized - if (eeprom_read_byte((uint8_t *) this->address) != 0x16) this->initStats(); - else eeprom_read_block(&this->data, - (void *)(this->address + sizeof(uint8_t)), sizeof(printStatistics)); + if (eeprom_read_byte((uint8_t*)address) != 0x16) initStats(); + else eeprom_read_block(&data, + (void*)(address + sizeof(uint8_t)), sizeof(printStatistics)); - this->loaded = true; + loaded = true; } void PrintCounter::saveStats() { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("saveStats")); + debug(PSTR("saveStats")); #endif // Refuses to save data if object is not loaded - if (!this->isLoaded()) return; + if (!isLoaded()) return; // Saves the struct to EEPROM - eeprom_update_block(&this->data, - (void *)(this->address + sizeof(uint8_t)), sizeof(printStatistics)); + eeprom_update_block(&data, + (void*)(address + sizeof(uint8_t)), sizeof(printStatistics)); } void PrintCounter::showStats() { @@ -98,19 +108,19 @@ void PrintCounter::showStats() { SERIAL_PROTOCOLPGM(MSG_STATS); SERIAL_ECHOPGM("Prints: "); - SERIAL_ECHO(this->data.totalPrints); + SERIAL_ECHO(data.totalPrints); SERIAL_ECHOPGM(", Finished: "); - SERIAL_ECHO(this->data.finishedPrints); + SERIAL_ECHO(data.finishedPrints); SERIAL_ECHOPGM(", Failed: "); // Note: Removes 1 from failures with an active counter - SERIAL_ECHO(this->data.totalPrints - this->data.finishedPrints - - ((this->isRunning() || this->isPaused()) ? 1 : 0)); + SERIAL_ECHO(data.totalPrints - data.finishedPrints + - ((isRunning() || isPaused()) ? 1 : 0)); SERIAL_EOL(); SERIAL_PROTOCOLPGM(MSG_STATS); - duration_t elapsed = this->data.printTime; + duration_t elapsed = data.printTime; elapsed.toString(buffer); SERIAL_ECHOPGM("Total time: "); @@ -118,11 +128,11 @@ void PrintCounter::showStats() { #if ENABLED(DEBUG_PRINTCOUNTER) SERIAL_ECHOPGM(" ("); - SERIAL_ECHO(this->data.printTime); + SERIAL_ECHO(data.printTime); SERIAL_CHAR(')'); #endif - elapsed = this->data.longestPrint; + elapsed = data.longestPrint; elapsed.toString(buffer); SERIAL_ECHOPGM(", Longest job: "); @@ -130,7 +140,7 @@ void PrintCounter::showStats() { #if ENABLED(DEBUG_PRINTCOUNTER) SERIAL_ECHOPGM(" ("); - SERIAL_ECHO(this->data.longestPrint); + SERIAL_ECHO(data.longestPrint); SERIAL_CHAR(')'); #endif @@ -138,14 +148,14 @@ void PrintCounter::showStats() { SERIAL_PROTOCOLPGM(MSG_STATS); SERIAL_ECHOPGM("Filament used: "); - SERIAL_ECHO(this->data.filamentUsed / 1000); + SERIAL_ECHO(data.filamentUsed / 1000); SERIAL_CHAR('m'); SERIAL_EOL(); } void PrintCounter::tick() { - if (!this->isRunning()) return; + if (!isRunning()) return; static uint32_t update_last = millis(), eeprom_last = millis(); @@ -153,37 +163,37 @@ void PrintCounter::tick() { millis_t now = millis(); // Trying to get the amount of calculations down to the bare min - const static uint16_t i = this->updateInterval * 1000; + const static uint16_t i = updateInterval * 1000; if (now - update_last >= i) { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("tick")); + debug(PSTR("tick")); #endif - this->data.printTime += this->deltaDuration(); + data.printTime += deltaDuration(); update_last = now; } // Trying to get the amount of calculations down to the bare min - const static millis_t j = this->saveInterval * 1000; + const static millis_t j = saveInterval * 1000; if (now - eeprom_last >= j) { eeprom_last = now; - this->saveStats(); + saveStats(); } } // @Override bool PrintCounter::start() { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("start")); + debug(PSTR("start")); #endif - bool paused = this->isPaused(); + bool paused = isPaused(); if (super::start()) { if (!paused) { - this->data.totalPrints++; - this->lastDuration = 0; + data.totalPrints++; + lastDuration = 0; } return true; } @@ -194,17 +204,17 @@ bool PrintCounter::start() { // @Override bool PrintCounter::stop() { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("stop")); + debug(PSTR("stop")); #endif if (super::stop()) { - this->data.finishedPrints++; - this->data.printTime += this->deltaDuration(); + data.finishedPrints++; + data.printTime += deltaDuration(); - if (this->duration() > this->data.longestPrint) - this->data.longestPrint = this->duration(); + if (duration() > data.longestPrint) + data.longestPrint = duration(); - this->saveStats(); + saveStats(); return true; } else return false; @@ -213,11 +223,11 @@ bool PrintCounter::stop() { // @Override void PrintCounter::reset() { #if ENABLED(DEBUG_PRINTCOUNTER) - PrintCounter::debug(PSTR("stop")); + debug(PSTR("stop")); #endif super::reset(); - this->lastDuration = 0; + lastDuration = 0; } #if ENABLED(DEBUG_PRINTCOUNTER) @@ -231,12 +241,4 @@ void PrintCounter::reset() { } #endif - -PrintCounter print_job_timer = PrintCounter(); - -#else - -#include "../libs/stopwatch.h" -Stopwatch print_job_timer = Stopwatch(); - #endif // PRINTCOUNTER diff --git a/Marlin/src/module/printcounter.h b/Marlin/src/module/printcounter.h index 640d505c5..db6f74606 100644 --- a/Marlin/src/module/printcounter.h +++ b/Marlin/src/module/printcounter.h @@ -23,13 +23,20 @@ #ifndef PRINTCOUNTER_H #define PRINTCOUNTER_H -#include "../inc/MarlinConfig.h" #include "../libs/stopwatch.h" #include "../libs/duration_t.h" +#include "../inc/MarlinConfig.h" // Print debug messages with M111 S2 //#define DEBUG_PRINTCOUNTER +#if ENABLED(I2C_EEPROM) || ENABLED(SPI_EEPROM) + // round up address to next page boundary (assuming 32 byte pages) + #define STATS_EEPROM_ADDRESS 0x40 +#else + #define STATS_EEPROM_ADDRESS 0x32 +#endif + struct printStatistics { // 16 bytes (20 with real doubles) //const uint8_t magic; // Magic header, it will always be 0x16 uint16_t totalPrints; // Number of prints @@ -43,20 +50,20 @@ class PrintCounter: public Stopwatch { private: typedef Stopwatch super; - printStatistics data; + #if ENABLED(I2C_EEPROM) || ENABLED(SPI_EEPROM) || defined(CPU_32_BIT) + typedef uint32_t promdress; + #else + typedef uint16_t promdress; + #endif + + static printStatistics data; /** * @brief EEPROM address * @details Defines the start offset address where the data is stored. */ - #if ENABLED(I2C_EEPROM) || ENABLED(SPI_EEPROM) - // round up address to next page boundary (assuming 32 byte pages) - const uint32_t address = 0x40; - #elif defined(CPU_32_BIT) - const uint32_t address = 0x32; - #else - const uint16_t address = 0x32; - #endif + static const promdress address; + /** * @brief Interval in seconds between counter updates * @details This const value defines what will be the time between each @@ -65,7 +72,7 @@ class PrintCounter: public Stopwatch { * @note The max value for this option is 60(s), otherwise integer * overflow will happen. */ - const uint16_t updateInterval = 10; + static const uint16_t updateInterval; /** * @brief Interval in seconds between EEPROM saves @@ -73,114 +80,114 @@ class PrintCounter: public Stopwatch { * EEPROM save cycle, the development team recommends to set this value * no lower than 3600 secs (1 hour). */ - const uint16_t saveInterval = 3600; + static const uint16_t saveInterval; /** * @brief Timestamp of the last call to deltaDuration() - * @details Stores the timestamp of the last deltaDuration(), this is + * @details Store the timestamp of the last deltaDuration(), this is * required due to the updateInterval cycle. */ - millis_t lastDuration; + static millis_t lastDuration; /** - * @brief Stats were loaded from EERPROM + * @brief Stats were loaded from EEPROM * @details If set to true it indicates if the statistical data was already * loaded from the EEPROM. */ - bool loaded = false; + static bool loaded; protected: /** * @brief dT since the last call - * @details Returns the elapsed time in seconds since the last call, this is + * @details Return the elapsed time in seconds since the last call, this is * used internally for print statistics accounting is not intended to be a * user callable function. */ - millis_t deltaDuration(); + static millis_t deltaDuration(); public: /** * @brief Initialize the print counter */ - inline void init() { + static inline void init() { super::init(); - this->loadStats(); + loadStats(); } /** - * @brief Checks if Print Statistics has been loaded - * @details Returns true if the statistical data has been loaded. + * @brief Check if Print Statistics has been loaded + * @details Return true if the statistical data has been loaded. * @return bool */ - bool isLoaded(); + FORCE_INLINE static bool isLoaded() { return loaded; } /** - * @brief Increments the total filament used + * @brief Increment the total filament used * @details The total filament used counter will be incremented by "amount". * * @param amount The amount of filament used in mm */ - void incFilamentUsed(double const &amount); + static void incFilamentUsed(double const &amount); /** - * @brief Resets the Print Statistics - * @details Resets the statistics to zero and saves them to EEPROM creating + * @brief Reset the Print Statistics + * @details Reset the statistics to zero and saves them to EEPROM creating * also the magic header. */ - void initStats(); + static void initStats(); /** - * @brief Loads the Print Statistics - * @details Loads the statistics from EEPROM + * @brief Load the Print Statistics + * @details Load the statistics from EEPROM */ - void loadStats(); + static void loadStats(); /** - * @brief Saves the Print Statistics - * @details Saves the statistics to EEPROM + * @brief Save the Print Statistics + * @details Save the statistics to EEPROM */ - void saveStats(); + static void saveStats(); /** * @brief Serial output the Print Statistics * @details This function may change in the future, for now it directly * prints the statistical data to serial. */ - void showStats(); + static void showStats(); /** * @brief Return the currently loaded statistics * @details Return the raw data, in the same structure used internally */ - printStatistics getStats() { return this->data; } + static printStatistics getStats() { return data; } /** * @brief Loop function * @details This function should be called at loop, it will take care of * periodically save the statistical data to EEPROM and do time keeping. */ - void tick(); + static void tick(); /** * The following functions are being overridden */ - bool start(); - bool stop(); - void reset(); + static bool start(); + static bool stop(); + static void reset(); #if ENABLED(DEBUG_PRINTCOUNTER) /** - * @brief Prints a debug message - * @details Prints a simple debug message "PrintCounter::function" + * @brief Print a debug message + * @details Print a simple debug message */ static void debug(const char func[]); #endif }; -// Print Job Timer +// Global Print Job Timer instance #if ENABLED(PRINTCOUNTER) extern PrintCounter print_job_timer; #else