Knowledge Base

MultiTrack (Advanced): Accuracy of SuperTimers

The SuperTimer mechanism has been designed to avoid problems of cumulative timing errors due to program latency when using MultiTrack.

The following program illustrates the point. If you run this in an MMi201 (or earlier) as it is, the 1 second flasher will manage just 58 flashes in a minute. In a more recent controller this will become closer to 59 flashes, because the processor is faster. By comparison, if you remove the very first line and let Flash1S run as a MultiTrack task, the flasher produces as close to 60 flashes per second as can reasonably checked with a watch.

(Click here for some tips for working around problems with copy and paste out of Internet Explorer and HTML-help (.chm) files)

        GoTo            Flash1S
        LaunchTask      Flash1S
        RunTasksForever

Flash1S
        On              7
        GoSub           SlowIt
        Pause           5
        Off             7
        fRecallW        fCounter
        fInc
        fStore          fCounter
        OBLCD_SetCur    0,0
        OBLCD_fDispW    5,0
        Pause           95
        GoTo            Flash1S

SlowIt
        fLoadW          1.111111
        fLoadQ          0.00001
        SetMem          Counter,100
SAA1
        fAdd
        DMGNZ           Counter,SAA1
        Return

Counter         defBYTE
fCounter        defFLOAT

So, what is happening????

The subroutine SlowIt has been designed simply to waste time, about 40mS in an MMi201. If Flash1S is run outside the MultiTrack task queue, that 40mS adds directly to the 50mS generated by Pause 5, giving a total output ON time of 90mS. So, instead of 1000mS total period we get 1040mS, or 57.6 flashes per minute.

When we change the program so Flash1S is a MultiTrack task, our super timer magic comes into effect. The SuperTimer is generated via a system timer that counts up 10mS ticks. That timer runs all the time, and is used for any timing outside the task queue. Inside the task queue, however, it is different. Each time the task queue is to be run, the system timer is copied to a separate buffer register, and that same, static value is used for all SuperTimer calculations. It is as if time stands still during each run of the task queue. It then jumps forward at the start of the next run, when the buffer register is again updated from the system timer. When the Pause 5 is first encountered the termination time is calculated starting from the time captured in the buffer.

This scheme would fail to work if subroutine SlowIt took more than 50mS, because SlowIt won’t complete until after the Pause 5 should have completed.