Pause()
Pause()
Don, of the parameter, the Pause() documentation description says "The amount of time to pause, in seconds (Single) or Timer 0 ticks (int16)" but the example and routine description, I believe incorrectly, suggest that its resolution is 1/230400Hz. Testing suggests that it is, indeed, running at the 512Hz tick rate.
Is the documentation incorrect, or is this a bug?
Is the documentation incorrect, or is this a bug?
Tom
The documentation is correct but I had to read it twice to fully understand it.
Timer0 ticks are indeed every 4.34 us. 450 of these Timer0 ticks makes one RTC tick which is 1/512 of a second. Sleep and Delay use RTC ticks whereas Pause uses Timer0 ticks. Task scheduling happens every RTC tick.
The maximum pause length is 65535 * 4.34us = 284,422us (or roughly 284ms as documented).
Timer0 ticks are indeed every 4.34 us. 450 of these Timer0 ticks makes one RTC tick which is 1/512 of a second. Sleep and Delay use RTC ticks whereas Pause uses Timer0 ticks. Task scheduling happens every RTC tick.
The maximum pause length is 65535 * 4.34us = 284,422us (or roughly 284ms as documented).
Mike Perks
Try this, with both Pause() and Sleep(), with identical results:
Code: Select all
Sub Main()
do
pause(512)
Console.WriteLine("Tick " & cstr(register.RTCTick))
loop
End Sub
Tom
Unless Heisenberg is at work (quite possible in a multitasking environment), my ElapsedTime tool shows that Pause(int16) is indeed more accurate and consistent than is Sleep(int16), but it is not more resolute, as the documentation suggests. The long-term mean of both is identical, in ~1.953mS increments according to the int16 value. The example of Pause(2304), which the comment says it equivalent to Pause(0.01), appears to not be correct.
Pause(single), though, does resolve better than Sleep(single). Pause(0.010) shows a spread of ~4.34uS, while Sleep(0.010) shows a spread of about four times that. Pause(single) does it better, but both still round (low) to the nearest tick, ~9.77mS. Pause(0.010) does not produce a 10mS delay despite its faster timebase.
Pause(0.010):
Max= 9.767794E-03S, Min= 9.763454E-03S, Spread= 4.339962E-06S, Mean(5000)= 9.765765E-03S (102.3985Hz)
Sleep(0.010):
Max= 9.771591E-03S, Min= 9.7564E-03S, Spread= 1.51908E-05S, Mean(5000)= 9.765449E-03S (102.4018Hz)
Overall, both forms of Pause() look faulty to me.
Pause(single), though, does resolve better than Sleep(single). Pause(0.010) shows a spread of ~4.34uS, while Sleep(0.010) shows a spread of about four times that. Pause(single) does it better, but both still round (low) to the nearest tick, ~9.77mS. Pause(0.010) does not produce a 10mS delay despite its faster timebase.
Pause(0.010):
Max= 9.767794E-03S, Min= 9.763454E-03S, Spread= 4.339962E-06S, Mean(5000)= 9.765765E-03S (102.3985Hz)
Sleep(0.010):
Max= 9.771591E-03S, Min= 9.7564E-03S, Spread= 1.51908E-05S, Mean(5000)= 9.765449E-03S (102.4018Hz)
Overall, both forms of Pause() look faulty to me.
Tom
Mike is correct in that the units of Pause() are low level ticks of the RTC timer which runs at 1/64th of the CPU frequency or 230.4KHz. The RTC timer is set up to generate an interrupt every 225 of these ticks (yielding an interrupt rate of 1024Hz). The RTC tick value is updated every other interrupt yielding an RTC tick rate of 512Hz.
I'll have to check the performance again using a logic analyzer but the last time I did so the timing was spot on.
One difference between Sleep() and Pause() is that another task may run if you call Sleep() but not so with Pause().
I'll have to check the performance again using a logic analyzer but the last time I did so the timing was spot on.
One difference between Sleep() and Pause() is that another task may run if you call Sleep() but not so with Pause().
- Don Kinzer
Consider this program:GTBecker wrote:[...] but not the parameter units, which appears to be RTCTicks.
Code: Select all
Const pin as Byte = 13
Sub Main()
Call PutPin(13, 1)
Register.PortA = &H00
#if 1
' Call Pause(23) ' yields a 119uS pulse
' Call Pause(115) ' yields a 536uS pulse
Call Pause(230) ' yields a 1.034mS pulse
#else
' Call Pause(100e-6) ' yields a 119uS pulse
' Call Pause(500e-6) ' yields a 536uS pulse
Call Pause(1e-3) ' yields a 1.034mS pulse
#endif
Register.PortA = &H80
End Sub
The integral values to pause in the first #if section correspond to the values that the compiler generates for Single constants in the second section (which you can verify by examining the .lst file).
Using the same test on a native mode device reveals an implementation error that was previously undetected.
- Don Kinzer
This issue has been corrected in the experimental release of the compiler and ZX Library (both are required).dkinzer wrote:Using the same test on a native mode device reveals an implementation error that was previously undetected.
Compiler:
http://www.zbasic.net/download/ZBasic/2 ... 2-8-10.zip
ZX Library:
http://www.zbasic.net/download/zxlib/zxlib_2-7-5.zip
- Don Kinzer
Pause is better, but the spread (jitter) is much greater. The previous compiler and library yielded 4.4uS spread (around an RTCTick); the new is ~9 times greater, but around the correct period.
- Pause(0.010), Previous compiler version on ZX-24n:
Max= 9.767794E-03S, Min= 9.763454E-03S, Spread= 4.339962E-06S, Mean(5000)= 9.765765E-03S (102.3985Hz)
Pause(0.010), New compiler (v2.8.10) on ZX-24n:
Max= 0.010096S, Min= 0.0100564S, Spread= 3.960448E-05S, Mean(5000)= 0.0100791S (99.21557Hz)
Tom
You may be able to reduce the spread by adding some synchronizing code. For example, if you loop waiting for a change in Register.RTCTick you may get within a few cycles of starting a sequence at the same phase relative to the cycle of the RTC timer.GTBecker wrote:Pause is better, but the spread (jitter) is much greater.
- Don Kinzer
It is interesting that the timing spread of Pause() now is almost always ~43.4uS (4.34uS*10, of course), sometimes one tick less, 39.06uS. I guess I was spoiled by the perhaps artificially-low one-tick 4.34uS spread when the function was misbehaving, implicitly synchronized to the RTCTick, as you suggest. Still, it produces very good timed delays now.
I tried several values I thought might be practical, like a half-cycle of 60Hz:
One-quarter second:
A quarter-second using Sleep():
It should be very handy for odd, short periods.
I tried several values I thought might be practical, like a half-cycle of 60Hz:
- Pause(0.008333) on a ZX-24n:
Max= 8.428818E-03S, Min= 8.385415E-03S, Spread= 4.340241E-05S, Mean(5000)= 8.40876E-03S (118.9236Hz)
One-quarter second:
- Pause(0.25):
Max= 0.2500911S, Min= 0.2500564S, Spread= 3.47197E-05S, Mean(50)= 0.2500778S (3.998755Hz)
A quarter-second using Sleep():
- Max= 0.2500044S, Min= 0.2499957S, Spread= 8.687374E-06S, Mean(50)= 0.25S (4.0Hz)
It should be very handy for odd, short periods.
Tom
I'm having some difficulty with Pause, again, and I'm having trouble building a simple demonstrable case.
In some code, a ZX-24n behaves as if it interprets the Single-type parameter as Timer0 clocks in the following, instead of real time:
The former delay is far too short; the latter call yields the correct delay. If I simply extract this code and try to make a test case the procedure works fine, though, interpreting the Single parameter correctly as real time.
What might affect how the IDE interprets the parameter type here?
In some code, a ZX-24n behaves as if it interprets the Single-type parameter as Timer0 clocks in the following, instead of real time:
Code: Select all
call Pause(ArmDelay) ' value is in Seconds
Code: Select all
call Pause(cint(230400.0 * ArmDelay)) ' converts period to Timer0 clocks
What might affect how the IDE interprets the parameter type here?
Tom