doslogo wrote: ↑Thu Mar 20, 2025 4:41 pm
I am a little bit confused how you can know if L borrowed from H. The timer is constantly running for each instruction, so while you capture the high byte, the low byte is already "lost" (you lost the count by the amount of cycles it took to read from the high byte). When I think about it, knowing how many cycles the instruction takes, and adding that to the extracted low byte and carrying it to the high byte.... Nah. I feel like some external odd thing will happen to skew the result.
If T1 = $0104 at the first cycle of this code, then borrow occurs between the LDA and LDX: A = $01, X = $FD. (The actual fetch occurs on the final cycle of the opcode)
The following CMP will catch that A != H, since H is now $00.
That inequality is how we know L borrowed from H in the middle of our reads. If there were no borrow, then H would still equal A.
It's ok that L is decrementing all that time, just as long as it doesn't borrow from H, because that borrow is what gives us an invalid reading, rather than a reading with just an offset.
If you want code which can provide the appropriate compensation, so you know the counter value at the start of the code, that's possible too:
Code: Select all
; START
ldx #$0A ; +2 = 2 -- Compensation, number of cycles from START to first L-read.
; Read H and L as quickly as possible.
ldy V_T1_H ; +4 = 6
lda V_T1_L ; +4 = 10
; Check if L borrowed from H in the time it took to read.
cpy V_T1_H ; +4 = 14
beq :+ ; +2 = 16
; If it did, reread.
ldy V_T1_H ; +4 = 20
lda V_T1_L ; +4 = 24
ldx #$18; Compensation, number of cycles from START to second L-read.
:
; Y and A contains valid counter value, now compensate for the time the read logic took.
stx TEMP
clc
adc TEMP
tax
tya
adc #$00
; A and X contains a valid, compensated timer counter value
This code assumes the counter is clocked once per cycle. If the counter has a different period, then divide those compensation constants by that period. For example, if clocked once every two cycles, divide the constants by two.
EDIT: Sorry, I forgot the counter is decreasing, so you'd need to
add the compensation value, not subtract as my code originally did.