From 4ec13192f363b680188a843f4fb2374240ac90f8 Mon Sep 17 00:00:00 2001 From: Jaby Date: Tue, 10 Jan 2023 20:36:28 +0100 Subject: [PATCH] Support HighResolutionTimer in a better fashion --- include/PSX/System/IOPorts/timer_io.hpp | 8 ++- include/PSX/Timer/high_res_timer.hpp | 75 +++++++++++++++++++++++ include/PSX/Timer/timer.hpp | 45 -------------- src/Library/src/BootLoader/start_boot.cpp | 6 +- src/Library/src/BootLoader/timer_boot.cpp | 72 +++++++++------------- src/Library/src/Timer/high_res_timer.cpp | 38 ++++++++++++ src/Library/src/Timer/timer.cpp | 35 ----------- src/Library/src/startup.cpp | 2 - 8 files changed, 152 insertions(+), 129 deletions(-) create mode 100644 include/PSX/Timer/high_res_timer.hpp delete mode 100644 include/PSX/Timer/timer.hpp create mode 100644 src/Library/src/Timer/high_res_timer.cpp delete mode 100644 src/Library/src/Timer/timer.cpp diff --git a/include/PSX/System/IOPorts/timer_io.hpp b/include/PSX/System/IOPorts/timer_io.hpp index fc8db231..6866be98 100644 --- a/include/PSX/System/IOPorts/timer_io.hpp +++ b/include/PSX/System/IOPorts/timer_io.hpp @@ -29,8 +29,14 @@ namespace JabyEngine { static constexpr auto CounterTargetValue = BitRange::from_to(0, 15); }; + struct __no_align CounterValue : public ComplexBitMap { + __io_port_inherit_complex_bit_map(CounterValue); + + static constexpr auto Value = BitRange::from_to(0, 15); + }; + struct __no_align Counter { - IOPort value; + IOPort value; IOPort mode; IOPort target; private: diff --git a/include/PSX/Timer/high_res_timer.hpp b/include/PSX/Timer/high_res_timer.hpp new file mode 100644 index 00000000..cca49493 --- /dev/null +++ b/include/PSX/Timer/high_res_timer.hpp @@ -0,0 +1,75 @@ +#ifndef __JABYENGINE_HIGH_RES_TIMER_HPP__ +#define __JABYENGINE_HIGH_RES_TIMER_HPP__ +#include "../jabyengine_defines.h" +#include + +namespace JabyEngine { + struct CPUTicks { + static constexpr double Frequency_Hz = 33868800.0; + static constexpr double Frequency_Hz_Div8 = (Frequency_Hz/8.0); + + template + static constexpr T ticks_per_ns(double CPU_Frequency_Hz, double time = 1.0) { + return static_cast((time/CPU_Frequency_Hz)*1000.0*1000.0*1000.0); + } + + template + static constexpr T ticks_per_us(double CPU_Frequency_Hz, double time = 1.0) { + return static_cast(((time*1000.0)/ticks_per_ns(CPU_Frequency_Hz))); + } + + template + static constexpr T ticks_per_ms(double CPU_Frequency_Hz, double time = 1.0) { + return static_cast(((time*1000.0*1000.0)/ticks_per_ns(CPU_Frequency_Hz))); + } + }; + + #ifdef JABYENGINE_USE_HIGH_PERCISION_TIMER + class HighResTime { + public: + class TimeStamp { + private: + uint16_t counter_10ms_value; + uint16_t fraction; + + constexpr TimeStamp(uint16_t counter_10ms_value, uint16_t fraction) : counter_10ms_value(counter_10ms_value), fraction(fraction) { + } + + constexpr static size_t to_us(uint16_t counter_10ms_value, uint16_t fraction) { + return counter_10ms_value*(10*1000) + ((fraction/HighResTime::TicksFor100us)*100); + } + + constexpr static size_t to_ms(uint16_t counter_10ms_value, uint16_t fraction) { + return counter_10ms_value*10 + (fraction/HighResTime::TicksFor1ms); + } + + public: + constexpr size_t microseconds_to(const TimeStamp& end) const { + return TimeStamp::to_us((end.counter_10ms_value - this->counter_10ms_value), (end.fraction - this->fraction)); + } + + constexpr size_t milliseconds_to(const TimeStamp& end) const { + return TimeStamp::to_ms((end.counter_10ms_value - this->counter_10ms_value), (end.fraction - this->fraction)); + } + friend class HighResTime; + }; + + private: + static constexpr uint16_t TicksFor100us = CPUTicks::ticks_per_us(CPUTicks::Frequency_Hz_Div8, 100.0); + static constexpr uint16_t TicksFor1ms = CPUTicks::ticks_per_ms(CPUTicks::Frequency_Hz_Div8, 1.0); + static constexpr uint16_t TicksFor10ms = CPUTicks::ticks_per_ms(CPUTicks::Frequency_Hz_Div8, 10.0); + + static volatile uint16_t global_counter_10ms; + + public: + HighResTime() = delete; + ~HighResTime() = delete; + + static TimeStamp get_time_stamp() { + return TimeStamp(HighResTime::global_counter_10ms, Timer_IO::Counter2.value.read().get_value(Timer_IO::CounterValue::Value)); + } + }; + #endif //JABYENGINE_USE_HIGH_PERCISION_TIMER +} + +#endif //!__JABYENGINE_HIGH_RES_TIMER_HPP__ \ No newline at end of file diff --git a/include/PSX/Timer/timer.hpp b/include/PSX/Timer/timer.hpp deleted file mode 100644 index 7054b07f..00000000 --- a/include/PSX/Timer/timer.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef __JABYENGINE_TIMER_HPP__ -#define __JABYENGINE_TIMER_HPP__ -#include "../jabyengine_defines.h" - -namespace JabyEngine { - class GlobalTime { - public: - class TimeStamp { - private: - size_t value; - - constexpr TimeStamp(size_t value) : value(value) {} - - public: - #ifdef JABYENGINE_USE_HIGH_PERCISION_TIMER - constexpr size_t microseconds_to(const TimeStamp& ts) const { - return (ts.value - this->value)*100; - } - - constexpr size_t milliseconds_to(const TimeStamp& ts) const { - return microseconds_to(ts)/1000; - } - #else - constexpr size_t milliseconds_to(const TimeStamp& ts) const { - return (ts.value - this->value)*10; - } - #endif //JABYENGINE_USE_HIGH_PERCISION_TIMER - - friend class GlobalTime; - }; - - private: - static volatile size_t global_counter; - - public: - GlobalTime() = delete; - ~GlobalTime() = delete; - - static TimeStamp get_time_stamp() { - return TimeStamp(GlobalTime::global_counter); - } - }; -} - -#endif //!__JABYENGINE_TIMER_HPP__ \ No newline at end of file diff --git a/src/Library/src/BootLoader/start_boot.cpp b/src/Library/src/BootLoader/start_boot.cpp index 2836c153..f5864a3b 100644 --- a/src/Library/src/BootLoader/start_boot.cpp +++ b/src/Library/src/BootLoader/start_boot.cpp @@ -1,7 +1,7 @@ #include "BootLoader/boot_loader.hpp" #include -#include +#include #include namespace JabyEngine { @@ -16,11 +16,11 @@ namespace JabyEngine { SPU::stop_voices(); Timer::setup(); - const auto start = GlobalTime::get_time_stamp(); + const auto start = HighResTime::get_time_stamp(); printf("Start...\n"); GPU::setup(); GPU::display_logo(); - const auto end = GlobalTime::get_time_stamp(); + const auto end = HighResTime::get_time_stamp(); printf("GPU setup took %ims %ius\n", start.milliseconds_to(end), start.microseconds_to(end)); //Pause?? diff --git a/src/Library/src/BootLoader/timer_boot.cpp b/src/Library/src/BootLoader/timer_boot.cpp index 0a1ef7f8..4259ab65 100644 --- a/src/Library/src/BootLoader/timer_boot.cpp +++ b/src/Library/src/BootLoader/timer_boot.cpp @@ -1,51 +1,37 @@ -#include -#include -#include +#include +#ifdef JABYENGINE_USE_HIGH_PERCISION_TIMER + #include + #include + #define private public + #include + #undef private -#include -#include + namespace JabyEngine { + namespace Timer { + extern InterrupCallback IRQCallback; + void setup() { + using namespace Timer_IO; -namespace JabyEngine { - namespace Timer { - extern InterrupCallback IRQCallback; + static constexpr auto Mode = CounterMode::with(CounterMode::FreeRun, Counter2::SyncMode::Freerun, CounterMode::ResetAfterTarget, CounterMode::IRQAtTarget, CounterMode::IRQEveryTime, CounterMode::IRQPulse, Counter2::Source::System_Clock_Div_8); - static constexpr double CPU_Frequency_Hz = 33868800.0; - static constexpr double CPU_Frequency_Hz_Div8 = (CPU_Frequency_Hz/8.0); + Interrupt::disable_irq(Interrupt::Timer2); - template - static constexpr T NS_Per_Tick(double CPU_Frequency_Hz, double time = 1.0) { - return static_cast((time/CPU_Frequency_Hz)*1000.0*1000.0*1000.0); - } + __syscall_EnterCriticalSection(); + __syscall_SysEnqIntRP(Timer2Irq, &IRQCallback); + __syscall_ExitCriticalSection(); - template - static constexpr T US_Per_Tick(double CPU_Frequency_Hz, double time = 1.0) { - return static_cast(((time*1000.0)/NS_Per_Tick(CPU_Frequency_Hz))); - } + Counter2.target.write(CounterTarget::CounterTargetValue.with(HighResTime::TicksFor10ms)); + Counter2.mode.write(Mode); - template - static constexpr T MS_Per_Tick(double CPU_Frequency_Hz, double time = 1.0) { - return static_cast(((time*1000.0*1000.0)/NS_Per_Tick(CPU_Frequency_Hz))); - } - - void setup() { - using namespace Timer_IO; - - static constexpr auto Mode = CounterMode::with(CounterMode::FreeRun, Counter2::SyncMode::Freerun, CounterMode::ResetAfterTarget, CounterMode::IRQAtTarget, CounterMode::IRQEveryTime, CounterMode::IRQPulse, Counter2::Source::System_Clock_Div_8); - #ifdef JABYENGINE_USE_HIGH_PERCISION_TIMER - static constexpr uint16_t Target = US_Per_Tick(CPU_Frequency_Hz, 100.0); - #else - static constexpr uint16_t Target = MS_Per_Tick(CPU_Frequency_Hz_Div8, 10.0); - #endif //#ifdef JABYENGINE_USE_HIGH_PERCISION_TIMER - Interrupt::disable_irq(Interrupt::Timer2); - - __syscall_EnterCriticalSection(); - __syscall_SysEnqIntRP(Timer2Irq, &IRQCallback); - __syscall_ExitCriticalSection(); - - Counter2.target.write(CounterTarget::CounterTargetValue.with(Target)); - Counter2.mode.write(Mode); - - Interrupt::enable_irq(Interrupt::Timer2); + Interrupt::enable_irq(Interrupt::Timer2); + } } } -} \ No newline at end of file +#else + namespace JabyEngine { + namespace Timer { + void setup() { + } + } + } +#endif //JABYENGINE_USE_HIGH_PERCISION_TIMER \ No newline at end of file diff --git a/src/Library/src/Timer/high_res_timer.cpp b/src/Library/src/Timer/high_res_timer.cpp new file mode 100644 index 00000000..7a7fd3d9 --- /dev/null +++ b/src/Library/src/Timer/high_res_timer.cpp @@ -0,0 +1,38 @@ +#include +#ifdef JABYENGINE_USE_HIGH_PERCISION_TIMER + #define private public + #include + #include + #include + #include + #undef private + + namespace JabyEngine { + volatile uint16_t HighResTime :: global_counter_10ms = 0; + + namespace Timer { + static InterruptVerifierResult interrupt_verifier() { + if(Interrupt::is_irq(Interrupt::Timer2)) { + return InterruptVerifierResult::ExecuteHandler; + } + + else { + return InterruptVerifierResult::SkipHandler; + } + } + + static void interrupt_handler(uint32_t) { + HighResTime::global_counter_10ms = HighResTime::global_counter_10ms + 1; + + Interrupt::ack_irq(Interrupt::Timer2); + __syscall_ReturnFromException(); + } + + InterrupCallback IRQCallback = { + .next = nullptr, + .handler_function = reinterpret_cast(interrupt_handler), + .verifier_function = interrupt_verifier + }; + } + } +#endif //JABYENGINE_USE_HIGH_PERCISION_TIMER \ No newline at end of file diff --git a/src/Library/src/Timer/timer.cpp b/src/Library/src/Timer/timer.cpp deleted file mode 100644 index 4a9d5b78..00000000 --- a/src/Library/src/Timer/timer.cpp +++ /dev/null @@ -1,35 +0,0 @@ -#define private public -#include -#include -#include -#include -#undef private - -namespace JabyEngine { - volatile size_t GlobalTime :: global_counter = 0; - - namespace Timer { - static InterruptVerifierResult interrupt_verifier() { - if(Interrupt::is_irq(Interrupt::Timer2)) { - return InterruptVerifierResult::ExecuteHandler; - } - - else { - return InterruptVerifierResult::SkipHandler; - } - } - - static void interrupt_handler(uint32_t) { - GlobalTime::global_counter = GlobalTime::global_counter + 1; - - Interrupt::ack_irq(Interrupt::Timer2); - __syscall_ReturnFromException(); - } - - InterrupCallback IRQCallback = { - .next = nullptr, - .handler_function = reinterpret_cast(interrupt_handler), - .verifier_function = interrupt_verifier - }; - } -} \ No newline at end of file diff --git a/src/Library/src/startup.cpp b/src/Library/src/startup.cpp index bc016c9a..cfd0d651 100644 --- a/src/Library/src/startup.cpp +++ b/src/Library/src/startup.cpp @@ -1,8 +1,6 @@ #include "../include/BootLoader/boot_loader.hpp" #include -#include - namespace JabyEngine { static NextRoutine execute(NextRoutine routine) { // Support currently only direct call