sorry Henrik:
I do not want you to hurry at all.
Just in case you will have time ... it will be very interesting result for all members of the radio hams club here.
thanks for all again
regards,
iw2fvo
sorry Henrik:
I do not want you to hurry at all.
Just in case you will have time ... it will be very interesting result for all members of the radio hams club here.
thanks for all again
regards,
iw2fvo
I enjoyed your article, Henrik, but I'm shocked at the processing overhead. I wrote and tested a simple calc_ftw() function in XC8, really not much more than a basic 32x32 multiplication routine, and I was wondering if something similar would be worth implementing in PBP?
Cheerful regards, Mike
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 }
Here's a slightly optimized version of the AD9850 calcFTW() function (XC8) from the previous post. This version is smaller and nearly 100 cycles faster weighing in at 42 words and 665 cycles.
I hope someone can take advantage of it and turn it into a PBP function.
Code:unsigned long ftw; // 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 }
Last edited by Mike, K8LH; - 17th July 2018 at 08:48.
mike you may find this interesting
www.picbasic.co.uk/forum/showthread.php?t=12433
Warning I'm not a teacher
Mike,
It can be almost copy/paste in PBP. I can try to sort details to work in PBP. But I don't understand what is calcFTW@c,@f,@n... Is it just variables declared in function?
Can you explain?
Last edited by pedja089; - 19th July 2018 at 10:14.
Yes, in XC8 that's how you would address the "local" variables (c, f, and n) using assembly language.
Here it is. It wasn't tested...
clrc and rrf are pseudo instruction from XC8. So I replaced it with real instruction.Code:ftw var long ; unsigned long ftw; // 32-bit Frequency Tuning Word f var long ;/************************************************************************ ; * 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 : C=1475739526 n VAR BYTE : 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
Usage:
F=123 : Call calcFTW
result is in ftw
Bookmarks