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.

    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

  2. #2
    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
       }

  3. #3
    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.

  4. #4
    Join Date
    May 2013
    Location
    australia
    Posts
    2,680


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    mike you may find this interesting
    www.picbasic.co.uk/forum/showthread.php?t=12433
    Warning I'm not a teacher

  5. #5
    Join Date
    Sep 2009
    Posts
    755


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    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.

  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.

    Yes, in XC8 that's how you would address the "local" variables (c, f, and n) using assembly language.

  7. #7
    Join Date
    Sep 2009
    Posts
    755


    Did you find this post helpful? Yes | No

    Default Re: Calculate tuning value for the AD9850 DDS.

    Here it is. It wasn't tested...
    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
    clrc and rrf are pseudo instruction from XC8. So I replaced it with real instruction.

    Usage:

    F=123 : Call calcFTW
    result is in ftw

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