[time-nuts] 32768 Hz from 10 MHz
Orin Eman
orin.eman at gmail.com
Fri Feb 3 06:15:11 UTC 2012
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.
Here's what I would do in a mix of C and asm:
unsigned char bitmask = 0x80;
unsigned char index = 0xFF;
unsigned char table[256] = { // Calculate using a spreadsheet or similar };
bit OutputBit;
asm {
loop:
BCF STATUS,C
RLF bitmask,F
BTFSS STATUS,C
GOTO IndexOK
RLF bitmask,F ; restore low bit from carry
INCF index,W ; on to the next byte in the table
GOTO DoLookup
IndexOK:
NOP ; equalize time in if/else cases
NOP
MOVF index,W
DoLookup:
CALL TableLookup ; Not defined here, returns value in W
ANDWF bitmask,W
BTFSS STATUS,Z
GOTO ExtraCycle ; 1 cycle if skipped, 2 if executed
ExtraCycle:
}
// Extra delay to get to 38/39 instructions (about 20 instructions if I
counted right)
OutputBit ^= 1; ; Toggle output
goto loop;
This version rotates the mask each time through and increments the index
every 8 times through. You could increment the index each time through and
rotate the mask when the index rolls over. That makes calculating the
table harder though.
No doubt I got the sense of the skips wrong or miscounted instructions
somewhere!
Orin.
More information about the Time-nuts_lists.febo.com
mailing list