[time-nuts] 32768 Hz from 10 MHz

Dennis Ferguson dennis.c.ferguson at gmail.com
Fri Feb 3 09:08:48 UTC 2012

On 3 Feb, 2012, at 14:15 , Orin Eman wrote:

> On Thu, Feb 2, 2012 at 7:16 PM, Hal Murray <hmurray at megapathdsl.net> wrote:
>>> It's possible to use Bresenham with two integers 10,000,000 and 32,768
>> but I
>>> found no way to perform all the 24-bit calculations on an 8-bit PIC quick
>>> enough. Removing the GCD often helps but in this case the accumulator
>>> remains 3-bytes wide.
>>> To generate 32 kHz you have to toggle a pin and calculate if the next
>> toggle
>>> must be 38 or 39 instructions in the future; all the math must occur
>> within
>>> 37 instructions. That's why I came up with the binary leap year kind of
>>> algorithm; it's as close to math-less as you can get.
>> You missed the simple way.  Table lookup.  :)
>> The table is only 256 slots long.
>> That's toggling between 305 and 306 cycles.  If your CPU uses N clocks per
>> instruction, multiply the table size by N.
> Well, I thought table lookup too, but I figured  a 2048 x 1 table.  Easily
> done with a rotating bit and 256 byte table.
> Assuming clocking a PIC at 10MHz, you have 2,500,000 instructions per
> second.  Since there was talk about time to the next toggle, we have
> 2,500,000/65536 instructions between toggles, ie 38.1470... instructions.
> The fraction turns out to be 301/2048, so you have to distribute 301 extra
> instructions over every 2048 half-periods of the 32768Hz waveform.

I only barely know the instruction set on those processors, but it seems
like it should be way easier than that.  You know it is going to be 38 or
39 instructions, so that only question is when it should be 39.  The value
of 2500000/65536 is 38.1470… in decimal, but in hex it is exactly 26.25a;
that is the 0x26 is 38 decimal while the fractional part is only 10 bits
long.  This means you should be able to compute when the extra cycle is
required by keeping a 16 bit accumulator to which the fractional part
0x25a0 is added at every change and executing the extra instruction when
there is a carry out of that. The seems straight forward.  If `lo' and `hi'
are the two halves of the accumulator then the working part of this becomes
something like (excusing my PIC assembler, which I mostly forget):

    movl    0xa0,w      // low byte of increment into w
    add     w,lo        // add w to lo, may set carry
    movl    0x25,w      // high byte of increment into w
    btfsc   3,0         // skip next if carry clear
    add     one,w       // increment w by one; I'm not sure how to do that
    add     w,hi        // add w to hi, may set carry
    // if carry set here need extra instruction.  Maybe this does it?
    btfss   3,0         // skip if carry set
    goto    blorp       // carry clear, don't execute next instruction
    nop                 // the extra instruction
    // enough instructions more to make 38/39

Maybe someone who knows what they're doing can interpret that?

Dennis Ferguson

More information about the time-nuts mailing list