| |
Krill
Registered: Apr 2002 Posts: 2839 |
Extending MOS 6522 VIA timers to more than 16 bits without interrupts
This is a trick i came across on some Commodore/drive related newsgroup, which i've put to good use in my loader, and the question is this:
Is there a canonical name for this technique*? :)
And not just for the VIA, but generally in micro-controller usage.
(My SE-fu has failed me, couldn't find anything noteworthy on the net or 6502.org, nor could i find that original newsgroup post.)
Background: Unlike on the 6526 CIA, the 16-bit VIA timers cannot be linked in hardware for 32-bit timeouts.
65535 cycles at 1 MHz are about 65.5 milliseconds, which is just a bit more than 3 PAL videoframes and insufficient for many purposes.
The normal method to extend that timeout period is to have an interrupt for every timeout, which would increase a variable, effectively yielding more than 16 bits with the help of software.
Unfortunately, interrupts are often not feasible (especially in disk drive code), so here's the
Solution: Arithmetically couple two timers by giving them different timeouts.
Consider timer A with a timeout of 65535 ($ffff) cycles, and timer B with 65533 ($fffd) cycles.
As they reset with different periods, their counters will drift apart over time.
Thus, a simple check like this:lda >counterA; timer A current counter value MSB
cmp >counterB; timer B current counter value MSB
bmi timedout ; hibyte(counterA - counterB) >= 128 -> timeout makes it possible to have much longer timeouts than just 65535 cycles.
For this example, that's
65535 * 256 * 128 / (65535 - 65533) = 1,073,725,440 cycles
which is a 30-bit number and corresponds to roughly 18 minutes at 1 MHz.
The bigger the period difference is, the smaller the effective timeout is.
For practical purposes, the minimum is 2 as in this example.
* Note that it works without (co-)prime numbers, but is possibly related to those approaches. |
|
| |
Copyfault
Registered: Dec 2001 Posts: 466 |
Quoting KrillThis is a trick i came across on some Commodore/drive related newsgroup, which i've put to good use in my loader, and the question is this:
Is there a canonical name for this technique*? :)
Not that I'd know, but just looking at the mathmatical context I'd say it's some kind of "simultaneous inequalities" in different modulo class rings (just like simultaneous congruences occur when applying the Chinese remainder theorem).
Quoting Krill[...]
The normal method to extend that timeout period is to have an interrupt for every timeout, which would increase a variable, effectively yielding more than 16 bits with the help of software.
Unfortunately, interrupts are often not feasible (especially in disk drive code), ...
Hmm, but if you'd choose two different counters, like a "dedicated counter for every timer", it should be possible to increase them seperately and calculate the larger value e.g. by applying the extended euclidian algorithm. I'm sure I miss smth, especially since you write interrupts are often not feasible (especially in disk drive code). What's the reason for this?
Quoting KrillSolution: Arithmetically couple two timers by giving them different timeouts.
Consider timer A with a timeout of 65535 ($ffff) cycles, and timer B with 65533 ($fffd) cycles.
As they reset with different periods, their counters will drift apart over time.
Thus, a simple check like this:lda >counterA; timer A current counter value MSB
cmp >counterB; timer B current counter value MSB
bmi timedout ; hibyte(counterA - counterB) >= 128 -> timeout makes it possible to have much longer timeouts than just 65535 cycles. That's just excellent :) But just for further understanding: doesn't setting a timer to e.g. $ffff mean it effectively counts $ffff+1=$10000=65536 cycles? Afaik, CIA-timers work that way, i.e. the value set is one less than the no. of cycles counted.
Quoting KrillFor practical purposes, the minimum is 2 as in this example.
... This is interesting: basically(=thinking purely theoretical) a difference of 1 should also work. What breaks this in practice? |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
this trick is so cool :) its like one of those when you think hard on optimising code and you have a brilliant idea and you can do it with even skipping some steps :) |
| |
mankeli
Registered: Oct 2010 Posts: 110 |
yes. very cool trick indeed! You can invent a name for it, but make sure it has a nice acronym. Like PDC = Phase Difference Counters |
| |
Copyfault
Registered: Dec 2001 Posts: 466 |
Since the approach is coupled to the Chinese remainder theorem which I checked on Wikipedia the other day, I forgot to mention that the calculus that can be extracted from it has a name already: https://en.wikipedia.org/wiki/Residue_number_system
So maybe this could be adopted to name the timer coupling, i.e. Residue Counter System or whatever...
Anyway, wanted to point to that wikipedia-entry in the first place. |
| |
Krill
Registered: Apr 2002 Posts: 2839 |
Quoting KrillIs there a canonical name for this technique*? :) Not sure if canonical, but i just came across this:
https://en.wikipedia.org/wiki/Range_ambiguity_resolution#Operat..
Seems like a pretty good real-world analogon, at least. =) |
| |
Martin Piper
Registered: Nov 2007 Posts: 634 |
I'm sure CIA1TimerBControl $dc0f bits 5-6 : %10 = Timer counts underflows of timer A |
| |
tlr
Registered: Sep 2003 Posts: 1714 |
Quote: I'm sure CIA1TimerBControl $dc0f bits 5-6 : %10 = Timer counts underflows of timer A
Yes, but CIA = 6526. This is about the 6522 VIA. |
| |
Krill
Registered: Apr 2002 Posts: 2839 |
Those who are able to read
Are at an advantage indeed. |
| |
Oswald
Registered: Apr 2002 Posts: 5017 |
nah for a short while I misstook it for 6526 aswell coming here again a week ago or so. |
| |
Martin Piper
Registered: Nov 2007 Posts: 634 |
:D Evidently I'm blind. |