| |
chatGPZ
Registered: Dec 2001 Posts: 11378 |
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? |
|
... 263 posts hidden. Click here to view all posts.... |
| |
Zibri Account closed
Registered: May 2020 Posts: 304 |
Quoting ZeSmasherCiao Zibri. just a little request from me, then I'll follow this interesting thread in silence again...
Quote:I was expecting curiosity about this program and I even prepared a document which explains everything I learnt so far on the 1541 and some techniques rarely (or never) used before. Nothing fancy. Just the result of a few weeks of study, from the schematics up to ROM disassembly (most of online ROM disassemblies have a lot of logical errors inside).
But after all this "drama" I really lost interest.
please don't! I'd really appreciate if you'll publish that txt one day. I'm not saying I'll understand much of what you discovered, but others will. sharing is caring. grazie! :)
Don't worry.. I will release that too.
Sometimes I just get itchy when some ignorant with an inferior program launches accusations and asks for proof when CODE is all the proof you need.
He spoke about theory but in practice, before mine there was no accurate program.
Anyway, don't worry, if anyone is interested I am happy to discuss it, but don't overestimate me.. I am no Krill :D
Prego. :D |
| |
Zibri Account closed
Registered: May 2020 Posts: 304 |
Quoting KrillQuoting ZibriMy program writes at the lowest density using "00" clocks in 1c00 which is synchronous with the cpu clock. Yes, you're operating on track 36, which is in the lowest density zone of tracks 31 and up.
I have a hunch that operating on the highest density instead would somewhat improve accuracy, but this of course on top of inaccuracies that are orders of magnitude bigger than 1 MHz clock cycles. :)
Well.. density as you know is not bound to tracks... I coould use density 00 even for track #1.
I saw no praticular improvement by using track 1 instead of 36 or 42 even. But I also feel that maybe I am missing something.
The important thing for now is that my program works, it's stable and has accurate results (as useful/useless they can be).
I really don't know if my program is more accurate because is better coded or has a better method.
In theory the waitforsec0 should work but I have see no implementation of that method giving accurate results in any program I tested. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11378 |
The problem is that you are mistaking metastability for accurracy. your code shows the same 3 cycles jumping numbers as the sector0 waiting if you change it slightly (constant time, which does not affect accurracy at all). Likewhise if someone is really bored, he can probably shuffly cycles around in the sector0 waiting code and make it metastable too.
And yes, the whole thread is about theory and methods, not bickering about someone elses code. |
| |
Copyfault
Registered: Dec 2001 Posts: 476 |
Quoting KrillThis is also one of the basic techniques as used for stabilising raster routines.
Depending on density (track zone), there are a nominal 26/28/30/32 cycles between two GCR bytes rolling in from disk.
After having synced to the first byte using a plain "bvc *", delay according to density such that a "bvc * + 2" would take 2 cycles if byte-sync (branch not taken) or 3 cycles if no byte-sync (branch taken). We're now down to a one-cycle jitter. Repeat to get down to 0 cycles.[...] Just a thought: couldn't it be done by using an auxiliary timer that "measures" the potential variance?
Something like:
1. start a 3-cycle-timer (running continously)
2. wait for sync
3. start main timer (used for speed calculation later) + in the same moment(=directly after main timer start) save the value of the aux timer as a reference value
4. wait for sync
5a. calculate the speed with the main timer
5b. calculate the differnce between the current value of the aux timer and the ref value stored before (this should be the variance)
Maybe I'm on the wrong track... after all, I guess the remaining 2-cycle-jittering is not worth the trouble.
Something that really bugs me in the chosen approach is the non-linearity: the "resolution" of the speed-value is seemingly higher the slower the drive is. Since we do a const/x-type calculation, this is no surprise. Is there really no sane way to precisely determine the position on a test-track after a constant number of cycles? This would enable us to have a linear dependance, i.e. drivespeed = byte / c, with constant c and the byte being given by the position on the track.
I slowly start to understand more and more that there is no good way to do this with the given properties of the 1541. Guess I have to accept the non-linear approach as is. But someone please prove me wrong;) |
| |
Zibri Account closed
Registered: May 2020 Posts: 304 |
Quoting GroepazAnd yes, the whole thread is about theory and methods, not bickering about someone elses code. Which is exactly what you are doing from the start. So stop. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11378 |
Quote:Which is exactly what you are doing from the start. So stop.
I have exactly ONCE posted something around those lines, and immediatly corrected myself and apologized. Since then, you are flooding this thread with how great your code is and how much everyone elses sucks. Indeed, please stop. It doesnt contribute anything to this thread at all. Do you realize Krill pretty much acknowledged what i wrote in #30? |
| |
Zibri Account closed
Registered: May 2020 Posts: 304 |
Quoting Copyfault Guess I have to accept the non-linear approach as is. But someone please prove me wrong;) I can't. I think you are right. I had the same thoughts.
About the 2 cycle jitter I also thought of writing 5 bytes + 1 bit. In that way, reading the last byte should tell us it there was a jitter or not.
But again.. I don't think if that is relevant/useful at all. |
| |
Zibri Account closed
Registered: May 2020 Posts: 304 |
Quoting GroepazDo you realize Krill pretty much acknowledged what i wrote in #30? Sure he did. And do you realize you (or anyone else) were not able to implement it right? At the time I released my program there was no accurate program released.
Please, really, stop this. |
| |
chatGPZ
Registered: Dec 2001 Posts: 11378 |
It doesnt matter who implemented what. The thread is about theories and methods, not someones code.
But now that you acknowledge that what i wrote in #30 is actually correct, you might want to reread some of the thread. It's a step forwared afterall. |
| |
Krill
Registered: Apr 2002 Posts: 2971 |
Quoting CopyfaultJust a thought: couldn't it be done by using an auxiliary timer that "measures" the potential variance?
Something like:
1. start a 3-cycle-timer (running continously)
2. wait for sync
3. start main timer (used for speed calculation later) + in the same moment(=directly after main timer start) save the value of the aux timer as a reference value
4. wait for sync
5a. calculate the speed with the main timer
5b. calculate the differnce between the current value of the aux timer and the ref value stored before (this should be the variance)
Thought about such an approach as well, but i think it falls flat due to the fact that the bvc polling loop has a given granularity of N = 3 cycles.
You start an aux timer before the loop, run for N * 3 cycles, then read the aux timer. It will have run for N * 3 plus a constant number of cycles and not tell you anything below that granularity.
What might work is controlling a cycle-counting timer in hardware via the byte-sync signal, but afaik there is not such facility in the 1541. |
Previous - 1 | ... | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | ... | 28 - Next |