mike you may find this interesting
www.picbasic.co.uk/forum/showthread.php?t=12433
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 09: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
Very interesting. Thank you. I'm not a PBP user so I had no idea inserting an assembly code function into a PBP program was that easy.
I suspect you're coding for an 18F which has RRCF and RRNCF instructions where my example was for an "enhanced mid-range" 16F1823 device which has slightly different RRF, ASRF, and LSRF instructions. Hopefully, those 16F instructions are supported in PBP. Also, when using assembly language, careful attention to banking is required. I found XC8 assigned the 'ftw' variable in Bank 0 RAM and the other variables were assigned in the "common" 0x70..0x7F area.
One might conclude that implementing an assembly language method in a program could save hundreds of words of program memory and thousands of instruction cycles processing time but it also requires careful attention to detail and environment.
Hopefully, someone may be able to take advantage of a similar method in their PBP AD9850/AD9851 or Si5351 Digital VFO project.
Cheerful regards, Mike, K8LH
Last edited by Mike, K8LH; - 20th July 2018 at 16:53.
I use 18F for 99% of my project. So by default i go to 18F ASM. Also pbp for 16F doesn't support long variables(because of large overhead, but in my opinion it should).
You are right, but I put all variables used in ASM into BANKA. So you dont need banking, at all. I forgot to do that here.
Here is corrected version.
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