diff --git a/Marlin/Marlin.h b/Marlin/Marlin.h index 4864309c5..b1ea99285 100644 --- a/Marlin/Marlin.h +++ b/Marlin/Marlin.h @@ -44,12 +44,6 @@ #include "utility.h" #include "serial.h" -#if ENABLED(PRINTCOUNTER) - #include "printcounter.h" -#else - #include "stopwatch.h" -#endif - void idle( #if ENABLED(ADVANCED_PAUSE_FEATURE) bool no_stepper_sleep = false // pass true to keep steppers from disabling on timeout @@ -459,13 +453,6 @@ void report_current_position(); extern int lpq_len; #endif -// Print job timer -#if ENABLED(PRINTCOUNTER) - extern PrintCounter print_job_timer; -#else - extern Stopwatch print_job_timer; -#endif - // Handling multiple extruders pins extern uint8_t active_extruder; diff --git a/Marlin/Marlin_main.cpp b/Marlin/Marlin_main.cpp index a493ff780..9b564ab7d 100644 --- a/Marlin/Marlin_main.cpp +++ b/Marlin/Marlin_main.cpp @@ -260,6 +260,7 @@ #include "pins_arduino.h" #include "math.h" #include "nozzle.h" +#include "printcounter.h" #include "duration_t.h" #include "types.h" #include "gcode.h" @@ -515,13 +516,6 @@ millis_t previous_cmd_ms = 0; static millis_t max_inactive_time = 0; static millis_t stepper_inactive_time = (DEFAULT_STEPPER_DEACTIVE_TIME) * 1000UL; -// Print Job Timer -#if ENABLED(PRINTCOUNTER) - PrintCounter print_job_timer = PrintCounter(); -#else - Stopwatch print_job_timer = Stopwatch(); -#endif - // Auto Power Control #if ENABLED(AUTO_POWER_CONTROL) #define PSU_ON() powerManager.power_on() @@ -13703,6 +13697,8 @@ void setup() { thermalManager.init(); // Initialize temperature loop + print_job_timer.init(); // Initial setup of print job timer + #if ENABLED(USE_WATCHDOG) watchdog_init(); #endif diff --git a/Marlin/cardreader.cpp b/Marlin/cardreader.cpp index b07fd10e4..644bbe7fe 100644 --- a/Marlin/cardreader.cpp +++ b/Marlin/cardreader.cpp @@ -29,6 +29,7 @@ #include "ultralcd.h" #include "stepper.h" #include "language.h" +#include "printcounter.h" #define LONGEST_FILENAME (longFilename[0] ? longFilename : filename) diff --git a/Marlin/duration_t.h b/Marlin/duration_t.h index f38ab0224..bcc3011bb 100644 --- a/Marlin/duration_t.h +++ b/Marlin/duration_t.h @@ -23,6 +23,9 @@ #ifndef __DURATION_T__ #define __DURATION_T__ +#include +#include + struct duration_t { /** * @brief Duration is stored in seconds diff --git a/Marlin/printcounter.cpp b/Marlin/printcounter.cpp index 1b046edcb..25212cde4 100644 --- a/Marlin/printcounter.cpp +++ b/Marlin/printcounter.cpp @@ -22,100 +22,112 @@ #include "MarlinConfig.h" -#if ENABLED(PRINTCOUNTER) +#if DISABLED(PRINTCOUNTER) + +#include "stopwatch.h" +Stopwatch print_job_timer; // Global Print Job Timer instance + +#else // PRINTCOUNTER -#include "Marlin.h" #include "printcounter.h" #include "duration_t.h" +#include "Marlin.h" -PrintCounter::PrintCounter(): super() { - this->loadStats(); -} +PrintCounter print_job_timer; // Global Print Job Timer instance + +#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 + +const PrintCounter::promdress PrintCounter::address = STATS_EEPROM_ADDRESS; + +const uint16_t PrintCounter::updateInterval = 10; +const uint16_t PrintCounter::saveInterval = 3600; +printStatistics PrintCounter::data; +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() { char buffer[21]; - duration_t elapsed; 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); - elapsed = this->data.printTime; + duration_t elapsed = data.printTime; elapsed.toString(buffer); SERIAL_ECHOPGM("Total time: "); @@ -123,11 +135,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: "); @@ -135,7 +147,7 @@ void PrintCounter::showStats() { #if ENABLED(DEBUG_PRINTCOUNTER) SERIAL_ECHOPGM(" ("); - SERIAL_ECHO(this->data.longestPrint); + SERIAL_ECHO(data.longestPrint); SERIAL_CHAR(')'); #endif @@ -143,14 +155,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(); @@ -158,37 +170,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; } @@ -199,17 +211,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; @@ -218,11 +230,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) @@ -234,7 +246,6 @@ void PrintCounter::reset() { SERIAL_ECHOLNPGM("()"); } } - #endif #endif // PRINTCOUNTER diff --git a/Marlin/printcounter.h b/Marlin/printcounter.h index 0eeded9d5..89c61cb2e 100644 --- a/Marlin/printcounter.h +++ b/Marlin/printcounter.h @@ -23,15 +23,14 @@ #ifndef PRINTCOUNTER_H #define PRINTCOUNTER_H +// Print debug messages with M111 S2 +//#define DEBUG_PRINTCOUNTER + #include "macros.h" #include "language.h" #include "stopwatch.h" #include - -// Print debug messages with M111 S2 -//#define DEBUG_PRINTCOUNTER - 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 @@ -45,13 +44,19 @@ 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. */ - const uint16_t address = 0x32; + static const promdress address; /** * @brief Interval in seconds between counter updates @@ -61,7 +66,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 @@ -69,107 +74,118 @@ 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 Class constructor - */ - PrintCounter(); /** - * @brief Checks if Print Statistics has been loaded - * @details Returns true if the statistical data has been loaded. + * @brief Initialize the print counter + */ + static inline void init() { + super::init(); + loadStats(); + } + + /** + * @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 }; +// Global Print Job Timer instance +#if ENABLED(PRINTCOUNTER) + extern PrintCounter print_job_timer; +#else + extern Stopwatch print_job_timer; +#endif + #endif // PRINTCOUNTER_H diff --git a/Marlin/stopwatch.cpp b/Marlin/stopwatch.cpp index 5958000f7..e918265cd 100644 --- a/Marlin/stopwatch.cpp +++ b/Marlin/stopwatch.cpp @@ -20,21 +20,23 @@ * */ -#include "Marlin.h" #include "stopwatch.h" -Stopwatch::Stopwatch() { - this->reset(); -} +#include "Marlin.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/stopwatch.h b/Marlin/stopwatch.h index ae3c998fb..74eb72e8d 100644 --- a/Marlin/stopwatch.h +++ b/Marlin/stopwatch.h @@ -23,11 +23,12 @@ #ifndef STOPWATCH_H #define STOPWATCH_H -#include "macros.h" - // Print debug messages with M111 S2 (Uses 156 bytes of PROGMEM) //#define DEBUG_STOPWATCH +#include "macros.h" +#include "types.h" + /** * @brief Stopwatch class * @details This class acts as a timer proving stopwatch functionality including @@ -41,16 +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 + * @brief Initialize the stopwatch */ - Stopwatch(); + FORCE_INLINE static void init() { reset(); } /** * @brief Stops the stopwatch @@ -58,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(); - #if ENABLED(DEBUG_STOPWATCH) + #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/temperature.cpp b/Marlin/temperature.cpp index 2d0a294fb..e4dadceea 100644 --- a/Marlin/temperature.cpp +++ b/Marlin/temperature.cpp @@ -30,6 +30,7 @@ #include "ultralcd.h" #include "planner.h" #include "language.h" +#include "printcounter.h" #if ENABLED(HEATER_0_USES_MAX6675) #include "MarlinSPI.h" diff --git a/Marlin/tmc_util.cpp b/Marlin/tmc_util.cpp index 42ecf631f..ecd685335 100644 --- a/Marlin/tmc_util.cpp +++ b/Marlin/tmc_util.cpp @@ -26,6 +26,7 @@ #include "tmc_util.h" #include "Marlin.h" +#include "printcounter.h" #include "duration_t.h" #include "stepper_indirection.h" diff --git a/Marlin/ultralcd.cpp b/Marlin/ultralcd.cpp index 80f712fc0..790c1180c 100644 --- a/Marlin/ultralcd.cpp +++ b/Marlin/ultralcd.cpp @@ -39,8 +39,9 @@ #include "buzzer.h" #endif +#include "printcounter.h" + #if ENABLED(PRINTCOUNTER) - #include "printcounter.h" #include "duration_t.h" #endif