| Author |
Message |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 28 September 2009, 20:48 PM Post subject: 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? |
|
| Back to top |
|
 |
mikep
Joined: 24 Sep 2005
Location: Austin, TX
|
|
Posted: 28 September 2009, 21:56 PM Post subject: |
|
|
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). |
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 28 September 2009, 23:09 PM Post subject: |
|
|
| Why does Pause(1) take 1.953mS? |
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 28 September 2009, 23:43 PM Post subject: |
|
|
Try this, with both Pause() and Sleep(), with identical results:
| Code: | Sub Main()
do
pause(512)
Console.WriteLine("Tick " & cstr(register.RTCTick))
loop
End Sub
|
|
|
| Back to top |
|
 |
mikep
Joined: 24 Sep 2005
Location: Austin, TX
|
|
Posted: 29 September 2009, 0:06 AM Post subject: |
|
|
| GTBecker wrote: | | Why does Pause(1) take 1.953mS? | Don't know. We will have to wait for Don  |
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 29 September 2009, 1:07 AM Post subject: |
|
|
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. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Location: Portland, OR
|
|
Posted: 29 September 2009, 3:17 AM Post subject: |
|
|
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(). |
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 29 September 2009, 19:52 PM Post subject: |
|
|
| dkinzer wrote: | | ... the units of Pause() are low level ticks of the RTC timer [at] 230.4KHz... |
The source, yes, but not the parameter units, which appears to be RTCTicks. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Location: Portland, OR
|
|
Posted: 30 September 2009, 0:11 AM Post subject: |
|
|
| GTBecker wrote: | | [...] but not the parameter units, which appears to be RTCTicks. | Consider this program: | Code: | 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 | This test code was compiled for and run on a ZX-24a. The times indicated in the comments are the length of time that the output pin (pin 13 in this case) was low as measured with a logic analyzer. The resulting pulse times are longer than requested due to the overhead of preparing to pause. (Offhand, I don't know why it is shorter with the approximate 100uS pause than it is for the 500uS and 1mS pause.) Clearly, this demonstrates that the "units" value for Pause() is approximately 4.34uS (as documented) corresponding to the rate at which the RTC timer is clocked.
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. |
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 30 September 2009, 1:38 AM Post subject: |
|
|
| dkinzer wrote: | | Using the same test on a native mode device reveals an implementation error... |
I have been developing and testing on a ZX-24n so I expect that we will both be found right. Thanks for pursuing it. |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Location: Portland, OR
|
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 30 September 2009, 20:55 PM Post subject: |
|
|
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) |
|
| Back to top |
|
 |
dkinzer Site Admin
Joined: 03 Sep 2005
Location: Portland, OR
|
|
Posted: 30 September 2009, 21:28 PM Post subject: |
|
|
| GTBecker wrote: | | Pause is better, but the spread (jitter) is much greater. | 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. |
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 01 October 2009, 2:23 AM Post subject: |
|
|
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:
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)
That's about 9.1% long.
One-quarter second:
Pause(0.25):
Max= 0.2500911S, Min= 0.2500564S, Spread= 3.47197E-05S, Mean(50)= 0.2500778S (3.998755Hz)
+0.03%
A quarter-second using Sleep():
Max= 0.2500044S, Min= 0.2499957S, Spread= 8.687374E-06S, Mean(50)= 0.25S (4.0Hz)
The apparent error here is essentially zero since the timing mechanism and the timed object are based on the same timebase. [Strictly, everything in the machine is based on the same timebase, but the ~asynchronous nature of Pause() makes it less precise than exact multiples of the RTCTick, as 0.25S is, I think.
It should be very handy for odd, short periods. |
|
| Back to top |
|
 |
GTBecker
Joined: 18 Jan 2006
Location: Cape Coral
|
|
Posted: 14 March 2010, 21:28 PM Post subject: |
|
|
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:
| Code: | | call Pause(ArmDelay) ' value is in Seconds |
| Code: | | call Pause(cint(230400.0 * ArmDelay)) ' converts period to Timer0 clocks |
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? |
|
| Back to top |
|
 |
|