I'm working on getting a piece of hardware interfaced to a computer using a Netduino. There are some places in the documentation for this hardware that specify delays for which the available .NET Micro Framework functions just won't work for me. For this application spin waits are fine. So I've implemented a class to take care of the delays for me. When the program is first started I call the Calibrate
method on this class. Calibrate
will perform a spin wait for a predetermined number of cycles timing how long it takes to complete. The amount of time it takes to complete is then used to calculate the ratio between the cycles and the timing. That value is used to know how many cycles to wait to delay for an approximate amount of time.
I've found that this works perfectly fine for my needs. Something to keep in mind when extremely short delays are needed is that there's some amount of overhead with the function call and preparing for the loop. For many applications this may not matter. If the spin wait is interrupted (such as by another thread taking control or a hardware interrupt being triggered) then the timing could get thrown off. So this solution isn't for every one.
I've pre-populated the variable for cycles per second with the value that the hardware that I am using came up with. The hardware I am using is a Netduino Plus 2. The needed value will likely be different on other hardware and possibly on future firmware updates of the same hardware.
public class SpinWaitTimer
{
double _cyclesPerSecond = 112262.2255516001;
public double CyclesPerSecond
{
get { return _cyclesPerSecond; }
set { _cyclesPerSecond = value; }
}
public SpinWaitTimer()
{
}
public void Calibrate()
{
const int CYCLE_COUNT = 1048576;
int dummyValue = 0;
DateTime startTime = DateTime.Now;
for (int i = 0; i < CYCLE_COUNT; ++i)
{
++dummyValue;
}
DateTime endTime = DateTime.Now;
TimeSpan timeDifference = endTime.Subtract(startTime);
_cyclesPerSecond = ((double)CYCLE_COUNT / (double)timeDifference.Ticks)*10000000d;
}
public void WaitSeconds(double sec)
{
int cycleCount = (int)((sec * CyclesPerSecond));
int dummyValue = 0;
for (int i = 0; i < cycleCount; ++i)
{
++dummyValue;
}
}
public void WaitMilliseconds(double microseconds)
{
int cycleCount = (int)(_cyclesPerSecond * CyclesPerSecond / 1000d);
int dummyValue = 0;
for (int i = 0; i < cycleCount; ++i)
{
++dummyValue;
}
}
public void WaitMicroseconds(double microseconds)
{
int cycleCount = (int)(_cyclesPerSecond * CyclesPerSecond / 1000000d);
int dummyValue = 0;
for (int i = 0; i < cycleCount; ++i)
{
++dummyValue;
}
}
}