**********************************************************************
* Name: TIM
* Stack: ( ob --> ? time )
* Desc: Execution time measurement
**********************************************************************
ASSEMBLE
CON(1) 8
RPL
xNAME TIM
::
CK1
'
::
SysTime ONE{}N >R ( Keep time variable in return stack )
GARBAGE ( Avoid GC fluctuations )
CODE
TIMEPART1 GOSBVL =SAVPTR
GOSBVL =DisableIntr
* Wait until no keys down
- GOSBVL =BITMAP
GOSBVL =Debounce
?A#0 W
GOYES -
GOSBVL =adjkey
* Prepare timing and do a small delay to stabilize
GOSBVL =GetTimChk
B=A W
C=0 W
LCHEX 1C20000 1 hour
B=B+C W B[W] = time + 1 hour
D=C W D[W] = 1 hour
A=0 W
C=0 W
D1=(2) =TIMER2 Wait until boundary to avoid
A=DAT1 B tick boundary effects later on
- C=DAT1 B
?C=A P
GOYES -
LC(2) 128
A=DAT1 8
DAT1=C 8
D1=(2) =TIMERCTRL.1
LC(2) #50 [SRQ WKE INT TRUN] = [0 1 0 1]
DAT1=C B
LCHEX 00000286
B=B+C W B[W] = time + 1 hour + 646 ticks
* SHUTDN with display on is with TIMER2 -2
* SHUTDN with display off is with TIMER2 -514 (512+2)
* So 516 ticks for clock adjustment
P= 7 Sign extend TIMER2
C=A P
C=C+C P
GONC +
A=-A W
A=-A WP
+ P= 0
B=B-A W
A=B W
GOSBVL PutNEXTIRQ
GOSUB D0->Time Save start time
C=B W
C=C-D W
DAT0=C 13
SHUTDN *STABILIZE*
D1=(5) =TIMER2 Second stabilization is a short one
C=0 W
LC(1) 2
DAT1=C 8
D1=(2) =TIMERCTRL.1
LC(2) #50 [SRQ WKE INT TRUN] = [0 1 0 1]
DAT1=C B
D0=(5) =BITOFFSET With a very fast display off/on toggle
C=DAT0 1 This gives extra stability while
CBIT=0 3 not being as annoying as the more
DAT0=C 1 stable 128 tick display off method.
CBIT=1 3 Experimentally this is the best place
DAT0=C 1 to do the display blink.
SHUTDN *STABILIZE*
D1=(2) =TIMER2 Restore timers
C=D W
DAT1=C 8
D1=(2) =TIMERCTRL.1
LC(2) #70 [SRQ WKE INT TRUN] = [0 1 1 1]
DAT1=C B
GOSBVL =AllowIntr
GOSBVL =GETPTR Evaluate input object
A=DAT1 A
D1=D1+ 5
D=D+1 A
PC=(A)
D0->Time D0=(5) =aRSKTOP Help subroutine to recall the
A=DAT0 A time hex string pushed to
D0=A return stack
A=DAT0 A
D0=A
D0=D0- 5
A=DAT0 A
D0=A
D0=D0+ 10
RTN
ENDCODE
CODE
TIMEPART2 GOSBVL =SAVPTR
A=0 W Prepare variables
C=0 W
B=0 A
D1=(5) =TIMER2
D0=(5) =IRAM@ Dispatch to SX/GX code
A=DAT0 XS
A=A+A XS
GONC sxfinish
GOTO gxfinish
sxfinish D0=(5) =NEXTIRQ Delay until tick changes to avoid
A=DAT0 13 irregularities in C increments
C=DAT1 8
D=C W
- B=B+1 A
C=DAT1 A
P= 0
?D=C P
GOYES -
D0=(5) =SAVE_C[A] Increment C, the interrupt system
C=0 W will then save some value as the
DAT1=C 8 timer goes negative
C=C+1 X 1
C=C+1 B 2
C=C+1 X 3 Dan: Low limit 3
C=C+1 B 4
C=C+1 X 5
C=C+1 B 6
C=C+1 X 7
C=C+1 B 8
C=C+1 X 9
C=C+1 B 10
C=C+1 X 11
C=C+1 B 12
C=C+1 X 13
C=C+1 B 14
C=C+1 X 15
C=C+1 B 16
C=C+1 X 17
C=C+1 B 18
C=C+1 X 19
C=C+1 B 20
C=C+1 X 21
C=C+1 B 22
C=C+1 X 23
C=C+1 B 24 Dan: Hi limit 24
C=C+1 X 25
C=C+1 B 26
C=C+1 X 27
C=C+1 B 28
C=C+1 X 29
C=C+1 B 30
C=C+1 X 31
C=C+1 B 32
C=C+1 X 33
C=C+1 B 34
C=C+1 X 35
C=C+1 B 36
C=C+1 X 37
C=C+1 B 38
C=C+1 X 39
C=C+1 B 40
C=C+1 X 41
C=C+1 B 42
C=C+1 X 43
C=C+1 B 44
C=C+1 X 45
C=C+1 B 46
C=C+1 X 47
C=C+1 B 48
C=C+1 X 49
C=C+1 B 50
C=DAT0 A Scale the counters by 3 for SX
RSTK=C
C=B A
C=C+C A
C=C+B A
R1=C A 3*loop count
C=RSTK
B=C A
C=C+C A
C=C+B A
R0=C A 3*count
GOTO commonfin
gxfinish D0=(5) =G_NEXTIRQ Delay until tick changes to avoid
A=DAT0 13 irregularities in C increments
C=DAT1 8
D=C W
- B=B+1 A
C=DAT1 A
P= 0
?D=C X
GOYES -
D0=(5) =G_SAVE_C[A] Let interrupt system save the counter
C=0 W when timer goes negative
DAT1=C 8
LC(2) 1
LC(2) 2
LC(2) 3
LC(2) 4
LC(2) 5
LC(2) 6
LC(2) 7
LC(2) 8
LC(2) 9
LC(2) 10
LC(2) 11
LC(2) 12
LC(2) 13
LC(2) 14
LC(2) 15
LC(2) 16
LC(2) 17
LC(2) 18 Dan: Lo limit 18 (?)
LC(2) 19
LC(2) 20
LC(2) 21
LC(2) 22
LC(2) 23
LC(2) 24
LC(2) 25
LC(2) 26
LC(2) 27
LC(2) 28
LC(2) 29
LC(2) 30
LC(2) 31
LC(2) 32
LC(2) 33
LC(2) 34
LC(2) 35
LC(2) 36
LC(2) 37
LC(2) 38 Dan: Hi limit 38 (?)
LC(2) 39
LC(2) 40
LC(2) 41
LC(2) 42
LC(2) 43
LC(2) 44
LC(2) 45
LC(2) 46
LC(2) 47
LC(2) 48
LC(2) 49
LC(2) 50
C=DAT0 A Scale the counters for GX
C=C+C A
R0=C.F A 2*count
C=B A
C=C+C A
R1=C.F A 2*loop count
* Finish up
commonfin GOSBVL =DisableIntr
C=D W
GOSBVL =GetTimeEnd Calculate ending time
GOSUB D0->Time Calculate running time
A=DAT0 13
C=C-A W
DAT0=C 13
C=D W Fix time to correct value
R3=C W
GOSBVL =GetTimChk
C=R3 W
C=C-1 W
A=A-C W
GOSBVL PutNEXTIRQ
GOSBVL =AllowIntr Return counters
GOVLNG =Push2#Loop
ENDCODE
* Calculate the total running time
RDUP 'RRDROP HXS>% ( #counter #loops %ticks )
UNROT SEVEN #* #+ UNCOERCE ( %ticks %7*loops+counter )
% 0.01 %* %- ( %time )
* Now measure NOP execution time to get calculator (not just version!)
* independant overhead time.
'NOP
CODE
GOTO TIMEPART1
ENDCODE
CODE
GOTO TIMEPART2
ENDCODE
'RRDROP HXS>% ( %time #counter #loops %ticks )
UNROT SEVEN #* #+ UNCOERCE ( %time %ticks %7*loops+counter )
% .01 %* %- ( %time %time2 )
* Substract the offset (including NOP execution time)
%- ( %time' )
* Add NOP execution time back in, it is not an overhead
* Actually we add slightly more since above doesn't seem to
* get the overhead exactly right, we use values such that
* we get correct execution times for NOP whose execution time
* can be accurately measured for example by timing 1000 sequential
* NOP's and dividing by 1000.
GX? ITE % 0.31 % 0.45 %+ ( %time'' )
* Format result for output
DUP % 8.192 %/ %2 RNDXY
DUP %100 %>= ITE
::
% 1000 %/
UNIT %1 tok_s umEND ;
;
UNIT %1 CHR m tok_s umP umEND ;
UM>U
SWAP DECOMP$ >TAG
;
* Copy above subroutine to even address
CHR_X TOTEMPOB
CODE
A=DAT1 A
?ABIT=1 0
GOYES +
+ GOVLNG =PushT/FLoop
ENDCODE
IT TOTEMPOB DROP
* And evaluate it from there
COLA_EVAL
;
**********************************************************************