unsigned long ftw; // the 32-bit Frequency Tuning Word
/************************************************************************
* Calculate AD9850 'FTW' (Frequency Tuning Word) Mike McLaren *
* *
* The 32-bit 'f' input is frequency*100 (0.01-Hz resolution) which *
* allows scaling the DDS constant up to 32-bits. Multiply the two *
* 32-bit terms and divide the 64-bit product by 2^32. The 32-bit *
* result is the frequency tuning word in the 'ftw' variable. *
* *
* FTW * 2^32 = freq*100 * 2^32/RefClk*2^32/100 *
* FTW * 2^32 = freq*100 * 1475739526 *
* *
* Fitting the frequency*100 value into a 32-bit variable makes our *
* upper frequency limit ~42,949,672.95-Hz. *
* *
* --- target -- ---- ftw ---- --- actual -- *
* 42,949,672.00 1,475,739,493 42,949,672.00 *
* 37,000,000.00 1,271,310,320 37,000,000.01 *
* 25,000,000.00 858,993,459 24,999,999.99 *
* 10,000,000.00 343,597,384 10,000,000.01 *
* 1,000,000.00 34,359,738 999,999.99 *
* 125,000.00 4,294,967 124,999.99 *
* 10,000.00 343,597 9,999.99 *
* *
* XC8 example (42 words, 665 cycles) *
************************************************************************/
void calcFTW(unsigned long f) // calculate AD9850 32-bit "FTW"
{ long c = 1475739526; // the "constant" term
unsigned char n = 32; //
/* *
* multiply 32-bit freq*100 value by our 32-bit "constant" and use *
* the upper 32-bits ('ftw') of the 64-bit result *
* */
asm("mult32x32: "); //
asm("clrc "); // |00
asm("btfss calcFTW@c+0,0 "); // |00
asm("bra nextbit "); // |00
asm("movf calcFTW@f+0,W "); // frequency lo |00
asm("addwf _ftw+0,F "); // |00
asm("movf calcFTW@f+1,W "); // frequency hi |00
asm("addwfc _ftw+1,F "); // |00
asm("movf calcFTW@f+2,W "); // frequency ul |00
asm("addwfc _ftw+2,F "); // |00
asm("movf calcFTW@f+3,W "); // frequency uh |00
asm("addwfc _ftw+3,F "); // |00
asm("nextbit: "); // |00
asm("rrf _ftw+3,F "); // |00
asm("rrf _ftw+2,F "); // |00
asm("rrf _ftw+1,F "); // |00
asm("rrf _ftw+0,F "); // |00
asm("rrf calcFTW@c+3,F "); // |00
asm("rrf calcFTW@c+2,F "); // |00
asm("rrf calcFTW@c+1,F "); // |00
asm("rrf calcFTW@c+0,F "); // |00
asm("decfsz calcFTW@n,F "); // done? yes, skip, else |00
asm("bra mult32x32 "); // |00
asm("movlw 0x80 "); // rounding... |00
asm("addwf calcFTW@c+3,W "); // " |00
asm("movlw 0 "); // " |00
asm("addwfc _ftw+0,F "); // " |00
asm("addwfc _ftw+1,F "); // " |00
asm("addwfc _ftw+2,F "); // " |00
asm("addwfc _ftw+3,F "); // " |00
}