Total Pageviews

Showing posts with label DDS. Show all posts
Showing posts with label DDS. Show all posts

Thursday, April 2, 2015

Touch screen DDS with AD9850 and Arduino

   With a touch screen display like this:
who work fine with SWTFT library from Smoke and WiresI write a sketch for a virtual keyboard... after some tests, I decided to use the DDS module with AD9850 (see article Signal generator with AD9850 and Arduino) together with this display and made a "touch screen DDS".
   Display is made as a shield for Arduino Uno/Mega boards and use a lot of outputs...
 I designed a intermediate shield for disconnect the microSD and connect the AD9850 module:
   Real, the and shield and modules:
   My sketch use library for control the display from Smoke and Wires and use info for control the AD9850 from http://webshed.org/wiki/AD9850_Arduino:
// Code for TFT shield display provided by Smoke And Wires
// http://www.smokeandwires.co.nz
// This code has been taken from the Adafruit TFT Library and modified
//  by us for use with our TFT Shields / Modules
// For original code / licensing please refer to
// https://github.com/adafruit/TFTLCD-Library

// adapted sketch by niq_ro from http://arduinotehniq.blogspot.com/
// http://nicuflorica.blogspot.ro/
// http://www.tehnic.go.ro
// http://www.niqro.3x.ro
// original virtual keyboard with DDS with AD8959 by niq_ro
// ver. 1m4a: 30.03.2015, Craiova - Romania

#include <Adafruit_GFX.h>    // Core graphics library
#include "SWTFT.h" // Hardware-specific library

// The control pins for the LCD can be assigned to any digital or
// analog pins...but we'll use the analog pins as this allows us to
// double up the pins with the touch screen (see the TFT paint example).
// #define LCD_CS A3 // Chip Select goes to Analog 3
// #define LCD_CD A2 // Command/Data goes to Analog 2
// #define LCD_WR A1 // LCD Write goes to Analog 1
// #define LCD_RD A0 // LCD Read goes to Analog 0

// #define LCD_RESET A4 // Can alternately just connect to Arduino's reset pin

// When using the BREAKOUT BOARD only, use these 8 data lines to the LCD:
// For the Arduino Uno, Duemilanove, Diecimila, etc.:
//   D0 connects to digital pin 8  (Notice these are
//   D1 connects to digital pin 9   NOT in order!)
//   D2 connects to digital pin 2
//   D3 connects to digital pin 3
//   D4 connects to digital pin 4
//   D5 connects to digital pin 5
//   D6 connects to digital pin 6
//   D7 connects to digital pin 7
// For the Arduino Mega, use digital pins 22 through 29
// (on the 2-row header at the end of the board).

#include <TouchScreen.h>


#define YP A1  // must be an analog pin, use "An" notation!
#define XM A2  // must be an analog pin, use "An" notation!
#define YM 7   // can be a digital pin
#define XP 6   // can be a digital pin

#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// For the one we're using, its 300 ohms across the X plate
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

// Assign human-readable names to some common 16-bit color values:
#define BLACK   0x0000
#define BLUE    0x001F
#define RED     0xF800
#define GREEN   0x07E0
#define CYAN    0x07FF
#define MAGENTA 0xF81F
#define YELLOW  0xFFE0
#define WHITE   0xFFFF
#define ROZ     0xFBE0
#define GRI     0xBDF7
// http://stackoverflow.com/questions/13720937/c-defined-16bit-high-color
// http://wiibrew.org/wiki/U16_colors

SWTFT tft;

#define BOXSIZE 80
#define BOXSIZE2 60
#define PENRADIUS 3

int ics; 
int numar, ics0, igr0, pas; 

#include <EEPROM.h>
long n1, n2, n3, n4, n5, n6, n7, n8; // number for frequency;
long frecv; // value for frecvency;
byte cifru; 

//Setup some items
//#define W_CLK 13   // Pin 13 - connect to AD9850 module word load clock pin (CLK)
#define CLOCK 13
//#define FQ_UD 12   // Pin 12 - connect to freq update pin (FQ)
#define LOAD 12
#define DATA 11   // Pin 11 - connect to serial data load pin (DATA)
#define RESET 10  // Pin 10 - connect to reset pin (RST) 
//#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
#define DDS_CLOCK 125000000 // http://webshed.org/wiki/AD9850_Arduino
//#define DDS_CLOCK 125000000

void setup(void) {

pinMode (DATA,  OUTPUT); 
pinMode (CLOCK, OUTPUT); 
pinMode (LOAD,  OUTPUT); 
pinMode (RESET, OUTPUT); 
  
AD9850_init();
AD9850_reset();
//SetFrequency(15000);
zaibar();
SetFrequency(frecv);
  
  Serial.begin(9600);
  Serial.print(F("DDS with AD9850 "));
  Serial.println("made by niq_ro");
  
  tft.reset();
  
  uint16_t identifier = tft.readID();

  Serial.print(F("LCD driver chip: "));
  Serial.println(identifier, HEX);
 
  tft.begin(identifier);

  tft.fillScreen(BLACK);
  tft.fillRect(0, 0, 320, 240, BLACK);
//  tft.setRotation(0);
//  tft.setCursor(5, 100);
  tft.setTextColor(RED);  tft.setTextSize(2);
//  tft.println("Acces control");
  tft.setCursor(30, 120);
  tft.println("DDS with AD9850");
  tft.setCursor(20, 150);
  tft.setTextColor(YELLOW);
  tft.println("on touch display");
  tft.setCursor(70, 180);
  tft.setTextColor(BLUE);
  tft.println("by niq_ro");
  tft.setCursor(75, 210);
  tft.setTextColor(ROZ);
  tft.println("ver. 1.4a");
  

delay(2000);
tft.fillRect(0, 0, 320, 240, BLACK);

numar = 0;
ics0 = 10;
igr0 = 280;
pas = 18;
frecv = 0;
  
//tft.setRotation(0);
 stergere ();

 cifre ();
 caractere();

}

#define MINPRESSURE 10
#define MAXPRESSURE 1000


void loop()
{
    
  // Recently Point was renamed TSPoint in the TouchScreen library
  // If you are using an older version of the library, use the
  // commented definition instead.
  // Point p = ts.getPoint();
  TSPoint p = ts.getPoint();

  // if sharing pins, you'll need to fix the directions of the touchscreen pins
  //pinMode(XP, OUTPUT);
  pinMode(XM, OUTPUT);
  pinMode(YP, OUTPUT);
  //pinMode(YM, OUTPUT);

  // we have some minimum pressure we consider 'valid'
  // pressure of 0 means no pressing!

  if (p.z > MINPRESSURE && p.z < MAXPRESSURE) {
  //   tft.setTextSize(4);
     // scale from 0->1023 to tft.width
    p.x = tft.width()-(map(p.x, TS_MINX, TS_MAXX, tft.width(), 0));
    p.y = tft.height()-(map(p.y, TS_MINY, TS_MAXY, tft.height(), 0));
 
    if (p.y < BOXSIZE2) {   // fist line (0, 1 & 2)
         if (p.x < BOXSIZE) { 
         tft.fillRect(0, 0, BOXSIZE, BOXSIZE2, GRI); // one       
         tft.setTextColor(BLACK);
         tft.setCursor(30, 20);
         tft.println("1");
 //        caracter(1);
int ics1 = ics0+pas*numar;
caracters(1,ics1,igr0);
cifru = 1;
         delay (200);
         tft.fillRect(0, 0, BOXSIZE, BOXSIZE2, RED); // one       
         tft.setTextColor(WHITE);
         tft.setCursor(30, 20);
         tft.println("1");

       } else if (p.x < BOXSIZE*2) {
         tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE2, GRI);  // two
         tft.setTextColor(BLACK);
         tft.setCursor(110, 20);
         tft.println("2");
//         caracter(2);
int ics1 = ics0+pas*numar;
caracters(2,ics1,igr0);
cifru = 2;
         delay (200);
         tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE2, YELLOW);  // two
         tft.setTextColor(BLACK);
         tft.setCursor(110, 20);
         tft.println("2");
         
        } else if (p.x < BOXSIZE*3) {
         tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE2, GRI); // three
         tft.setTextColor(BLACK);
         tft.setCursor(190, 20);
         tft.println("3");
//         caracter(3);
int ics1 = ics0+pas*numar;
caracters(3,ics1,igr0);
cifru = 3;
         delay (200);
         tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE2, BLUE); // three
         tft.setTextColor(WHITE);
         tft.setCursor(190, 20);
         tft.println("3");
       }
   //      numar = numar + 1;
    }
    
  if ((p.y < BOXSIZE2*2) && (p.y > BOXSIZE2)) {   // second line (4, 5 & 6)
         if (p.x < BOXSIZE) { 
         tft.fillRect(0, BOXSIZE2, BOXSIZE, BOXSIZE2, GRI); // four       
         tft.setTextColor(BLACK);
         tft.setCursor(30, 80);
         tft.println("4");
int ics1 = ics0+pas*numar;
caracters(4,ics1,igr0);
cifru = 4;
//         caracter(4);
         delay (200);
         tft.fillRect(0, BOXSIZE2, BOXSIZE, BOXSIZE2, CYAN); // four 
         tft.setTextColor(BLACK);
         tft.setCursor(30, 80);
         tft.println("4");

       } else if (p.x < BOXSIZE*2) {
         tft.fillRect(BOXSIZE, BOXSIZE2, BOXSIZE, BOXSIZE2, GRI);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 80);
         tft.println("5");
int ics1 = ics0+pas*numar;
caracters(5,ics1,igr0);
cifru = 5;
//         caracter(5);
         delay (200);
         tft.fillRect(BOXSIZE, BOXSIZE2, BOXSIZE, BOXSIZE2, GREEN);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 80);
         tft.println("5");
         
        } else if (p.x < BOXSIZE*3) {
         tft.fillRect(BOXSIZE*2, BOXSIZE2, BOXSIZE, BOXSIZE2, GRI); // six
         tft.setTextColor(BLACK);
         tft.setCursor(190, 80);
         tft.println("6");
int ics1 = ics0+pas*numar;
caracters(6,ics1,igr0);
cifru = 6;
//         caracter(6);
         delay (200);
         tft.fillRect(BOXSIZE*2, BOXSIZE2, BOXSIZE, BOXSIZE2, MAGENTA); // six
         tft.setTextColor(WHITE);
         tft.setCursor(190, 80);
         tft.println("6");
       }
    //     numar = numar + 1;
  }

if ((p.y < BOXSIZE2*3) && (p.y > BOXSIZE2*2)) {   // second line (7, 8 & 9)
         if (p.x < BOXSIZE) { 
         tft.fillRect(0, BOXSIZE2*2, BOXSIZE, BOXSIZE2, GRI); // four       
         tft.setTextColor(BLACK);
         tft.setCursor(30, 140);
         tft.println("7");
int ics1 = ics0+pas*numar;
caracters(7,ics1,igr0);
cifru = 7;
//         caracter(7);
         delay (200);
         tft.fillRect(0, BOXSIZE2*2, BOXSIZE, BOXSIZE2, RED); // four 
         tft.setTextColor(WHITE);
         tft.setCursor(30, 140);
         tft.println("7");

       } else if (p.x < BOXSIZE*2) {
         tft.fillRect(BOXSIZE, BOXSIZE2*2, BOXSIZE, BOXSIZE2, GRI);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 140);
         tft.println("8");
int ics1 = ics0+pas*numar;
caracters(8,ics1,igr0);
cifru = 8;
//         caracter(8);
         delay (200);
         tft.fillRect(BOXSIZE, BOXSIZE2*2, BOXSIZE, BOXSIZE2, YELLOW);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 140);
         tft.println("8");
         
        } else if (p.x < BOXSIZE*3) {
         tft.fillRect(BOXSIZE*2, BOXSIZE2*2, BOXSIZE, BOXSIZE2, GRI); // six
         tft.setTextColor(BLACK);
         tft.setCursor(190, 140);
         tft.println("9");
//         caracter(9);
int ics1 = ics0+pas*numar;
caracters(9,ics1,igr0);
cifru = 9;
         delay (200);
         tft.fillRect(BOXSIZE*2, BOXSIZE2*2, BOXSIZE, BOXSIZE2, BLUE); // six
         tft.setTextColor(WHITE);
         tft.setCursor(190, 140);
         tft.println("9");
       }
  //       numar = numar + 1;
 }

if ((p.y < BOXSIZE2*4) && (p.y > BOXSIZE2*3)) {   // second line (*, 0 & #)
/*
       if (p.x < BOXSIZE) { 
         tft.fillRect(0, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GRI); // four       
         tft.setTextColor(BLACK);
         tft.setCursor(30, 200);
         tft.println("*");
int ics1 = ics0+pas*numar;
caracters(10,ics1,igr0);
//         caracter(10);
         delay (200);
         tft.fillRect(0, BOXSIZE2*3, BOXSIZE, BOXSIZE2, CYAN); // four 
         tft.setTextColor(BLACK);
         tft.setCursor(30, 200);
         tft.println("*");

       } else
   */   
       if ((p.x > BOXSIZE) && (p.x < BOXSIZE*2))  {
         tft.fillRect(BOXSIZE, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GRI);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 200);
         tft.println("0");
//         caracter(0);
int ics1 = ics0+pas*numar;
caracters(0,ics1,igr0);
cifru = 0;
         delay (200);
         tft.fillRect(BOXSIZE, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GREEN);  // five
         tft.setTextColor(BLACK);
         tft.setCursor(110, 200);
         tft.println("0");
         
        }
 /*
        else if (p.x < BOXSIZE*3) {
         tft.fillRect(BOXSIZE*2, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GRI); // six
         tft.setTextColor(BLACK);
         tft.setCursor(190, 200);
         tft.println("#");
int ics1 = ics0+pas*numar;
caracters(11,ics1,igr0);
//         caracter(11);
         delay (200);
         tft.fillRect(BOXSIZE*2, BOXSIZE2*3, BOXSIZE, BOXSIZE2, MAGENTA); // six
         tft.setTextColor(WHITE);
         tft.setCursor(190, 200);
         tft.println("#");
       }
*/       
       
// numar = numar + 1;
     }
//caractere();

  numar = numar + 1;
memorie(cifru,numar);
Serial.print(cifru);

  if (numar == 2) numar = numar +1;
  if (numar == 6) numar = numar +1;

  if (numar == 10) {
    tft.setTextColor(YELLOW);
     tft.setTextSize(3);
         tft.setCursor(200, 250);
         tft.println("ok");

 Serial.print(" --> "); 
// read eeprom memory and calculate the stored number (freqvency)
zaibar(); 

 Serial.print(frecv);
 Serial.println("Hz");
 Serial.println("---------");
  Serial.print(frecv);
/*
  Serial.println(frecv);
          Serial.println("---------");
          for (int j=11; j<19; j++)
          {
           Serial.print(EEPROM.read(j));
          }
 */
   delay (3000);
 tft.fillRect(0, 310 , 239, 5, BLACK);   // for testing   
 tft.fillRect(199, 249 , pas*2+2, 30, BLACK);   // for testing   
//   caractere();
   numar = 0;
        
  }
  }

  
}  // end main loop


void cifre ()
{
// number for "buttons"
 tft.setTextSize(4);
 tft.setTextColor(WHITE);
 tft.setCursor(30, 20);
 tft.println("1");
 tft.setTextColor(BLACK);
 tft.setCursor(110, 20);
 tft.println("2");
 tft.setTextColor(WHITE);
 tft.setCursor(190, 20);
 tft.println("3");
 tft.setTextColor(BLACK);
 tft.setCursor(30, 80);
 tft.println("4");
 tft.setTextColor(BLACK);
 tft.setCursor(110, 80);
 tft.println("5");
 tft.setTextColor(WHITE);
 tft.setCursor(190, 80);
 tft.println("6");
 tft.setTextColor(WHITE);
 tft.setCursor(30, 140);
 tft.println("7");
 tft.setTextColor(BLACK);
 tft.setCursor(110, 140);
 tft.println("8");
 tft.setTextColor(WHITE);
 tft.setCursor(190, 140);
 tft.println("9");
// tft.setTextColor(BLACK);
// tft.setCursor(30, 200);
// tft.println("*");
 tft.setTextColor(BLACK);
 tft.setCursor(110, 200);
 tft.println("0");
// tft.setTextColor(WHITE);
// tft.setCursor(190, 200);
// tft.println("#");
}

void stergere ()
{
//      Serial.println("erase");
// firs line
  tft.fillRect(0, 0, BOXSIZE, BOXSIZE2, RED); // one
  tft.fillRect(BOXSIZE, 0, BOXSIZE, BOXSIZE2, YELLOW);  // two
  tft.fillRect(BOXSIZE*2, 0, BOXSIZE, BOXSIZE2, BLUE); // three
// second line
  tft.fillRect(0, BOXSIZE2 , BOXSIZE, BOXSIZE2, CYAN);  // four
  tft.fillRect(BOXSIZE, BOXSIZE2, BOXSIZE, BOXSIZE2, GREEN);  // five
  tft.fillRect(BOXSIZE*2, BOXSIZE2, BOXSIZE, BOXSIZE2, MAGENTA);  // six
// 3rd line
  tft.fillRect(0, BOXSIZE2*2 , BOXSIZE, BOXSIZE2, RED);  // seven
  tft.fillRect(BOXSIZE, BOXSIZE2*2, BOXSIZE, BOXSIZE2, YELLOW);  // eight
  tft.fillRect(BOXSIZE*2, BOXSIZE2*2, BOXSIZE, BOXSIZE2, BLUE);  // nein
// 4th line
//  tft.fillRect(0, BOXSIZE2*3 , BOXSIZE, BOXSIZE2, CYAN);  // *
  tft.fillRect(BOXSIZE, BOXSIZE2*3, BOXSIZE, BOXSIZE2, GREEN);  // zero
//  tft.fillRect(BOXSIZE*2, BOXSIZE2*3, BOXSIZE, BOXSIZE2, MAGENTA);  // #

  cifre ();  
    }

void caracter (int numar)
{
 tft.setTextSize(4);
 tft.setTextColor(WHITE);
 tft.setCursor(110, 280);
 tft.fillRect(0, 260 , 240, 59, BLACK);  // *
if (numar == 0) tft.println("0");
if (numar == 1) tft.println("1");
if (numar == 2) tft.println("2");
if (numar == 3) tft.println("3");
if (numar == 4) tft.println("4");
if (numar == 5) tft.println("5");
if (numar == 6) tft.println("6");
if (numar == 7) tft.println("7");
if (numar == 8) tft.println("8");
if (numar == 9) tft.println("9");
//if (numar == 10) tft.println("*");
//if (numar == 11) tft.println("#");
}

void caractere()
{
 tft.setTextSize(2);
tft.fillRect(0, 241 , 240, 79, BLACK);  // *
 tft.setTextColor(WHITE);
 tft.setCursor(10, 258);
 tft.println("DDS with AD9850");
 tft.setTextSize(3);
 tft.setCursor(10, 280);
// tft.println("??.???.???Hz");
citiremem();
// tft.println(EEPROM.read(11)); 
}

void caracters (int numar, int ics, int igr)
{
 tft.setTextSize(3);
 tft.setTextColor(WHITE);
//tft.drawLine(x1, y1, x2, y2, color); // line model
 tft.drawLine(ics, igr+32, ics+pas, igr+32, BLUE);


 tft.setCursor(ics, igr);
 tft.fillRect(ics, igr-2 , pas, 30, YELLOW);   // for testing
 delay(100);
 tft.fillRect(ics, igr-2 , pas, 30, BLACK);  

if (numar == 0) tft.println("0");
if (numar == 1) tft.println("1");
if (numar == 2) tft.println("2");
if (numar == 3) tft.println("3");
if (numar == 4) tft.println("4");
if (numar == 5) tft.println("5");
if (numar == 6) tft.println("6");
if (numar == 7) tft.println("7");
if (numar == 8) tft.println("8");
if (numar == 9) tft.println("9");
//if (numar == 10) tft.println("*");
//if (numar == 11) tft.println("#");
tft.setTextSize(4);
}


void memorie (byte cifra, int pozitie)
{
  if (pozitie == 1) {
    EEPROM.write(11,cifra); // cifra zeci de MHz
  //  Serial.print(EEPROM.read(11));
  }
  if (pozitie == 2) {
    EEPROM.write(12,cifra); // cifra MHZ
 //   Serial.print(EEPROM.read(12));
  }  
  if (pozitie == 4) {
    EEPROM.write(13,cifra); // cifra sute de kHz
//   Serial.print(EEPROM.read(13));
  }
  if (pozitie == 5) {
    EEPROM.write(14,cifra); // cifra zeci de kHz
 //   Serial.print(EEPROM.read(14));
  }
  if (pozitie == 6) {
    EEPROM.write(15,cifra); // cifra kHz
 //   Serial.print(EEPROM.read(15));
  }   
  if (pozitie == 8) {
    EEPROM.write(16,cifra); // cifra sute de Hz
  //  Serial.print(EEPROM.read(16));
  }
  if (pozitie == 9) {
    EEPROM.write(17,cifra); // cifra zeci de Hz
 //   Serial.print(EEPROM.read(17));
  }
  if (pozitie == 10) {
    EEPROM.write(18,cifra); // cifra Hz
 //   Serial.print(EEPROM.read(18));
  }
}

void citiremem ()
{
//tft.setTextSize(3);
// tft.setCursor(10, 280);
 for (int ji=11; ji<19; ji++)
{
  int nr = EEPROM.read(ji);

if (nr == 0) tft.print("0");
if (nr == 1) tft.print("1");
if (nr == 2) tft.print("2");
if (nr == 3) tft.print("3");
if (nr == 4) tft.print("4");
if (nr == 5) tft.print("5");
if (nr == 6) tft.print("6");
if (nr == 7) tft.print("7");
if (nr == 8) tft.print("8");
if (nr == 9) tft.print("9");

if (ji==12) tft.print(".");
if (ji==15) tft.print(".");
}
tft.println("Hz");
}


void SetFrequency(unsigned long frequency)
{
  unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;
  digitalWrite (LOAD, LOW); 

  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 8);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 16);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 24);
  shiftOut(DATA, CLOCK, LSBFIRST, 0x0);
  digitalWrite (LOAD, HIGH); 
}

void AD9850_init()
{

  digitalWrite(RESET, LOW);
  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);
  digitalWrite(DATA, LOW);
}

void AD9850_reset()
{
  //reset sequence is:
  // CLOCK & LOAD = LOW
  //  Pulse RESET high for a few uS (use 5 uS here)
  //  Pulse CLOCK high for a few uS (use 5 uS here)
  //  Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here)

  // data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also
  // toggle the LOAD line here.

  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);

  digitalWrite(RESET, LOW);
  delay(5);
  digitalWrite(RESET, HIGH);  //pulse RESET
  delay(5);
  digitalWrite(RESET, LOW);
  delay(5);

  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(CLOCK, HIGH);  //pulse CLOCK
  delay(5);
  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(DATA, LOW);    //make sure DATA pin is LOW

  digitalWrite(LOAD, LOW);
  delay(5);
  digitalWrite(LOAD, HIGH);  //pulse LOAD
  delay(5);
  digitalWrite(LOAD, LOW);
  // Chip is RESET now
}


void zaibar()
{
 n1 = EEPROM.read(11); //Serial.print(n1);
 n2 = EEPROM.read(12); //Serial.print(n2);
 n3 = EEPROM.read(13); //Serial.print(n3);
 n4 = EEPROM.read(14); //Serial.print(n4);
 n5 = EEPROM.read(15); //Serial.print(n5);
 n6 = EEPROM.read(16); //Serial.print(n6);
 n7 = EEPROM.read(17); //Serial.print(n7);
 n8 = EEPROM.read(18); //Serial.print(n8);
 frecv = n1*10000000 + n2*1000000+n3*100000+n4*10000+n5*1000+n6*100+n7*10+n8;
}  
   For measure the freqvency I made a simple freqvencymeter with Arduino, using info from interface.khm.de:
   I made a movie named Touch screen DDS with AD9850

Saturday, March 28, 2015

Signal generator with AD9850 and Arduino

   With AD9850 module we can made a signal generator controlled by Arduino with a rotary encoder and last frecvency stored in EEPROM.
   Base project is from http://www.ad7c.com/projects/ad9850-dds-vfo/
   I use a simplified schematic (without MF Frequency Shift):
   After I upload sketch and put oscilloscope I can see the square signal:
and sinus:

   My resuslts are:
   I use this sketch for DDS with AD9850, Arduino and rotary encoder:
/*
Main code by Richard Visokey AD7C - http://www.ad7c.com
Revision 2.0 - November 6th, 2013
adapted sketch 1.2 - january 1st, 2015 - by Nicu Florica - http://www.tehnic.go.ro
http://nicuflorica.blogspot.ro/
http://arduinotehniq.blogsopt.com/
*/

// Include the library code
#include <LiquidCrystal.h>
#include <rotary.h>
#include <EEPROM.h>

//Setup some items
#define W_CLK 8   // Pin 8 - connect to AD9850 module word load clock pin (CLK)
#define FQ_UD 9   // Pin 9 - connect to freq update pin (FQ)
#define DATA 10   // Pin 10 - connect to serial data load pin (DATA)
#define RESET 11  // Pin 11 - connect to reset pin (RST) 
#define pulseHigh(pin) {digitalWrite(pin, HIGH); digitalWrite(pin, LOW); }
Rotary r = Rotary(2,3); // sets the pins the rotary encoder uses.  Must be interrupt pins.
LiquidCrystal lcd(13, 12, 7, 6, 5, 4); // I used an odd pin combination because I need pin 2 and 3 for the interrupts.
int_fast32_t rx=7200000; // Starting frequency of VFO
int_fast32_t rx2=1; // variable to hold the updated frequency
int_fast32_t increment = 1; // starting VFO update increment in HZ.
int buttonstate = 0;
String hertz = "1 Hz";
int  hertzPosition = 6;
byte ones,tens,hundreds,thousands,tenthousands,hundredthousands,millions ;  //Placeholders
String freq; // string to hold the frequency
int_fast32_t timepassed = millis(); // int to hold the arduino miilis since startup
int memstatus = 1;  // value to notify if memory is current or old. 0=old, 1=current.

int ForceFreq = 0;  // Change this to 0 after you upload and run a working sketch to activate the EEPROM memory.  YOU MUST PUT THIS BACK TO 0 AND UPLOAD THE SKETCH AGAIN AFTER STARTING FREQUENCY IS SET!

void setup() {
  pinMode(A0,INPUT); // Connect to a button that goes to GND on push
  digitalWrite(A0,HIGH);
  lcd.begin(16, 2);
  PCICR |= (1 << PCIE2);
  PCMSK2 |= (1 << PCINT18) | (1 << PCINT19);
  sei();
  pinMode(FQ_UD, OUTPUT);
  pinMode(W_CLK, OUTPUT);
  pinMode(DATA, OUTPUT);
  pinMode(RESET, OUTPUT); 
  pulseHigh(RESET);
  pulseHigh(W_CLK);
  pulseHigh(FQ_UD);  // this pulse enables serial mode on the AD9850 - Datasheet page 12.
  lcd.setCursor(hertzPosition,1);    
  lcd.print(hertz);
   // Load the stored frequency  
  if (ForceFreq == 0) {
    freq = String(EEPROM.read(0))+String(EEPROM.read(1))+String(EEPROM.read(2))+String(EEPROM.read(3))+String(EEPROM.read(4))+String(EEPROM.read(5))+String(EEPROM.read(6));
    rx = freq.toInt();  
  }
}


void loop() {
  if (rx != rx2){    
        showFreq();
        sendFrequency(rx);
        rx2 = rx;
      }
      
  buttonstate = digitalRead(A0);
  if(buttonstate == LOW) {
        setincrement();        
    };

  // Write the frequency to memory if not stored and 2 seconds have passed since the last frequency change.
    if(memstatus == 0){   
      if(timepassed+2000 < millis()){
        storeMEM();
        }
      }   
}


ISR(PCINT2_vect) {
  unsigned char result = r.process();
  if (result) {    
    if (result == DIR_CW){rx=rx+increment;}
    else {rx=rx-increment;};       
      if (rx >=30000000){rx=rx2;}; // UPPER VFO LIMIT
      if (rx <=1){rx=rx2;}; // LOWER VFO LIMIT
  }
}



// frequency calc from datasheet page 8 = <sys clock> * <frequency tuning word>/2^32
void sendFrequency(double frequency) {  
  int32_t freq = frequency * 4294967295/125000000;  // note 125 MHz clock on 9850.  You can make 'slight' tuning variations here by adjusting the clock frequency.
  for (int b=0; b<4; b++, freq>>=8) {
    tfr_byte(freq & 0xFF);
  }
  tfr_byte(0x000);   // Final control byte, all 0 for 9850 chip
  pulseHigh(FQ_UD);  // Done!  Should see output
}
// transfers a byte, a bit at a time, LSB first to the 9850 via serial DATA line
void tfr_byte(byte data)
{
  for (int i=0; i<8; i++, data>>=1) {
    digitalWrite(DATA, data & 0x01);
    pulseHigh(W_CLK);   //after each bit sent, CLK is pulsed high
  }
}

void setincrement(){
  if(increment == 1){increment = 10; hertz = "10 Hz"; hertzPosition=5;}
  else if(increment == 10){increment = 50; hertz = "50 Hz"; hertzPosition=5;}
  else if (increment == 50){increment = 100;  hertz = "100 Hz"; hertzPosition=4;}
  else if (increment == 100){increment = 500; hertz="500 Hz"; hertzPosition=4;}
  else if (increment == 500){increment = 1000; hertz="1 kHz"; hertzPosition=6;}
  else if (increment == 1000){increment = 2500; hertz="2.5 kHz"; hertzPosition=4;}
  else if (increment == 2500){increment = 5000; hertz="5 kHz"; hertzPosition=6;}
  else if (increment == 5000){increment = 10000; hertz="10 kHz"; hertzPosition=5;}
  else if (increment == 10000){increment = 100000; hertz="100 kHz"; hertzPosition=4;}
  else if (increment == 100000){increment = 1000000; hertz="1 MHz"; hertzPosition=6;}  
  else{increment = 1; hertz = "1 Hz"; hertzPosition=6;};  
   lcd.setCursor(0,1);
   lcd.print("                ");
   lcd.setCursor(hertzPosition,1); 
   lcd.print(hertz); 
   delay(250); // Adjust this delay to speed up/slow down the button menu scroll speed.
};

void showFreq(){
    millions = int(rx/1000000);
    hundredthousands = ((rx/100000)%10);
    tenthousands = ((rx/10000)%10);
    thousands = ((rx/1000)%10);
    hundreds = ((rx/100)%10);
    tens = ((rx/10)%10);
    ones = ((rx/1)%10);
    lcd.setCursor(0,0);
    lcd.print("                ");
   if (millions > 9)
   {
       lcd.setCursor(1,0);
      }
   else 
   {
        lcd.setCursor(2,0); 
   }
    lcd.print(millions);
    lcd.print(",");
    lcd.print(hundredthousands);
    lcd.print(tenthousands);
    lcd.print(thousands);
    lcd.print(".");
    lcd.print(hundreds);
    lcd.print(tens);
    lcd.print(ones);
    lcd.print(" MHz  ");
    timepassed = millis();
    memstatus = 0; // Trigger memory write
};

void storeMEM(){
  //Write each frequency section to a EPROM slot.  Yes, it's cheating but it works!
   EEPROM.write(0,millions);
   EEPROM.write(1,hundredthousands);
   EEPROM.write(2,tenthousands);
   EEPROM.write(3,thousands);
   EEPROM.write(4,hundreds);       
   EEPROM.write(5,tens);
   EEPROM.write(6,ones);   
   memstatus = 1;  // Let program know memory has been written
   lcd.setCursor(1,15);
   lcd.print("*");
   delay(500);
   lcd.setCursor(1,15);
   lcd.print(" ");
 
};
   Now, I have in tests a new version with a TFT display with touch using a homemade shield from Arduino:
   I made a movie with a preliminary test for DDS with AD9850 and TFT display with touch...