Code:
unsigned char ftw[8]; // ftw calculation array
/************************************************************************
* Calculate AD9850 'FTW' (Frequency Tuning Word) *
* *
* 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 result by 2^32 (use the upper *
* four bytes) for the 32-bit 'FTW'. *
* *
* 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 764 cycles *
* 37,000,000.00 1,271,310,320 37,000,000.01 764 " *
* 25,000,000.00 858,993,459 24,999,999.99 764 " *
* 10,000,000.00 343,597,384 10,000,000.01 764 " *
* 1,000,000.00 34,359,738 999,999.99 764 " *
* 125,000.00 4,294,967 124,999.99 764 " *
* 10,000.00 343,597 9,999.99 764 " *
* *
* XC8 example (50 words, <1000 cycles) *
************************************************************************/
void calcFTW(unsigned long f) // calculate AD9850 32-bit "FTW"
{ long c = 1475739526; // the "constant" term
asm("movlb _ftw/128 "); // bank 0 |00
asm("clrf _ftw+0 "); // clear FTW array |00
asm("clrf _ftw+1 "); // " |00
asm("clrf _ftw+2 "); // " |00
asm("clrf _ftw+3 "); // " |00
asm("clrf _ftw+4 "); // " |00
asm("clrf _ftw+5 "); // " |00
asm("clrf _ftw+6 "); // " |00
asm("clrf _ftw+7 "); // " |00
asm("bsf _ftw+3,7 "); // loop count (32 iterations) |00
/* *
* multiply 32-bit freq*100 value by our 32-bit "constant" and use *
* the upper 32-bits of the 64-bit result ftw[4..7] as the "FTW". *
* */
asm("mult32x32: "); //
// asm("rrf calcFTW@c+0,W "); // preserve 'constant" variable |00
asm("rrf calcFTW@c+3,F "); // constant uh |00
asm("rrf calcFTW@c+2,F "); // constant ul |00
asm("rrf calcFTW@c+1,F "); // constant hi |00
asm("rrf calcFTW@c+0,F "); // constant lo |00
asm("skipc "); // |00
asm("bra nextbit "); // |00
asm("movf calcFTW@f+0,W "); // frequency lo |00
asm("addwf _ftw+4,F "); // |00
asm("movf calcFTW@f+1,W "); // frequency hi |00
asm("addwfc _ftw+5,F "); // |00
asm("movf calcFTW@f+2,W "); // frequency ul |00
asm("addwfc _ftw+6,F "); // |00
asm("movf calcFTW@f+3,W "); // frequency uh |00
asm("addwfc _ftw+7,F "); // |00
asm("nextbit: "); // |00
asm("rrf _ftw+7,F "); // |00
asm("rrf _ftw+6,F "); // |00
asm("rrf _ftw+5,F "); // |00
asm("rrf _ftw+4,F "); // |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("skipc "); // done? yes, skip, else |00
asm("bra mult32x32 "); // |00
asm("movlw 0x80 "); // rounding... |00
asm("addwf _ftw+3,W "); // " |00
asm("movlw 0 "); // " |00
asm("addwfc _ftw+4,F "); // " |00
asm("addwfc _ftw+5,F "); // " |00
asm("addwfc _ftw+6,F "); // " |00
asm("addwfc _ftw+7,F "); // " |00
}
Bookmarks