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
   }