A sine wave generator using AD9833 and AD9850 using STM32F103RB

Dependencies:   mbed

This is a sine wave generator using DDS IC' AD9833 and AD9850. The STM32F1 microcontroller produces the SPI commands for the two DDS.

Learn more about STM32F1 in my blog: https://www.teachmemicro.com

AD9850.cpp

Committer:
roland_tmm
Date:
2017-11-21
Revision:
2:602f7589c53e
Parent:
1:9dcccb399f0b

File content as of revision 2:602f7589c53e:

/******************************************************************************************************************
 * AD9850 library for AD9850
 * Created 11/21/2017
 * Roland Pelayo 
 *
 * Use this library freely
 *
 * Hardware connections : 
 * W_CLK   -> any pin
 * FQ_UD   -> any pin
 * DATA/D7 -> any pin
 * RESET   -> any pin
 *
 * Functions :
 * dds.begin(W_CLK pin, FQ_UD pin, DATA pin, RESET pin); Initialize the output pins and master reset the AD9850 
 * dds.calibrate(frequency); Compensation of crystal oscillator frequency
 * dds.setfreq(frequency,phase); frequency in Hz, phase coded on 5 bits
 * dds.down(); power down mode reducing the dissipated power from 380mW to 30mW @5V
 * dds.up(); wake-up the AD9850
 *
 * AD9850 datasheet at http://www.analog.com/static/imported-files/data_sheets/AD9850.pdf
 *
 *****************************************************************************************************************/

#include "AD9850.h"
#include "mbed.h"

#define W_CLK PB_10
#define FQ_UD PB_11
#define DATA PB_1
#define RESET PB_0

SPI SPI_dev2(DATA, PB_8, W_CLK);

DigitalOut wclk(W_CLK);
DigitalOut fq_ud(FQ_UD);
DigitalOut dat(DATA);
DigitalOut res(RESET);

AD9850::AD9850() {

}

void AD9850::Begin() {
    SPI_dev2.format(16,0); 
    deltaphase = 0;
    phase = 0;
    calibFreq = 125000000;
    begin_priv();
}

void AD9850::begin_priv() {
   
    res = 0;
    wait_us(5);
    res = 1;
    wait_us(5);
    res = 0;
    
    wclk = 0;
    wait_us(5);
    wclk = 1;
    wait_us(5);
    wclk = 0;   
   
    fq_ud = 0;
    wait_us(5);
    fq_ud = 1;
    wait_us(5);
    fq_ud = 0;
    
}

void AD9850::update() {
    uint32_t d,p;
    for (int i=0; i<4; i++, deltaphase>>=8) {
     d = ReverseBits(deltaphase);
     SPI_dev2.write((d>>16) & 0x000000FF);
     SPI_dev2.write(d & 0x000000FF);
    // shiftOut(DATA, W_CLK, LSBFIRST, deltaphase & 0xFF);
    }
    p = ReverseBits(phase);
    SPI_dev2.write((p>>16) & 0x000000FF);
    SPI_dev2.write(p & 0x000000FF);
    //shiftOut(DATA, W_CLK, LSBFIRST, phase & 0xFF);
    fq_ud = 0;
    wait_us(5);
    fq_ud = 1;
    wait_us(5);
    fq_ud = 0;
}


void AD9850::SetDDSFrequency(double f, uint8_t p) {
    deltaphase = f * 4294967296.0 / calibFreq;
    phase = p << 3;
    update();
}


void AD9850::down() {
    fq_ud = 0;
    wait_us(5);
    fq_ud = 1;
    wait_us(5);
    fq_ud = 0;
    SPI_dev2.write((ReverseBits(0x00000004))>>16);
    SPI_dev2.write(ReverseBits(0x00000004));
    //shiftOut(DATA, W_CLK, LSBFIRST, 0x04);
    fq_ud = 0;
    wait_us(5);
    fq_ud = 1;
    wait_us(5);
    fq_ud = 0;
}
    

void AD9850::up() {
    update();
}


void AD9850::CalibrateDDS(double TrimFreq)
{
    calibFreq = TrimFreq;
}

int AD9850::ReverseBits(int value)
{
// Unfortunately need to invert bit order of the desired frequency setting since MBED only allows for MSB first from SPI. We need LSB first for AD9850
    int mask=0;;
    int i=0;
    int target=0;
    int bitTarget=0x80000000; // Hard-wired for 32-bit inversion

    for (i=0;i<32;i++) { // ditto
        mask=1<<i;   
        bitTarget=1<<(31-i); // ditto

        if(value & mask)
            target=target | bitTarget;
    } 
    return target;
}