Calculate tuning value for the AD9850 DDS.


Closed Thread
Results 1 to 17 of 17

Hybrid View

  1. #1
    Join Date
    Jun 2008
    Location
    Varese , Italy
    Posts
    326


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    Hi to all in this forum.
    I am using the magic number to control my AD9850 DDS and it worked very well for years.
    Now I am going to use the AD9912 DDS and I will like to calculate or to have the magic number to control it : the ref clock is 100 MHz internally multiplied by 10 so the real ref should be 1 GHz. I am using PBP 2.50 and longs.
    I understand that the 9912 has a 48 bit tuning word (FTW): what will be the limitations in this case ?
    Thanks in advance for any assistance .
    regards,
    Ambrogio
    iw2fvo

  2. #2
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,624


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    Hi,
    The AD9912 datasheet says: FTW = 2^48 * (fdds / 1GHz) where fdds is the desired frequency and 1GHz is the reference clock.
    As per the Wiki example for the AD9850, but with these numbers instead, you calculate 2^48/1GHz=281475 which is what I believe is the "magic number" you're referring to.

    So, FTW = fdds * 281475 which we can verify against the example in the datasheet:
    19,440,000 * 281475 = 5471874000000 which in reality would result in a frequency 1.6085Hz higher than ideal due to 2^48/1GHz not being exactly 281475. Does it matter? That's up to you.

    Now, LONGS are "only" 32 bits so what's the highest frequency possible? Well, 2^32/281475=15258.788Hz.

    Since the ** operator, when used with LONGs, results in an 48bit wide intermediate result I would guess we could use some trickery and retrieve all 48 bits directly but I don't have time to play around with that right now.

    /Henrik.

  3. #3
    Join Date
    Jun 2008
    Location
    Varese , Italy
    Posts
    326


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    Thanks Henrik for the kind reply on the matter.
    On the AD9850 the FTW is computed by the following : FTW = Frequency ** 2251800.
    I call magic number the " 2251800" constant.
    What will be the constant for the ad9912 DDS?
    How could I determine the frequency limitation due to the longs .. etc ?
    Thanks again for the assistance.
    Regards,
    Ambrgio
    iw2fvo

  4. #4
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,624


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    Did you READ my previous reply?

  5. #5
    Join Date
    Jun 2008
    Location
    Varese , Italy
    Posts
    326


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    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

  6. #6
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    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
       }

  7. #7
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    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.

Similar Threads

  1. OSCTUNE Tuning range
    By MikeBZH in forum Schematics
    Replies: 3
    Last Post: - 8th June 2009, 06:54
  2. Need help in controlling DDS AD9850/51
    By vu2iia in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 7th March 2007, 13:40
  3. RF video reciever - digital tuning
    By RYTECH in forum Schematics
    Replies: 13
    Last Post: - 15th September 2006, 01:05
  4. calculate with date
    By Pedro Pinto in forum mel PIC BASIC Pro
    Replies: 1
    Last Post: - 14th October 2005, 17:49
  5. iButton CRC-8 Calculate
    By Pesa in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 4th May 2005, 10:05

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts