| ||||||||||
The time unit can be set to any arbitrary indivisible unit with the setTicksPerSecond function. Time units can be as small as the CPU clock speed, but are intended to be about the length of a millisecond or greater. For example, MIDI files have an arbitrary time unit described as ticks per second in the header to the file -- usually around 96 or so. A Timer object could match the timing units in this case by calling setTicksPerSecond(96) as shown in example 2 below.
| ||||||||||
Warning: when changing the number of ticks per second with the setTicksPerSecond function, you should call the reset function at the same time. This will prevent a discontinuity which is created in the tick count when the timing resolution is changed.
There is another function called getTimerInSeconds which will return a floating-point value of the current time in seconds. Likewise, a function called getTimeInTicks is an analogous function which behaves in the exact same way as the getTime function. A generic way to count seconds with an arbitrary number of ticks per second is shown in example 3 below.
| ||||||||||
The Timer class must have the correct speed for the CPU in order to give correct timing values. Since there is no direct way (at least known to me) of getting the CPU speed of the computer in a program, the Timer class will take a measurement of the CPU speed when the very first instance of the Timer class is created by calling the measureCpuSpeed function which takes about a 1/4 second to estimate the speed of the computer. The measured value is expected to be about +/- 5% of the correct value, but there is no guarentee to that since the measurement accuracy relies on many variables and assumptions.
If you want an accurate timer, then you must set the exact speed of your CPU with the setCpuSpeed function. For example, the function call Timer::setCpuSpeed(200000000) sets the CPU speed to 200 MHz. setCpuSpeed is a static function which can be called through an instance of the Timer class, or it can be called directly as shown in the previous sentence. Note that changing the CPU speed for one instance of the Timer class will change the value for all instances of the Timer class. You may view the Timer classes value for the CPU speed by calling the getCpuSpeed function. You can access the clock cycle count directly with the function clockCycles which will return the current number of clock cycles as a 64-bit integer since the computer was last rebooted.
Warning: The Timer class is only guarenteed to work on Pentium-class computers at the present time, since assembler code is used to access the clock cycle count from a Pentium hardware register in the function clockCycles. Assuming that the clockCycles function returns the proper value, all of the other class functions for the Timer class will work properly -- only the clockCycles function is OS/CPU dependent.
All timers are coordinated with each other until the reset function is called on one of them. Coordinated timers, when running at the same number of ticks per second, will output identical timing values. If you have two timers which you want to reset, yet still produce the exact same output, you would first reset one of the timers, then sync the two timers as shown in example 4.
| ||||||
Although calling the setTicksPerSecond function on each synchronized timer will cause them to output different numbers, the two timers are in fact still synchronized and will output identical values whenever they again have the same number of tick divisions per second. You can also reset both timers at nearly the same instant, but they would not be precisely coordinated with each other.
Now that a period is specified, it is best to rest the timer so that the start of the period is initialized. Once a periodic timer is started, you can call either the expired or the getPeriodCount functions to check on the period time:
Period timers can be updated by advancing the inital period pointer by an integral number of periods. This is useful to keep track of events which need to run once every period. Without updating a timer, the period count would continue to rise as each new period duration is arrived at. You can update a timer by two different methods, so that the period count cycles from 0 to 1 (or any other number of cycles):
So, an implementation in the C language to access the clock cycles on a Pentuim CPU using a UNIX operating system would be:
unsigned long long int clockCount;
__asm__ volatile (".byte 0x0f, 0x31" : "=A" (clockCount));
The same result from a Microsoft-base operating system:
LONGLONG clockCount;
unsigned long high_end, low_end;
__asm {
__asm _emit 0x0f __asm _emit 0x31
mov high_end, edx
mov low_end, eax
}
clockCount = high_end;
clockCount = clockCount << 32;
clockCount |= low_end;