Wagner, Someone must've lit a fire under your ass! I applaud your very thorough investigation. If I may though, let me interject a few comments. 1) The 'auto-reload' algorithm, as you call it, and the phase accumulator are the same when the phase accumulator's delta is 1. Using these two algorithms, there are some frequencies that just cannot be produced accurately. 2) For jitter-less, constant (but programmable) frequency square waves, there's another algorithm. It's analogous to a software PWM. You have two (software) timers. One times the square wave's cycle while the other times the square wave's high time. The square wave's low time is the difference between these two. Using isochronous code in combination with controlled delays, it's possible to generate square waves that have only a single instruction cycle of jitter and a frequency limited to how efficient your code is. Reggie wrote this cute delay routine that can delay between 11 and 256+11 cycles based on the contents of the W register. Using that, I'd expect that the maximum frequency of the square wave to be about 1/30'th to 1/40'th of the instruction frequency. (I'm being generous with the loop overhead and the per-loop calculations.) The caveat of course is that this technique does not lend itself to dual tones like DTMF. 3) Phase accumulators are also useful in conjunction with linear interpolation. Linear interpolation is useless for square waves - or any other discontinuous wave form for that matter. In fact, the error of a phase accumulator produced wave form (generated using linear interpolation) can be ascertained from the first derivative of the wave form. Or more specifically, the Cauchy Remainder Theorem on polynomial interpolation may be used to estimate the error. Good work Wganer. .lo PS. I did not run your program. In addition to distributing the .exe perhaps you should also distribute the source. --- Wagner Lipnharski wrote: > I got interested to analyze the performance of Phase > Accumulators. Paul > was very gentle explaining it, kind enough to type > about it after > midnight and all. > > > I put both versions (auto-reload and phase > accumulator) side by side, > with their pros and cons. I also made a PC program > to calculate the > jitter of the Phase Accumulator technique, you will > see the download > link at the end. > > In both versions, it is necessary a timed routine, > very steady in time, > driven by a timer interrupt or by a non > interruptible software time > loop. Any error or slack in this routine would be > transferred to the > output signal and accumulated along the time. > > AUTO-RELOAD: > ------------ > > The first and old way, using Auto-Reload decrement > (or increment) > counters, is based in load a counter with a certain > value, and decrement > it each time the timer routine loops. When the > counter goes zero, the > routine flips an output port pin, and reloads the > counter with that > certain value again. As each loop of the timer > routine has a specific > and steady period of time, you can say this old way > generates an output > signal at the port pin, that is directly related to > the timer routine > period x the specific reload value. > > Lets say that the timer routine loops once every > millisecond, then the > output can be programmed to flip each 1ms, 2ms, 3ms, > 4ms... and so on, > and you would have only "integers" as result. It is > basically a > multiplier of the timer routine period. As it deals > with periods, the > frequency in Hertz is difficult to produce > constantly as integers > results. > > This routine generates a very steady signal all > along, and its counter > can be used to generate a perfect tooth saw > generator via an DAC. The > use of a even/odd zero flag can be used to read the > counter value, > invert it and generate a nice triangular wave form. > > This routine only outputs something based on the > carry or zero counter, > and no counter bit(s) can be used to identify a half > counting or > something like that. > > The processing at each loop is faster, since > requires only an > instruction to decrement the counter and check for > carry, even that it > is necessary to reload the counter at each carry. > > As you can see, this routine can generate a pulse as > short as the timer > routine period, and long as many bits allocated to > the decrementing > counter. > > > PHASE-ACCUMULATOR: > ------------------ > > The Phase Accumulator way, use a full bits counter > to produce a carry, > or rollover situation. This system requires a timer > routine that > generates pulses in a quantity enough to fit into > the counter in the > period of one second. As Paul said as example; a 16 > bits counter has > 65536 combinations, so it requires a timer routine > that generates 65536 > pulses per second, or a period = 15.295s. Now, > there is this "adder" > value, that represents how many steps the counter > will advance at each > loop of the timer routine. > > If the adder is set to "1", the counter will advance > one by one, it will > take 65536 pulses to generate a carry, so, it will > take a whole one > second, 1 carry per second. > > If the adder is set to "2", the counter will need > 32768 pulses to > generate the carry, and it will take 0.5 second, 2 > carries per second. > > The rollover: > ------------- > If the adders is set to "10", the counter will > advance in 10 steps, so > needing 6553.6 steps..oops, it will carry only at > the 6554th loop, and > will rollover the value (6554-6553.6)*10 = 4, so now > the counter is not > starting from zero, then it is 4 counts shorter, or > 65532. > > Now, the next carry will require 6553.2 steps, ooops > again, it will > carry only at the 6554th loop, and will rollover the > value > (6554-6553.2)*10 = 8, so the counter is again > shorter, or 65528. > > The next carry will require 6552.8, oops again, the > carry will happens > only at the 6553th loop and will rollover > (6553-6552.8)*10 = 2, but > wait, this carry happened one loop count before the > first two above. > This is the jitter generated by this system. Some > pulses are larger, > some are shorter, and in average they generate the > expected pulses per > period of time. > > This system is based in a division factor of a carry > "1" by a fixed > period of time, that generates frequency, so one can > say you set the > "adder" with the frequency, in Hertz, and it > generates that number in > pulses per second. Of course your adder should be > set to the double of > the expected frequency if your routine flips the > PORT pin each time a > carry happens, or set your timer routine with the > double frequency of > the counter bits combination. > > As this routine generates frequency in integers > relative to the counter > bits and timer frequency, the period of those output > pulses are not > integers. > > This routine can also be used to generate wave forms > based on its > counter bits. The advantage is that for example the > counter high order > bit can be considered the polarity, or even > representing the signal > output when the timer routine frequency is equal to > the counter bits > combinations. > > This routine needs extra processing each loop, since > there is an > addition involved. > > If 2^n (n:counter bits) = 1 w (timer routine > period), then this routine > can generate a pulse short as the granularity of the > timer period, and > largest as 1 second. To expand this time, or > increase the counter bits > or increase the timer routine period. > > > RESULTS: > -------- > > It sounds that whenever you need a fixed period of > time (as a time > delay), as any integer multiple of the timer routine > period, you should > use the *auto-reload* technique, and when you need > fixed (jitter) > *frequency* you should use the Phase Accumulator > technique. > > With the *auto-reload* is impossible to generate > 1200 Hz from a 8MHz > crystal, because the division does *not* result in > an integer value, but > you can generate 3ms, 50ms, 60ms, or 139ms based on > a === message truncated === ===== __________________________________________________ Do You Yahoo!? Bid and sell for free at http://auctions.yahoo.com