Hempl/Timers
Hardware view
editThe AT32UC3A has three 16-bit countdown timers which can run at three different frequencies, independent of each other. When they are set to run at a high frequency, the timing accuracy is higher but the longest possible delay is shorter.
Only a small set of clock frequencies is available, which are divided down from the PBA bus frequency of 16.5MHz:
Divisor | Clock frequency | Longest delay |
---|---|---|
PBA/2 | 8.25 MHz | 7.94 ms |
PBA/8 | 2.0625 MHz | 31.77 ms |
PBA/32 | 515.625 kHz | 0.127 second |
PBA/128 | 128.906 kHz | 0.508 second |
Apart from these four selections, the chip also has provision for running any of the timers from an external 32768Hz real-time precision crystal. The Mizar32 board from version 1.3.2 has a space for this component (X2) where it may be mounted.
Software view
editHempl provides a timer
library to access the real-time counters.
Three types of timer
editHardware timers
editThe first two hardware timers are directly accessible, using timer IDs 0
and 1
. Hempl uses a PBA frequency of 16.5MHz and by default the clock rates are set to lowest available frequency of 128906Hz, giving a timing precision of about a hundred thousandth of a second and a maximum delay of just over half a second.
This is how one can create a wait for 1/10th of a second using the first timer:
(tmr-delay 0 100000)
These can be used to achieve short delays of high accuracy.
For either of the first two timers, you can set a higher clock rate than the default of 129kHz. However, only four values are supported as shown in the table above with PBA frequency = 16.5MHz. Other values will set the arithmetically nearest available frequency.
Below, is an example to set the highest possible timing precision for timer 1, giving a maximum delay of 7.94ms:
(prinl (tmr-setclock 1 10000000) )
The above code prints 8250000
as the output.
Virtual timers
editThe third hardware timer cannot be accessed directly, but instead is used to generate four "virtual timers" whose timer ids are tmr-virt-0
to tmr-virt-3
. These have a lower tick frequency and accuracy - ten times per second - but can be used to create delays of up to 35 minutes in integer eLua or 142 years in floating point eLua.
(tmr-delay tmr-virt-0 5000000) # Wait for five seconds
These are used to achieve longer delays of lower accuracy but the clock rate of the virtual timers cannot be changed.
System timer
editFrom the 20120123 firmware release, there is a third timer mechanism, the system timer tmr.SYS_TIMER
which has an accuracy of one millionth of a second and can be used to give high-precision delays and timings up to 35 minutes with integer Lua and up to 142 years in floating point Lua, but you cannot change the clock frequency of the system timer, and it cannot be used to generate interrupts (see below).
Timer operations
editDelays
editAll three types of timer can be used to make your program wait for a specified length of time, as shown in the examples above. The precision of the delay and the maximum delay available depend on the type of timer used. In general, the system timer is the best for all types of delay, as it has high precision and can perform long delays.
Measuring time
editSometimes it can be useful to know how much time has elapsed since some previous moment, for example to measure the speed of your code or when you need to take some decision after a certain amount of time has passed but also need to do something else while you are waiting.
This example measures people's reaction time by printing "Go!" on the console and then seeing how long it takes them to press a key in response. We will use the system timer for this.
Of course, if you press Enter before it says Go!, it will say you reacted incredibly quickly.
In PicoLisp:
# A reaction timer in picolisp (de reaction-timer () (prinl "Welcome to the reaction timer. When I say Go!, enter a character.") (prinl "Press q [Enter] to quit.") (setq timer *tmr-sys-timer* answer "" ) (until (=T answer) (println "Ready?") # Wait for a random time from 2 to 5 seconds (tmr-delay timer (+ 2000000 (rand 1 3000000))) (println "Go!") (setq start-time (tmr-read timer) answer (read) # wait for them to enter any character end-time (tmr-read timer) )
Please note: You may also download the above code reaction.l
from our examples repository on github.
Timer interrupts
editPlease note: There is currently no support for interrupt handling in PicoLisp. See issue #12.
Further reading
edit- The Atmel AT32UC3A datasheet, Chapter 31: Timer/Counter (TC) The tmr module in the eLua reference manual
- Virtual timers in the eLua reference manual.