Using a timer so se how fast (?) my code runs

it this possible on the ARC32 ?

Ive been cutting out bits and pices from the Phonex code, but it dosnt make much sens to me, and (maby) therefor i havnt got it to work. It is really not nesessery if it is something “usual”, like milliseconds, it can just as well be clockcykels or whatever… as long at it reprecent time in some manner
I was thinking something like

Init Timerfunction ...... Start timer ... test this code ... Stop timer Pressent the result
Can anyone help me with some code ?

It is all in the phoenix code… Depending on which version and processors it uses different timers… From the version I uploaded today for serial communications…

some defines to use…

;[TIMING]
lTimerCnt			var	LONG	; used now also in timing of how long since we received a message
lCurrentTime		var long	
lTimerStart			var long	;Start time of the calculation cycles
lTimerEnd			var long 	;End time of the calculation cycles
CycleTime			var byte	;Total Cycle time

You need to define the interrupts you are using…

[code];[TIMER INTERRUPT INIT]
#ifdef BASICATOMPRO28

TIMERINT con TIMERAINT
ONASMINTERRUPT TIMERAINT, HANDLE_TIMERA_ASM
#else
TIMERINT con TIMERB1INT
ONASMINTERRUPT TIMERB1INT, HANDLE_TIMERB1_ASM
#endif
[/code]

You need to initialize the timer code…

[code];Timer

Then define the timer interrupt code as well as a helper function to get the time…

[code];==============================================================================
;[Handle_Timer_asm] - Handle timer A overflow in assembly language. Currently only
;used for timings for debugging the speed of the code
;Now used to time how long since we received a message from the remote.
;this is important when we are in the NEW message mode, as we could be hung
;out with the robot walking and no new commands coming in.
;==============================================================================
#ifdef BASICATOMPRO28
BEGINASMSUB
HANDLE_TIMERA_ASM
push.l er1 ; first save away ER1 as we will mess with it.
bclr #6,@IRR1:8 ; clear the corresponding bit in the interrupt pending mask
mov.l @LTIMERCNT:16,er1 ; Add 256 to our counter
add.l #256,er1
mov.l er1, @LTIMERCNT:16
pop.l er1
rte
ENDASMSUB
#else
BEGINASMSUB
HANDLE_TIMERB1_ASM
push.l er1 ; first save away ER1 as we will mess with it.
bclr #5,@IRR2:8 ; clear the corresponding bit in the interrupt pending mask
mov.l @LTIMERCNT:16,er1 ; Add 256 to our counter
add.l #256,er1
mov.l er1, @LTIMERCNT:16
pop.l er1
rte
ENDASMSUB
#endif
return ; Put a basic statement before…

;==============================================================================
;[GetCurrentTime] - Gets the Timer value from our overflow counter as well as the TCA counter. It
; makes sure of consistency. That is it is very possible that
; after we grabbed the timers value it overflows, before we grab the other part
; so we check to make sure it is correct and if necessary regrab things.
;==============================================================================
GetCurrentTime:
#ifdef BASICATOMPRO28
lCurrentTime = lTimerCnt + TCA
#else
lCurrentTime = lTimerCnt + TCB1
#endif
; handle wrap
if lTimerCnt <> (lCurrentTime & 0xffffff00) then
#ifdef BASICATOMPRO28
lCurrentTime = lTimerCnt + TCA
#else
lCurrentTime = lTimerCnt + TCB1
#endif
endif

return lCurrentTime

[/code]
lTimerCnt = 0
#ifdef BASICATOMPRO28
WTIMERTICSPERMSMUL con 64 ; BAP28 is 16mhz need a multiplier and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 125 ;
TMA = 0 ; clock / 8192 ; Low resolution clock - used for timeouts…
#else
WTIMERTICSPERMSMUL con 256 ; Arc32 is 20mhz need a multiplier and divider to make the conversion with /8192
WTIMERTICSPERMSDIV con 625 ;
TMB1 = 0 ; clock / 8192 ; Low resolution clock - used for timeouts…
#endif

ENABLE TIMERINT
ENABLE
[/code]

How to time something…

; get the start time...
  'Start time
  GOSUB GetCurrentTime], lTimerStart 
... do whatever you wish to time...
; Get the end time
  Gosub GetCurrentTime], lTimerEnd
; compute Delta time in Miliseconds...
  CycleTime = ((lTimerEnd-lTimerStart) * WTIMERTICSPERMSMUL) / WTIMERTICSPERMSDIV 

This is setup to use TimerA on Bap28 and timerB1 on Bap40 and Arc32. It initializes the timer to say only increment every 8192 clocks, size these timers are 8 bit timers that will overflow every 8192*256=2,097,152 clocks. So on Arc32 you will get 20000000/2,097,152 or about 9.5 times per second…

=======================================================================================================
Option 2:

So if all you wish to do is time a specific thing and it will complete in under 1/9.5 seconds and this resolution is sufficient for you than all of this could be overkill. That is you don’t need the interrupt… You could get away with simply using the timer without an interrupt. That is for Arc32, you could simply initialize the timer somewhere at the start…

TMB1 = 0 ; clock / 8192

Then at the start of the code you wish to time simply set the counter associated with the timer to zero
TCB1 = 0

Do your stuff and then at the end save away the timer and convert to ms…
CycleTime = (TCB1 * WTIMERTICSPERMSMUL) / WTIMERTICSPERMSDIV

==========================================================================
Option 3:

Personally if I need this for timings that are not needed for the program itself (like timings for the servos or error out if I don’t see anything on an XBee for a timeout period…) I cheat.

I find an unused IO pin on my board (example P4). At the start of the code I wish to time, I do a: high P4 and the end of the code I wish to time I do a low P4. I then hook up my logic analyzer and record the time. When I move the mouse inside the pulse shown in the analyzer software it will give me the time… But that is cheating!

Sorry for the long winded three different ways answer.
Kurt

Very thorough explanation Kurt! And very useful information. :smiley:

I’ve used option #3 several times, its definitely the easiest way to do it in code though. And also very accurate.

Thanks, this was exactly what i wanted

i bow deeply

Ill try it when i get home from work

It works like a charm !!

There semes to be an Option 4 if you have an ARC32:

Init Timerfunction:

starttime var long stoptime var long
Start timer

starttime = hservotime 0

test this code, for example

GOSUB GetIRDistance[cIRRanger], Result

Stop timer

stoptime = hservotime 0

Pressent the result

hserout "Time (usec) = ", dec (stoptime-starttime)/20, 13]

By doing this timing i found out that the penalty for doing /4.35 instead of the recommended * 100 / 435 is about 5 us
Not much but intresting !