#pragma once #include #include class FreqTimer { public: FreqTimer(); /* * Starts the timer if stopped */ void toggleStart(); /* * Timer is running */ [[nodiscard]] bool running() const { return _state == State::RUNNING; } /* * Timer has been started */ [[nodiscard]] bool started() const { return _state == State::RUNNING or _state == State::STOPPED; } /* * Current preset in ms */ [[nodiscard]] int64_t preset_ms() const noexcept { return _preset_ms; } /* * Whether the preset time has been exceeded */ [[nodiscard]] bool overtime() const { return time_ms() < 0; } /* * Reset the time */ void reset(); /* * Reset the time and preset */ void clear(); [[nodiscard]] std::string counter_display_value() const; /* * Lowest frequency which can be measured * in the interval (as measured in events/min * or multiples of 60 Hz) */ [[nodiscard]] double record_floor() const; [[nodiscard]] double overtime_record_floor() const; /* * Without a preset, the timer acts like a * stopwatch and counts freely from zero. * With a preset, the timer acts like a timer * counting down to zero, then counts up to * measure the number of seconds since the * timing has ended. */ [[nodiscard]] bool has_preset() const; /* * The current duration in milliseconds. * * If the timer has exceeded the preset, * this time will be negative. */ [[nodiscard]] int64_t time_ms() const; [[nodiscard]] uint64_t total_duration_ms() const; /* * Increment the timer's preset by the specified * amount (in milisec.) Subsequent calls between * timings increment the time. Incrementing a * timing after a timing has been restarted will * reset the timing and start from zero. */ void increment_preset_ms(uint64_t amount_ms); private: enum class State { // The timer initially starts in // "setting" mode and the preset // can be modified by incrementing // it by values (measured in seconds) // // Once it is started, this preset // is "sticky" and a reset returns // the timer to the preset value. // Incrementing the preset or clearing // the timer moves the timer back // into setting mode. SETTING, // Timer is active RUNNING, // Timer is temporarily stopped STOPPED, // Reset RESET, }; State _state; uint64_t _time_offset_ms; uint64_t _time_start_ms; int64_t _preset_ms; [[nodiscard]] uint64_t _duration_since_last_stop_ms() const; void _stop(); void _start(); };