Procrastin8 wrote:
What is the typical approach here though, carve out 2 bytes of memory (not ZP I assume) that will hold the current count?
Two bytes at least, four bytes if you want to use the counter for something other than just a time-delay counter. For example, if you use a 32-bit counter that is initialized to $00000000 at boot time and then incremented once per second you have a system uptime counter, as well as a counter for setting delays and alarms. The 65C02 code required to increment the counter is compact and fast.
The usual procedure is to also have a one-byte "jiffy" counter along with your main counter. The jiffy counter is decremented on each VIA timer IRQ. When it reaches zero the main counter is updated. The following code fragment is an example of this procedure:
Code:
;update 16-bit time counter...
;
dec jiffyct ;jiffy counter
bne skip ;not time to update
;
lda #hz ;jiffy IRQ rate (e.g., 100)
sta jiffyct ;reset counter
inc counter ;bump counter LSB
bne skip ;done with counter
;
inc counter+1 ;bump counter MSB
;
skip ...program continues...
The above code, which uses a 16-bit counter, would be part of your interrupt service routine and would be executed each time an IRQ has occurred and has been determined to be the result of a VIA timer underflow. A 100 Hz jiffy rate is common in UNIX-like operating systems and gives you 10 millisecond resolution.
jiffyct should be initialized to the jiffy rate at boot time.
The time delay part is easy as well. As I said, the procedure is to add the time delay period to the current counter value and then spin in a loop until the counter reaches the computed sum.
Code:
;generate time delay: .X = time delay in seconds LSB
; .Y = time delay in seconds MSB
;
;all registers are used
;
;NOTE: This code will not work on an NMOS 6502. Also, if
; $0000 is passed as the delay period this function's
; behavior is undefined.
;
timdel clc
txa ;delay period LSB
sei ;halt counter updates
adc counter ;time counter LSB
tax ;future time counter LSB
tya ;delay period MSB
adc counter+1 ;time counter MSB
tay ;future time counter MSB
lda jiffyct ;current jiffy counter value
cli ;resume counter updates
;
; ———————————————————————————————————————————————————
; Now we repeatedly compare the time counter with our
; computed future counter value & break the loop when
; equality is attained. To maximize precision, we
; also compare the jiffy counter value in .A with the
; constantly-changing jiffy count & only do a main
; counter comparison when they are the same. Since
; the jiffy count is only updated when an IRQ occurs
; the WAI instruction is used to "sleep" until an IRQ
; "wakes up" the MPU.
; ———————————————————————————————————————————————————
;
timdel01 wai ;wait for any IRQ
cmp jiffyct ;check jiffy count
bne timdel01 ;not time to check main counter
;
cpy counter+1 ;check counter MSB
bcc timdel01 ;wait some more
;
cpx counter ;check counter LSB
bcc timdel01 ;wait some more
;
rts ;delay has expired — return to caller
Call the above function with:
Code:
ldx #<delay
ldy #>delay
jsr timdel
As for where to set up the counters, keeping them in absolute memory will result in code that is about 25 percent slower than if the counters are on page zero. I generally recommend that any variables that are to be manipulated in an interrupt service routine be kept on page zero to reduce background processing load.