From: <m97...@us...> - 2011-08-30 19:35:11
|
Revision: 12254 http://openmsx.svn.sourceforge.net/openmsx/?rev=12254&view=rev Author: m9710797 Date: 2011-08-30 19:35:05 +0000 (Tue, 30 Aug 2011) Log Message: ----------- Added DynamicClock::setFreq(num, denom) Added a method to set the frequency as a ratio. Compared to the existing setFreq() method which accepts an integer parameter, using this new method can result in less rounding errors. This new method will be used in the next patch. At the same time simplified the corresponding calculation in the Clock class. This calculation was still prepared to deal with 96-bit intermediate results (not needed anymore). This calculation was correct and it happened at compile time (so speed is not an issue). But it's nicer to use the same formula in both Clock (compile-time) and DynamicClock (run-time). Modified Paths: -------------- openmsx/trunk/src/Clock.hh openmsx/trunk/src/DynamicClock.hh Modified: openmsx/trunk/src/Clock.hh =================================================================== --- openmsx/trunk/src/Clock.hh 2011-08-29 19:28:35 UTC (rev 12253) +++ openmsx/trunk/src/Clock.hh 2011-08-30 19:35:05 UTC (rev 12254) @@ -17,23 +17,17 @@ * A clock has a current time, which can be increased by * an integer number of ticks. */ -template <unsigned FREQ_NOM, unsigned FREQ_DENOM = 1> +template <unsigned FREQ_NUM, unsigned FREQ_DENOM = 1> class Clock { private: // stuff below calculates: - // MASTER_TICKS = MAIN_FREQ / (FREQ_NOM / FREQ_DENOM) + 0.5 - // intermediate results are 96bit, that's why it's a bit complicated - static const unsigned long long P = - (MAIN_FREQ & 0xFFFFFFFF) * FREQ_DENOM + (FREQ_NOM / 2); - static const unsigned long long Q = - (MAIN_FREQ >> 32) * FREQ_DENOM + (P >> 32); - static const unsigned long long R1 = Q / FREQ_NOM; - static const unsigned long long R0 = - (((Q - (R1 * FREQ_NOM)) << 32) + (P & 0xFFFFFFFF)) / FREQ_NOM; - static const unsigned long long MASTER_TICKS = (R1 << 32) + R0; + // MASTER_TICKS = MAIN_FREQ / (FREQ_NUM / FREQ_DENOM) + 0.5 + STATIC_ASSERT(MAIN_FREQ < (1ull << 32)); + static const unsigned long long P = MAIN_FREQ * FREQ_DENOM + (FREQ_NUM / 2); + static const unsigned long long MASTER_TICKS = P / FREQ_NUM; + STATIC_ASSERT(MASTER_TICKS < (1ull << 32)); static const unsigned MASTER_TICKS32 = MASTER_TICKS; - STATIC_ASSERT(MASTER_TICKS < 0x100000000ull); public: // Note: default copy constructor and assigment operator are ok. Modified: openmsx/trunk/src/DynamicClock.hh =================================================================== --- openmsx/trunk/src/DynamicClock.hh 2011-08-29 19:28:35 UTC (rev 12253) +++ openmsx/trunk/src/DynamicClock.hh 2011-08-30 19:35:05 UTC (rev 12254) @@ -5,6 +5,7 @@ #include "EmuTime.hh" #include "DivModBySame.hh" +#include "static_assert.hh" #include <cassert> namespace openmsx { @@ -83,6 +84,17 @@ assert(newStep); divmod.setDivisor(newStep); } + /** Equivalent to setFreq(freq_num / freq_denom), but possibly with + * less rounding errors. + */ + void setFreq(unsigned freq_num, unsigned freq_denom) { + STATIC_ASSERT(MAIN_FREQ < (1ull << 32)); + unsigned long long p = MAIN_FREQ * freq_denom + (freq_num / 2); + unsigned long long newStep = p / freq_num; + assert(newStep < (1ull << 32)); + assert(newStep); + divmod.setDivisor(unsigned(newStep)); + } /** Returns the frequency (in Hz) at which this clock ticks. * @see setFreq() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |