Code:
ftw var long ; unsigned long ftw; // 32-bit Frequency Tuning Word
f var long BANKA
;/************************************************************************
; * 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) *
; ************************************************************************/
calcFTW: ; void calcFTW(unsigned long f) // calculate AD9850 32-bit "FTW"
; { long c = 1475739526; // the "constant" term
; unsigned char n = 32; //
c VAR LONG BANKA : C=1475739526
n VAR BYTE BANKA : 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: ; //
BCF STATUS,C ; clrc ; // |00
btfss _c+0,0 ; // |00
bra nextbit ; // |00
movf _f+0,W ; // frequency lo |00
addwf _ftw+0,F ; // |00
movf _f+1,W ; // frequency hi |00
addwfc _ftw+1,F ; // |00
movf _f+2,W ; // frequency ul |00
addwfc _ftw+2,F ; // |00
movf _f+3,W ; // frequency uh |00
addwfc _ftw+3,F ; // |00
nextbit: ; // |00
RRCF _ftw+3,F ; // |00
RRCF _ftw+2,F ; // |00
RRCF _ftw+1,F ; // |00
RRCF _ftw+0,F ; // |00
RRCF _c+3,F ; // |00
RRCF _c+2,F ; // |00
RRCF _c+1,F ; // |00
RRCF _c+0,F ; // |00
decfsz _n,F ; // done? yes, skip, else |00
bra mult32x32 ; // |00
movlw 0x80 ; // rounding... |00
addwf _c+3,W ; // " |00
movlw 0 ; // " |00
addwfc _ftw+0,F ; // " |00
addwfc _ftw+1,F ; // " |00
addwfc _ftw+2,F ; // " |00
addwfc _ftw+3,F ; // " |00
ENDASM; }
Return
Bookmarks