Shahariar
Published © LGPL

Low Cost DDS Function Generator for Makers

Generating Sine, Square, Triangular, Sawtooth Waveform with Direct Digital Synthesizer method using PSoC 4 MCU and few passive components.

IntermediateFull instructions provided3 hours4,026

Things used in this project

Hardware components

PSoC 4 Prototyping Kit
Cypress PSoC 4 Prototyping Kit
×1
Protoboard 4cm X 6 cm Green
×1
Rotary potentiometer (generic)
Rotary potentiometer (generic)
×3
Resistor 1k ohm
Resistor 1k ohm
×1
Resistor 10k ohm
Resistor 10k ohm
×1
Pushbutton switch 12mm
SparkFun Pushbutton switch 12mm
×1
Male Header 40 Position 1 Row (0.1")
Male Header 40 Position 1 Row (0.1")
×1
SparkFun Capacitor 1 nF
×1
Knob for Pots
×1
Resistor 0.05 ohm
Resistor 0.05 ohm
×10

Software apps and online services

PSoC Creator
Cypress PSoC Creator

Hand tools and fabrication machines

Soldering iron (generic)
Soldering iron (generic)

Story

Read more

Schematics

Final Ckt PSoC Internal H/W + External Passive

PSoC Sch

Chip Pin Mapping

External Circuit with Passive components

Connection between the PSoC Cy8C049 kit and Passive components

Code

Complete Code

C/C++
Ver 1.0.0 Freq Stepping, Sweeping, HF Harmonics Filtering included
// Copyright Sucks
// I Copyleft this code



/*
PSoC chip cy8c4245axi-483 with ARM M0 mcu
Operating Voltage 5.0 V
Operating Frequency 48 MHz
*/



#include <project.h>
int value=0;  // dac variable to output proportionate current
int d=1;      // 
int sw = 0;   // variable to switch between wave type
int freq_scaler=0; // takes adc input to adjust freq
int freq_offset=0; // controls minimum value of freq
int freq_stepper=1; // steps freq range 
uint32_t  sine_wave[256] = {
  0x80, 0x83, 0x86, 0x89, 0x8C, 0x90, 0x93, 0x96,
  0x99, 0x9C, 0x9F, 0xA2, 0xA5, 0xA8, 0xAB, 0xAE,
  0xB1, 0xB3, 0xB6, 0xB9, 0xBC, 0xBF, 0xC1, 0xC4,
  0xC7, 0xC9, 0xCC, 0xCE, 0xD1, 0xD3, 0xD5, 0xD8,
  0xDA, 0xDC, 0xDE, 0xE0, 0xE2, 0xE4, 0xE6, 0xE8,
  0xEA, 0xEB, 0xED, 0xEF, 0xF0, 0xF1, 0xF3, 0xF4,
  0xF5, 0xF6, 0xF8, 0xF9, 0xFA, 0xFA, 0xFB, 0xFC,
  0xFD, 0xFD, 0xFE, 0xFE, 0xFE, 0xFF, 0xFF, 0xFF,
  0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFE, 0xFD,
  0xFD, 0xFC, 0xFB, 0xFA, 0xFA, 0xF9, 0xF8, 0xF6,
  0xF5, 0xF4, 0xF3, 0xF1, 0xF0, 0xEF, 0xED, 0xEB,
  0xEA, 0xE8, 0xE6, 0xE4, 0xE2, 0xE0, 0xDE, 0xDC,
  0xDA, 0xD8, 0xD5, 0xD3, 0xD1, 0xCE, 0xCC, 0xC9,
  0xC7, 0xC4, 0xC1, 0xBF, 0xBC, 0xB9, 0xB6, 0xB3,
  0xB1, 0xAE, 0xAB, 0xA8, 0xA5, 0xA2, 0x9F, 0x9C,
  0x99, 0x96, 0x93, 0x90, 0x8C, 0x89, 0x86, 0x83,
  0x80, 0x7D, 0x7A, 0x77, 0x74, 0x70, 0x6D, 0x6A,
  0x67, 0x64, 0x61, 0x5E, 0x5B, 0x58, 0x55, 0x52,
  0x4F, 0x4D, 0x4A, 0x47, 0x44, 0x41, 0x3F, 0x3C,
  0x39, 0x37, 0x34, 0x32, 0x2F, 0x2D, 0x2B, 0x28,
  0x26, 0x24, 0x22, 0x20, 0x1E, 0x1C, 0x1A, 0x18,
  0x16, 0x15, 0x13, 0x11, 0x10, 0x0F, 0x0D, 0x0C,
  0x0B, 0x0A, 0x08, 0x07, 0x06, 0x06, 0x05, 0x04,
  0x03, 0x03, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
  0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x03,
  0x03, 0x04, 0x05, 0x06, 0x06, 0x07, 0x08, 0x0A,
  0x0B, 0x0C, 0x0D, 0x0F, 0x10, 0x11, 0x13, 0x15,
  0x16, 0x18, 0x1A, 0x1C, 0x1E, 0x20, 0x22, 0x24,
  0x26, 0x28, 0x2B, 0x2D, 0x2F, 0x32, 0x34, 0x37,
  0x39, 0x3C, 0x3F, 0x41, 0x44, 0x47, 0x4A, 0x4D,
  0x4F, 0x52, 0x55, 0x58, 0x5B, 0x5E, 0x61, 0x64,
  0x67, 0x6A, 0x6D, 0x70, 0x74, 0x77, 0x7A, 0x7D
};



int main()
{
	//PWM_Start();
  IDAC_Start();
  Opamp_1_Start();
  Opamp_2_Start();
  ADC_Start();
  ADC_StartConvert();
  AMux_Start();

	for(;;)
    {
        // filters out stepping noise, signal will attunate 
        if (sw!=3 && freq_stepper >3)
        {AMux_Connect(0);}
        else
        {AMux_Disconnect(0);}
        
        if (freq_stepper>16)
        {freq_stepper=1;}
        
    
       /////// Following Fn generates sine wave //////
        while(sw==0)
        {
            IDAC_SetValue(sine_wave[value]);
            
            CyDelayCycles(freq_scaler+freq_offset);
            value=value+freq_stepper;
          
                if(value>255)
                {
                value = 0; sw = Status_Register_1_Read();    
                freq_stepper = Status_Register_2_Read() + 1;
                freq_scaler = ADC_GetResult16(0);
                }
            
        }
        ////// Following Fn generates Ramp Wave //////
      while(sw==1)
       {
            IDAC_SetValue(value);
          CyDelayCycles(freq_scaler+freq_offset);
        
            value=value+freq_stepper;
            if(value>255)
            {
             value = 0;
             sw = Status_Register_1_Read();
             freq_stepper = Status_Register_2_Read() + 1;
             freq_scaler = ADC_GetResult16(0);
            }
        }
        ////// Following Fn generates Tri Wave //////
      while(sw==2)
       {
        IDAC_SetValue(value);
      CyDelayCycles(freq_scaler+freq_offset);
        
        if (value<=255-2*(freq_stepper+1) && d == 1)     
         value=value+2*(freq_stepper+1);
        else
        { 
            d=0;sw=Status_Register_1_Read();
            freq_stepper = Status_Register_2_Read() + 1;
        }
        
        if (value>=0+2*(freq_stepper+1) && d == 0)     
         value=value-2*(freq_stepper+1);
        else
        {
            d=1;sw=Status_Register_1_Read();
           freq_scaler=ADC_GetResult16(0);   
        }
       
    }
        ///// Following Fn generates Sq Wave //////
       while(sw==3)
      {
        IDAC_SetValue(value);
        
     while( ADC_IsEndConversion(ADC_RETURN_STATUS)){}
         CyDelayCycles(33*freq_scaler/freq_stepper);
        if (value==0)
        value = 255;
        else
        value = 0;
        sw=Status_Register_1_Read();
        
    //    while( ADC_IsEndConversion(ADC_RETURN_STATUS)){}
        freq_scaler=ADC_GetResult16(0);
        freq_stepper = Status_Register_2_Read() + 1;
            
      }   
     
        
    }
}

DDS Function Generator

C/C++
Ver 1.0.1 working
No preview (download only).

Bootloader

C/C++
No preview (download only).

Credits

Shahariar

Shahariar

74 projects • 265 followers
"What Kills a 'Great life' is a 'Good Life', which is Living a Life Inside While Loop"

Comments