Log inRegister an accountBrowse CSDbHelp & documentationFacts & StatisticsThe forumsAvailable RSS-feeds on CSDbSupport CSDb Commodore 64 Scene Database
You are not logged in - nap
CSDb User Forums


Forums > C64 Coding > Accurately Measuring Drive RPM
2020-08-03 16:07
chatGPZ

Registered: Dec 2001
Posts: 11089
Accurately Measuring Drive RPM

To bring the discussion from 1541 Speed Test into the forum....

first lets recapitulate:

The general idea is: have a "marker" on a track, then measure the time for one revolution using timers. Generally there are different ways to achieve this:

- wait for the marker and toggle a IEC line. the C64 measures the time using CIA timer. this is what eg the well known "Kwik Load" copy does, the problem is that it is PAL/NTSC specific, and it can never be 100% exact due to the timing drift between drive and C64.

- wait for the marker and measure the time using VIA timers on the drive. the problem with this is that VIA timers are only 16bit and can not be cascaded, so you either have to measure smaller portions at a time, or rely on the wraparound and the value being in certain bounds at the time you read it.

now, to make either way slightly more accurate, a special kind of reference track can be used. typically this track will contain nothing except one marker - which makes the code a bit simpler and straightforward. this is what 1541 Speed Test does. the DOS also does something similar when formatting, to calculate the gaps. This obviosly has the problem that we are overwriting said track.

Now - the question isn't how to do all this, that's a solved problem. The question is, given a specific implementation, how *accurate* is it actually, and why?

The basic math to calculate the RPM is this:

expected ideal:
300 rounds per minute
= 5 rounds per second
= 200 milliseconds per round
at 1MHz (0,001 milliseconds per clock)
= 200000 cycles per round

to calculate RPM from cycles per round:
RPM = (200000 * 300) / cycles

two little test programs are here: https://sourceforge.net/p/vice-emu/code/HEAD/tree/testprogs/dri.. ... the first reads timer values between each sector header and then the total time for a revolution is accumulated from the delta times. the second leaves the timer running for one revolution and then indirectly gets the time for a revolution from that. to my own surprise, both appear to be accurate down to 3 cycles (in theory the second one should be more accurate, at least thats what i thought. i also expected some more jitter than just 3 cycles)

1541 Speed Test writes a track that contains one long sync, and then 5 regular bytes which serve as the marker. it then reads 6 bytes and measures the time that takes, which equals one revolution. somehow this produces a stable value without any jitter, which was a bit surprising to me too (i expected at least one cycle jitter, due to the sync waiting loops) (i am waiting for the source release and will put a derived test into the vice repo too)

So, again, the question is... how accurate are those and why? (a stable value alone does not tell its accurate). Some details are not quite clear to me, eg if we are writing a reference track, how much will that affect the accuracy of the following measurement? how will the result change when the reference track was written at a different speed than when doing the measuring? Will using a certain speedzone make it more or less accurate?

Bonus question: can we use https://en.wikipedia.org/wiki/Chinese_remainder_theorem with two VIA timers to make this more accurate? or is it a pointless exercise?
2020-08-03 17:13
Krill

Registered: Apr 2002
Posts: 2821
Quoting Groepaz
VIA timers are only 16bit and can not be cascaded
[...]
Bonus question: can we use https://en.wikipedia.org/wiki/Chinese_remainder_theorem with two VIA timers to make this more accurate? or is it a pointless exercise?
From loader sources:
            ; timers/watchdog initialisation
            ; for the long timeout between block-ready and block-send, use two arithmetically cascaded timers:
            ; their periods differ, so their counters drift further apart every time either timer resets.
            ; the effective timeout is reached as soon as the difference between the counters is >= 128, which for
            ; the used periods' difference of 7 cycles with the counter periods of $ef00 and $ef07 is at least
            ; floor(128 / 7) * $ef07 = 18 * $ef07 = 1,101,438 cycles at 1 MHz, i.e., roughly 1 second.
            ; a few cycles are added to or subtracted from the effective timeout: added because as a counter reset
            ; apparently takes 2 cycles, so the effective periods are $ef02 and $ef09, subtracted because the counters'
            ; difference does not increase by 7 on counter $ef07 reset, but increases by 7 and then decreases by 2.
I have a hunch that you could use something like this to have rather precise measurements using two VIA timers with adjustable periods.
2020-08-03 17:24
Quiss

Registered: Nov 2016
Posts: 37
Quote:

Bonus question: can we use https://en.wikipedia.org/wiki/Chinese_remainder_theorem with two VIA timers to make this more accurate? or is it a pointless exercise?


You don't need to go full Chinese remainder.

Set both timers to free running, and their latches to N and N-1, respectively.

Now, whenever you read out both timers, the difference between them will tell you how often they underflowed, thus giving you another ~16 most significant bits.

(Also see Krill's post: Extending MOS 6522 VIA timers to more than 16 bits without interrupts)
2020-08-03 17:40
Zibri
Account closed

Registered: May 2020
Posts: 304
Quote: To bring the discussion from 1541 Speed Test into the forum....

first lets recapitulate:

The general idea is: have a "marker" on a track, then measure the time for one revolution using timers. Generally there are different ways to achieve this:

- wait for the marker and toggle a IEC line. the C64 measures the time using CIA timer. this is what eg the well known "Kwik Load" copy does, the problem is that it is PAL/NTSC specific, and it can never be 100% exact due to the timing drift between drive and C64.

- wait for the marker and measure the time using VIA timers on the drive. the problem with this is that VIA timers are only 16bit and can not be cascaded, so you either have to measure smaller portions at a time, or rely on the wraparound and the value being in certain bounds at the time you read it.

now, to make either way slightly more accurate, a special kind of reference track can be used. typically this track will contain nothing except one marker - which makes the code a bit simpler and straightforward. this is what 1541 Speed Test does. the DOS also does something similar when formatting, to calculate the gaps. This obviosly has the problem that we are overwriting said track.

Now - the question isn't how to do all this, that's a solved problem. The question is, given a specific implementation, how *accurate* is it actually, and why?

The basic math to calculate the RPM is this:

expected ideal:
300 rounds per minute
= 5 rounds per second
= 200 milliseconds per round
at 1MHz (0,001 milliseconds per clock)
= 200000 cycles per round

to calculate RPM from cycles per round:
RPM = (200000 * 300) / cycles

two little test programs are here: https://sourceforge.net/p/vice-emu/code/HEAD/tree/testprogs/dri.. ... the first reads timer values between each sector header and then the total time for a revolution is accumulated from the delta times. the second leaves the timer running for one revolution and then indirectly gets the time for a revolution from that. to my own surprise, both appear to be accurate down to 3 cycles (in theory the second one should be more accurate, at least thats what i thought. i also expected some more jitter than just 3 cycles)

1541 Speed Test writes a track that contains one long sync, and then 5 regular bytes which serve as the marker. it then reads 6 bytes and measures the time that takes, which equals one revolution. somehow this produces a stable value without any jitter, which was a bit surprising to me too (i expected at least one cycle jitter, due to the sync waiting loops) (i am waiting for the source release and will put a derived test into the vice repo too)

So, again, the question is... how accurate are those and why? (a stable value alone does not tell its accurate). Some details are not quite clear to me, eg if we are writing a reference track, how much will that affect the accuracy of the following measurement? how will the result change when the reference track was written at a different speed than when doing the measuring? Will using a certain speedzone make it more or less accurate?

Bonus question: can we use https://en.wikipedia.org/wiki/Chinese_remainder_theorem with two VIA timers to make this more accurate? or is it a pointless exercise?


"somehow this produces a stable value without any jitter"

because to check for a sync you have to use two
LDA/BMI wait loops.
These induce an error of 6-7 cycles each!

Instead to read "X" bytes you use a single
loop BVC loop
which has only a 2/3 cycle jitter.
2 / 200000 is more accuracy that I wanted to achieve.

Note, don't put in vice repository a "derived" test (i.e. copied). Just put my program.
2020-08-03 17:48
Zibri
Account closed

Registered: May 2020
Posts: 304
Another note:
it's totally useless to use both VIA timers.
Considering the speed range of VICE, the difference between 275 RPM and 325 is 33566.4 cycles which is fine because it's smaller than the 65536 cycles the timer can give us.
Obviously the timer will underflow 3 times.. but we don't care because we already know the range.
Believe me there is no better way to determine the rpm than my program does.
For sure you could have a "sort of" accurate result in other ways but you will need more rounds and mathematical averaging. This is the fastest direct way to get it.
2020-08-03 17:50
Krill

Registered: Apr 2002
Posts: 2821
Quoting Zibri
Note, don't put in vice repository a "derived" test (i.e. copied). Just put my program.
Pretty sure they'll add an unmodified version if you make it VICE test suite compliant (so it can be run in batch mode, without manual intervention).

They did with skew1.prg provided by me (https://sourceforge.net/p/vice-emu/code/HEAD/tree/testprogs/dri..) which also measures RPM, but only as a bonus.
2020-08-03 17:51
Krill

Registered: Apr 2002
Posts: 2821
Quoting Zibri
Another note:
it's totally useless to use both VIA timers.
Considering the speed range of VICE, the difference between 275 RPM and 325 is 33566.4 cycles which is fine because it's smaller than the 65536 cycles the timer can give us.
The point is that 2 timers can give accurate measurements of at least 30 bits, even without hardware cascading.
A revolution takes 200,000 cycles plus/minus tolerance, so you could measure that time pretty much directly.
2020-08-03 18:36
chatGPZ

Registered: Dec 2001
Posts: 11089
The question still is: by doing that, do we gain accurracy over the free running timer? Like Zibri said, we know already we will measure something close to 200000 cycles, and we dont have to be able to measure arbitrary times.

And yes, i'd prefer a simple small non interactive test program, similar to the existing ones :)
2020-08-03 18:44
Krill

Registered: Apr 2002
Posts: 2821
Quoting Groepaz
The question still is: by doing that, do we gain accurracy over the free running timer? Like Zibri said, we know already we will measure something close to 200000 cycles, and we dont have to be able to measure arbitrary times.
Granted, possibly no gain by extending the range. But there may be something with, e.g., using an additional timer with a period co-prime to the main free-running timer (maybe also pretty small, like 3 cycles). Could maybe be used to increase accuracy and counter the polling loop's jitter.

Or a second timer with exactly the polling loop's period... mh. :)
2020-08-03 18:49
Copyfault

Registered: Dec 2001
Posts: 466
Never thought this would become *that* mathmatical ;)

Well, reading the word "Chinese remainder theorem" triggered me, so if we set the two VIAs to different (and coprime) timer values and trigger different irqs, we could implement the chinese remainder theorem 1:1.

But the approach with the differences is even better. While the Chin.remainder theorem states a certain "equality" between different modulo-class-rings, one can proof in a more or less direct way that, given M<N
Z_M  X  Z_N  ->  Z_N; (m, n) |-> n-m

is surjective with kernel isomorphic* to Z_M (the "smaller one").

Putting this straight (and less algebraic;)) this means that the difference (in Z_N, mind!) gives a measure of the relative positions of the numbers in Z_N and Z_M. Aplplying this to continously running timers, it exactly gives the no. of underflows modulo M.

At certain points the difference can result in a negative value; but since we're in modulo-class-rings, there's always a non-negative representative: in Z_N, this means n-m = N+n-m in case of n-m<0.

So the widest range should be achieved by setting one VIA timer to $ffff (as far as I understand timers, this effectively means 65536=$10000 cycles since it underflows after reaching 0) and the other to $fffe. Since the larger value is $ffff, we have N=65536 in the algebraic sense and the modulo is given automagically by the way the binary system works ;)

Really nice! Never thought that such "algebraic nonsense" *does* occur in practice. Makes me happy :)

*) "isomorphic" is usually used in mathmatics when certain abstract construction and maps between them are considered. It extends the idea of "being equal" to these concepts. Here we "only" take a closer look at modulo-class-rings, so it's ok to think of "numbers are equal modulo a certain number" here.
2020-08-03 19:27
Zibri
Account closed

Registered: May 2020
Posts: 304
As already stated in my program instructions, all you have to do is:

"U30"+chr$(tracknumber) (I suggest track 36 but any can be chosen) crates the test track.

"U31" times the "actual track" (so run in a loop after U30 can give you a result every revolution).

The result is on channel #15 and it's a "0" followed by 2 bytes which are the ramainder timer in little endian.

Then to get rpm all you have to do is:

RPM = 6000000000/(196603-Timer)

P.S.
The drive code is the last block of my program.

By doing
LOAD"rpm",8

even without running it the code is already loaded and ready in the drive :D

and you can, for example create the test track by just issuing:
open,15,8,15,"U30"+chr$(36)
get #15, a$,a$,b$
close15
The timer will be: TT=chr$(a$+chr$(0))+chr$(b$+chr$(0))*256
RPM will be as the formula above.

Remember to add 0.5 before doing INT in basic or you'll get a wrong result.

Later today I will post an example in basic that just gives a one shot result if you want.
 
... 263 posts hidden. Click here to view all posts....
 
Previous - 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | ... | 28 - Next
RefreshSubscribe to this thread:

You need to be logged in to post in the forum.

Search the forum:
Search   for   in  
All times are CET.
Search CSDb
Advanced
Users Online
Scooby/G★P/Light
Freeze/Blazon
da Blondie/Resource
Monte Carlos/Cascade
Guests online: 190
Top Demos
1 Next Level  (9.8)
2 Mojo  (9.7)
3 Coma Light 13  (9.7)
4 Edge of Disgrace  (9.6)
5 Comaland 100%  (9.6)
6 No Bounds  (9.6)
7 Uncensored  (9.6)
8 Wonderland XIV  (9.6)
9 The Ghost  (9.6)
10 Bromance  (9.6)
Top onefile Demos
1 It's More Fun to Com..  (9.9)
2 Party Elk 2  (9.7)
3 Cubic Dream  (9.6)
4 Copper Booze  (9.5)
5 Rainbow Connection  (9.5)
6 TRSAC, Gabber & Pebe..  (9.5)
7 Onscreen 5k  (9.5)
8 Dawnfall V1.1  (9.5)
9 Quadrants  (9.5)
10 Daah, Those Acid Pil..  (9.5)
Top Groups
1 Oxyron  (9.3)
2 Nostalgia  (9.3)
3 Booze Design  (9.3)
4 Censor Design  (9.3)
5 Crest  (9.3)
Top Swappers
1 Derbyshire Ram  (10)
2 Jerry  (9.8)
3 Violator  (9.8)
4 Acidchild  (9.7)
5 Starlight  (9.6)

Home - Disclaimer
Copyright © No Name 2001-2024
Page generated in: 0.118 sec.