diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ed04e3..ca6bc14 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,7 @@ list(APPEND OSTD_SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/src/ostd/StringEditor.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ostd/String.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ostd/TextStyleParser.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/ostd/Time.cpp ${CMAKE_CURRENT_LIST_DIR}/src/ostd/Utils.cpp ) list(APPEND OGFX_SOURCE_FILES diff --git a/other/build.nr b/other/build.nr index eec1f49..c9ac2c6 100644 --- a/other/build.nr +++ b/other/build.nr @@ -1 +1 @@ -1905 +1907 diff --git a/src/ostd/Time.cpp b/src/ostd/Time.cpp new file mode 100644 index 0000000..8171692 --- /dev/null +++ b/src/ostd/Time.cpp @@ -0,0 +1,77 @@ +#include "Time.hpp" +#include "Utils.hpp" +#include + +namespace ostd +{ + StepTimer& StepTimer::create(double updatesPerSecond, StepTimer::Callback callback) + { + m_targetDt = 1.0 / updatesPerSecond; + m_callback = std::move(callback); + m_prevTime = Clock::now(); + m_accumulator = 0.0; + m_valid = true; + return *this; + } + + void StepTimer::update(void) + { + if (!m_valid) return; + + TimePoint currentTime = Clock::now(); + Duration frameDuration = currentTime - m_prevTime; + m_prevTime = currentTime; + + // Convert to seconds + double frameTime = std::chrono::duration(frameDuration).count(); + + // Clamp to prevent spiral of death (5 FPS minimum) + constexpr double MAX_FRAME_TIME = 0.2; + if (frameTime > MAX_FRAME_TIME) + frameTime = MAX_FRAME_TIME; + + m_accumulator += frameTime; + + while (m_accumulator >= m_targetDt) + { + m_callback(m_targetDt); + m_accumulator -= m_targetDt; + } + } + + void StepTimer::reset(void) + { + if (m_valid) + { + m_accumulator = 0.0; + m_prevTime = Clock::now(); + } + } + + + + // Utils + void Utils::sleep(uint32_t __time, eTimeUnits __unit) + { + switch (__unit) + { + case eTimeUnits::Seconds: + std::this_thread::sleep_for(std::chrono::seconds(__time)); + break; + case eTimeUnits::Milliseconds: + std::this_thread::sleep_for(std::chrono::milliseconds(__time)); + break; + case eTimeUnits::Microseconds: + std::this_thread::sleep_for(std::chrono::microseconds(__time)); + break; + case eTimeUnits::Nanoseconds: + std::this_thread::sleep_for(std::chrono::nanoseconds(__time)); + break; + default: break; + } + } + uint64_t Utils::getRunningTime_ms(void) + { + return std::chrono::duration_cast (std::chrono::system_clock::now().time_since_epoch()).count() - Utils::s_startTime_ms; + } +} diff --git a/src/ostd/Time.hpp b/src/ostd/Time.hpp new file mode 100644 index 0000000..18d2027 --- /dev/null +++ b/src/ostd/Time.hpp @@ -0,0 +1,185 @@ +#pragma once + +#include +#include +#include + +namespace ostd +{ + enum class eTimeUnits + { + Seconds = 0, + Milliseconds, + Microseconds, + Nanoseconds + }; + enum class eMonths + { + January = 0, + February, + March, + April, + May, + June, + July, + August, + September, + October, + November, + December + }; + + + template + class _Counter + { + public: + inline _Counter(void) { m_count = 200; m_current = 0; } + inline _Counter(T count, T step = 1) { m_count = count; m_current = 0; m_step = step; } + inline void setCount(T count) { m_count = count; m_counting = false; m_current = 0; } + inline T getCount(void) { return m_count; } + inline T getCurrent(void) { return m_current; }; + inline T getStep(void) { return m_step; } + inline void start(void) { m_current = 0; m_counting = true; } + inline void stop(void) { m_current = 0; m_counting = false; } + inline bool isDone(void) { return !m_counting; } + inline bool isCounting(void) { return m_counting; } + inline void update(void) + { + if (!m_counting) return; + m_current += m_step; + if (m_current > m_count) + stop(); + } + + private: + T m_current { 0 }; + T m_count { 200 }; + T m_step { 1 }; + bool m_counting { false }; + }; + + typedef _Counter Counter; + typedef _Counter FloatCounter; + typedef _Counter DoubleCounter; + + class OutputHandlerBase; + class Timer + { + public: + inline Timer(void) { m_started = false; m_current = 0; m_timeUnit = eTimeUnits::Nanoseconds; m_dest = nullptr; } + uint64_t start(bool print = true, String name = "", eTimeUnits timeUnit = eTimeUnits::Nanoseconds, OutputHandlerBase* __destination = nullptr); + uint64_t startCount(eTimeUnits timeUnit = eTimeUnits::Nanoseconds); + uint64_t end(bool print = true); + uint64_t endCount(bool stop = true); + + static uint64_t getEpoch(eTimeUnits timeUnit = eTimeUnits::Milliseconds); + + inline const String& getName(void) const { return m_name; } + inline uint64_t read(void) { if (!m_started) return 0; return endCount(false); } + + private: + bool m_started; + int64_t m_current; + eTimeUnits m_timeUnit; + String m_name; + OutputHandlerBase* m_dest; + }; + + class StepTimer + { + public: + using Callback = std::function; + using Clock = std::chrono::high_resolution_clock; + using TimePoint = Clock::time_point; + using Duration = Clock::duration; + + public: + StepTimer() = default; + inline StepTimer(double updatesPerSecond, Callback callback) { create(updatesPerSecond, callback); } + StepTimer& create(double updatesPerSecond, Callback callback); + void update(void); + void reset(void); + inline double getInterpolationAlpha(void) const { return m_valid && m_targetDt > 0.0 ? m_accumulator / m_targetDt : 0.0; } + inline void invalidate(void) { m_valid = false; } + inline bool isValid(void) const { return m_valid; } + + private: + TimePoint m_prevTime; + double m_targetDt { 0.0 }; + Callback m_callback { nullptr }; + double m_accumulator { 0.0 }; + bool m_valid { false }; + }; + + struct GameClock + { + public: + GameClock(void); + const float& start(void); + inline const float& getTimeOfDay(void) const { return m_timeOfDay; } + String asString(void); + void update(void); + + private: + String getFormattedTime(void); + String convertMonth(void); + + public: + uint8_t minutes; + uint8_t hours; + uint16_t days; + uint8_t months; + uint16_t years; + + private: + Timer m_rtClock; + float m_timeOfDay; + float m_totalSeconds; + }; + + class LocalTime + { + public: + String getFullString(bool include_date = true, bool include_time = true, bool day_name = true, bool month_as_name = true, bool include_seconds = true) const; + inline String getDateString(bool day_name = true, bool month_as_name = true) { return getFullString(true, false, day_name, month_as_name, false); } + inline String getTimeString(bool include_seconds = true) { return getFullString(false, true, false, false, include_seconds); } + int32_t hours(void) const; + int32_t minutes(void) const; + int32_t seconds(void) const; + int32_t day(void) const; + int32_t month(void) const; + int32_t year(void) const; + int32_t weekDay(void) const; + String shours(bool leading_zero = true) const; + String sminutes(bool leading_zero = true) const; + String sseconds(bool leading_zero = true) const; + String sday(bool leading_zero = true) const; + String smonth(bool leading_zero = true, bool month_name = true) const; + String syear(void) const; + String sWeekDay(bool day_name = true) const; + + protected: + virtual String monthToText(int32_t month) const; + virtual String weekDayToText(int32_t day) const; + }; + typedef LocalTime LocalTime_EN; + class LocalTime_IT : public LocalTime + { + protected: + String monthToText(int32_t month) const override; + String weekDayToText(int32_t day) const override; + }; + class LocalTime_ES : public LocalTime + { + protected: + String monthToText(int32_t month) const override; + String weekDayToText(int32_t day) const override; + }; + class LocalTime_DE : public LocalTime + { + protected: + String monthToText(int32_t month) const override; + String weekDayToText(int32_t day) const override; + }; +} diff --git a/src/ostd/Utils.cpp b/src/ostd/Utils.cpp index 075269d..6d7916b 100755 --- a/src/ostd/Utils.cpp +++ b/src/ostd/Utils.cpp @@ -14,7 +14,6 @@ #include #include #include -#include #include #define __get_local_time() \ @@ -687,29 +686,6 @@ namespace ostd str = str += c; return str; } - void Utils::sleep(uint32_t __time, eTimeUnits __unit) - { - switch (__unit) - { - case eTimeUnits::Seconds: - std::this_thread::sleep_for(std::chrono::seconds(__time)); - break; - case eTimeUnits::Milliseconds: - std::this_thread::sleep_for(std::chrono::milliseconds(__time)); - break; - case eTimeUnits::Microseconds: - std::this_thread::sleep_for(std::chrono::microseconds(__time)); - break; - case eTimeUnits::Nanoseconds: - std::this_thread::sleep_for(std::chrono::nanoseconds(__time)); - break; - default: break; - } - } - uint64_t Utils::getRunningTime_ms(void) - { - return std::chrono::duration_cast (std::chrono::system_clock::now().time_since_epoch()).count() - Utils::s_startTime_ms; - } float Utils::map_value(float input, float input_start, float input_end, float output_start, float output_end) { float slope = 1.0 * (output_end - output_start) / (input_end - input_start); diff --git a/src/ostd/Utils.hpp b/src/ostd/Utils.hpp index 7660533..b5585d1 100755 --- a/src/ostd/Utils.hpp +++ b/src/ostd/Utils.hpp @@ -5,162 +5,12 @@ #include #include #include +#include #include namespace ostd { - enum class eTimeUnits - { - Seconds = 0, - Milliseconds, - Microseconds, - Nanoseconds - }; - enum class eMonths - { - January = 0, - February, - March, - April, - May, - June, - July, - August, - September, - October, - November, - December - }; - - - template - class _Counter - { - public: - inline _Counter(void) { m_count = 200; m_current = 0; } - inline _Counter(T count, T step = 1) { m_count = count; m_current = 0; m_step = step; } - inline void setCount(T count) { m_count = count; m_counting = false; m_current = 0; } - inline T getCount(void) { return m_count; } - inline T getCurrent(void) { return m_current; }; - inline T getStep(void) { return m_step; } - inline void start(void) { m_current = 0; m_counting = true; } - inline void stop(void) { m_current = 0; m_counting = false; } - inline bool isDone(void) { return !m_counting; } - inline bool isCounting(void) { return m_counting; } - inline void update(void) - { - if (!m_counting) return; - m_current += m_step; - if (m_current > m_count) - stop(); - } - - private: - T m_current { 0 }; - T m_count { 200 }; - T m_step { 1 }; - bool m_counting { false }; - }; - - typedef _Counter Counter; - typedef _Counter FloatCounter; - typedef _Counter DoubleCounter; - - class OutputHandlerBase; - class Timer - { - public: - inline Timer(void) { m_started = false; m_current = 0; m_timeUnit = eTimeUnits::Nanoseconds; m_dest = nullptr; } - uint64_t start(bool print = true, String name = "", eTimeUnits timeUnit = eTimeUnits::Nanoseconds, OutputHandlerBase* __destination = nullptr); - uint64_t startCount(eTimeUnits timeUnit = eTimeUnits::Nanoseconds); - uint64_t end(bool print = true); - uint64_t endCount(bool stop = true); - - static uint64_t getEpoch(eTimeUnits timeUnit = eTimeUnits::Milliseconds); - - inline const String& getName(void) const { return m_name; } - inline uint64_t read(void) { if (!m_started) return 0; return endCount(false); } - - private: - bool m_started; - int64_t m_current; - eTimeUnits m_timeUnit; - String m_name; - OutputHandlerBase* m_dest; - }; - - struct GameClock - { - public: - GameClock(void); - const float& start(void); - inline const float& getTimeOfDay(void) const { return m_timeOfDay; } - String asString(void); - void update(void); - - private: - String getFormattedTime(void); - String convertMonth(void); - - public: - uint8_t minutes; - uint8_t hours; - uint16_t days; - uint8_t months; - uint16_t years; - - private: - Timer m_rtClock; - float m_timeOfDay; - float m_totalSeconds; - }; - - class LocalTime - { - public: - String getFullString(bool include_date = true, bool include_time = true, bool day_name = true, bool month_as_name = true, bool include_seconds = true) const; - inline String getDateString(bool day_name = true, bool month_as_name = true) { return getFullString(true, false, day_name, month_as_name, false); } - inline String getTimeString(bool include_seconds = true) { return getFullString(false, true, false, false, include_seconds); } - int32_t hours(void) const; - int32_t minutes(void) const; - int32_t seconds(void) const; - int32_t day(void) const; - int32_t month(void) const; - int32_t year(void) const; - int32_t weekDay(void) const; - String shours(bool leading_zero = true) const; - String sminutes(bool leading_zero = true) const; - String sseconds(bool leading_zero = true) const; - String sday(bool leading_zero = true) const; - String smonth(bool leading_zero = true, bool month_name = true) const; - String syear(void) const; - String sWeekDay(bool day_name = true) const; - - protected: - virtual String monthToText(int32_t month) const; - virtual String weekDayToText(int32_t day) const; - }; - typedef LocalTime LocalTime_EN; - class LocalTime_IT : public LocalTime - { - protected: - String monthToText(int32_t month) const override; - String weekDayToText(int32_t day) const override; - }; - class LocalTime_ES : public LocalTime - { - protected: - String monthToText(int32_t month) const override; - String weekDayToText(int32_t day) const override; - }; - class LocalTime_DE : public LocalTime - { - protected: - String monthToText(int32_t month) const override; - String weekDayToText(int32_t day) const override; - }; - class Utils { public: @@ -175,8 +25,6 @@ namespace ostd static String getHexStr(uint64_t value, bool prefix = true, uint8_t nbytes = 1); static String getBinStr(uint64_t value, bool prefix = true, uint8_t nbytes = 1); static String duplicateChar(unsigned char c, uint16_t count); - static void sleep(uint32_t __time, eTimeUnits __unit = eTimeUnits::Milliseconds); - static uint64_t getRunningTime_ms(void); static float map_value(float input, float input_start, float input_end, float output_start, float output_end); static bool loadFileFromHppResource(String output_file_path, const char* resource_buffer, unsigned int size); static void printByteStream(const ByteStream& data, StreamIndex start, uint8_t line_len, uint16_t n_rows, OutputHandlerBase& out, int32_t addrHighlight = -1, uint32_t highlightRange = 1, const String& title = ""); @@ -185,6 +33,10 @@ namespace ostd static ByteStream stringToByteStream(const String& data); static String byteStreamToString(const ByteStream& data); + //Implemented in + static void sleep(uint32_t __time, eTimeUnits __unit = eTimeUnits::Milliseconds); + static uint64_t getRunningTime_ms(void); + //Implemented in static String md5(const String& str);