[A83] Detecting clock frequency
[Prev][Next][Index][Thread]
[A83] Detecting clock frequency
Hi!
I'm new to this list, so I don't know if anyone has tried this before,
but I wrote a routine to attempt to detect the CPU clock frequency.
It works by sending a command to the LCD driver, and then counting how
many T-states elapse before the driver becomes ready to accept another
command. Since the driver will (hopefully) take about the same amount of
time to recover regardless of the clock speed (about 4us - 9us by my
calculations), this should provide a reasonably accurate reference for
calculating clock speed.
The acutal timing is done by copying code to APPBACKUPSCREEN to output a
command, and then test the busy bit of the LCD driver. Each time the LCD
is busy, a NOP instruction is inserted in between the output and the
busy test, and the test is tried again. The number of NOP's required (at
4 T-states each) to create a sufficient delay, plus about 7 T-states
overhead gives a fairly good delay timing. I do the complete test 256
times and take the average, just to be sure.
Unfornunately, since I own only a standard 83+, I have no way of
checking it works across all calcs (although it does report ~6Mhz for my
calc).
It would be greatly appreciated if anybody would try this code on their
calcs, especially owners of SE or over-clocked calcs.
Thanks for any help!
------ Code begins here -------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Driver program for TestCPUFrequency
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
call TestCPUFrequency
ei
bcall(_GrBufClr)
ld bc, $0000
ld (penCol), bc
ld hl, txt_frequency
bcall(_VPutS)
ld a, 4
bcall(_DispOP1A)
ld hl, txt_mhz
bcall(_VPutS)
ld bc, $1000
ld (penCol), bc
ld hl, txt_done
bcall(_VPutS)
bcall(_GetKey)
ret
txt_frequency: .db "CPU Frequency: ", 0
txt_mhz: .db "Mhz", 0
txt_done: .db "Press any key to continue...", 0
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; End of driver program
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Define T6A04_6MHZ_DELAY to be the number of T-states required to
provide
;; the average case delay between sending commands to the T6A04 LCD
driver.
;;
;; Accoring to T6A04 specs, the required delay (T) for the TI calcs
should be
;; 4.65us <= T <= 9.30us. If we take the mean value of 6.975us, this
gives us
;; approximately 42 T-states on a 6Mhz processor.
;;
;; Coincidently, 42 also happens to be the answer to the meaning of
life, the
;; universe and everything ;)
#define T6A04_6MHZ_DELAY 42
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; TestCPUFrequency:
;;
;; This routine estimates the clock frequency of the CPU by taking the
;; average number of T-states spent waiting for the LCD driver to become
;; ready in response to a command over 256 iterations.
;;
;; Interrupts are disables by this routine. You must re-enable them
youself.
;;
;; INPUTS:
;; none
;;
;; OUTPUTS:
;; OP1 - Estimated clock frequency in Mhz
;;
;; DESTROYED:
;; AF, BC, DE, HL, OP2, APPBACKUPSCREEN
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
TestCPUFrequency:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Disable interrupts, save original X/Y counter mode and set
some
;; counters to zero.
di
in a, ($10)
and $03
push af
xor a
ld h, a
ld l, a
_LCDTestLoop:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; At the beginning of each loop, save the loop counter (A) and
total
;; NOP count (HL). Then copy the initial LCD timing code to
;; APPBACKUPSCREEN.
push af
push hl
ld hl, _LCDTimerCodeA
ld de, APPBACKUPSCREEN
ld bc, _LCDTimerCodeC - _LCDTimerCodeA
ldir
_LCDTestWaitTime:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Inside the timing loop. Call the timing code and insert an
extra
;; NOP instruction each time it fails until eventual success.
call APPBACKUPSCREEN
jp nc, _LCDWaitTimeOK
push bc
ld hl, _LCDTimerCodeC - _LCDTimerCodeA + APPBACKUPSCREEN
add hl, bc
ex de, hl
ld hl, _LCDTimerCodeC - _LCDTimerCodeA + APPBACKUPSCREEN -
1
add hl, bc
ld bc, _LCDTimerCodeC - _LCDTimerCodeB
lddr
inc hl
ld (hl), $00
pop bc
inc bc
jp _LCDTestWaitTime
_LCDWaitTimeOK:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Add the number of NOP's used in this loop (BC) to the total
count
;; (HL) and then loop again until we have performed 256 tests.
pop hl
pop af
add hl, bc
dec a
jp nz, _LCDTestLoop
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Testing is complete. Restore original X/Y counter mode.
pop af
or $04
out ($10), a
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Convert HL, an 8.8 fixed point number representing the
average
;; number of NOP instructions used, to an FP number in OP1.
push hl
ld h, 0
bcall(_SetXXXXOP2)
bcall(_OP2ToOP1)
ld hl, 256
bcall(_SetXXXXOP2)
bcall(_FPDiv)
pop hl
ld l, h
ld h, 0
bcall(_SetXXXXOP2)
bcall(_FPAdd)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Finally, calculate the estimated CPU clock frequency.
ld hl, 4 ; each NOP instruction takes 4
bcall(_SetXXXXOP2) ; T-states.
bcall(_FPMult)
ld hl, 7 ; plus the overhead for the LCD
bcall(_SetXXXXOP2) ; status read.
bcall(_FPAdd)
ld hl, 6 ; our reference point is a 6Mhz
calc.
bcall(_SetXXXXOP2)
bcall(_FPMult)
ld hl, T6A04_6MHZ_DELAY ; and then divide by the average
LCD
bcall(_SetXXXXOP2) ; delay.
bcall(_FPDiv)
ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; This code is copied to APPBACKUPSCREEN, with the NOP
instructions
;; inserted at _LCDTimerCodeB.
_LCDTimerCodeA:
scf
ld a, $05
out ($10), a ; output X auto-increment
command.
_LCDTimerCodeB:
in a, ($10) ; read status byte
rla ; rotate busy bit to carry
ret
_LCDTimerCodeC:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; End of TestCPUFrequency
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;