Categories
Statistics
Flag Counter
Since 08.08.2014
Counts only, if "DNT = disabled".

Your IP is 44.213.60.33
ec2-44-213-60-33.compute-1.a
Info
Valid HTML 4.01 Transitional Creative Commons Lizenzvertrag
rss
เราจะทำแบบวิศวกรผู้ยิ่งใหญ่
We love the King
23. July 2024
Your valuable opinion :
5 stars

Avg. 6 from 8 votes.



Arduino-Kumod.php    30363 Bytes    02-04-2021 19:55:09


Arduino/Genuino Kumod


A versatile Dual DDS Synthesiser with the AD 9958







The assembled prototype




✈ Motivation




As the Polarmod worked nicely, we decided to create some kind of 'Spin-Off'. This Synthesiser can also be locked to a 10 MHz Reference, can be programmed via USB and offers many modes of operation.

It can serve as an I-Q-Source, a Two Tone generator, a Sweep Oscillator and can work in an IF-Offset Mode. A website on calculating IP3 can be found here.

"Ku" [in Thai : คู่ ] is the classificator for a 'pair' (e.g. a pair of boots, a couple, ...).




✈ Block Diagam Kumod





Block Diagram of the Kumod - a nifty little device

This device (Version 1, picture below) uses a free running XCO which is multiplied by a factor of 10 by the internal VCO/PLL of the AD9958. This allows for a Reference Clock of 500 MHz. Version 3 (see placement, below) can be populated with any 7 x 5 mm crystal oscillator or with our 100 MHz Ref Clock Module. Two internal Amplifier (GALI-51+, approx. 17 dB) boost the signal to + 10 dBm. In order to achieve a much lower cut-off (as when using the standard TCBT-14) we use two inductors in series, both damped with a resistor. Simulation (and measurement) show, that 1 MHz is by far not the end. The upper limit is somewhere in the region of 200 MHz, depending on your demands for image suppression. (An SCLF-190 lowpass-filter could be used here as well !)

Specifications :

FREQUENCY RANGE1 MHz ... 200 MHz in 1 kHz steps (Software limited)
AMPLITUDE RANGE- 20 ... + 10 dBm in 0.1 dB steps
PHASE RANGE0 ... 359.9° in 0.1° steps
REMOTEUSB (Arduino), not isolated
SUPPLY+ 7.5 V ... 9 V approx. 399 mA



Inside View of Version 1 - with a 50 MHz XCO


1 MHz CW
Simulation indicates a much lower cut-off
100 MHz, 0 dBm. SYNC_CLK visible @ 125 MHz




✈ Amplitude Setting




The Amplitude can be controlled manually by writing the amplitude scale factor directly. For this action to be successful, you need to set ACR[12] = 1 and ACR[11] = 0.

We measured the overall (inclusive GALI-51+ Amplifier) Setpoint (ASF) versus Power characteristics :



Our spreadsheet program was so kind to deliver a function which approximates the behaviour quite nicely. All which was left, was to solve for ASF (= Amplitude Scale Factor).



You'll find this in the code below, lines 242 and 255.




✈ Test Sketch for Arduino/Genuino Nano Every



Double click on code to select ...

/* //////////////////////////////////////////////////////////////////

  ARDUINO/Genuino Project "KUMOD", an DDS SYNTHESISER AD9958
  https://www.changpuak.ch/electronics/Arduino-Kumod.php
  Software Version 1.0 - 02.04.2021 by ALEXANDER SSE FRANK, 
  on the auspicious occasion of 
  HRH Princess Maha Chakri Sirindhorn's Birthday

  HELPFUL:
  randomnerdtutorials.com/guide-for-oled-display-with-arduino/

////////////////////////////////////////////////////////////////// */

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH1106.h>


// DISPLAY
#define OLED_MOSI  A2
#define OLED_CLK   A3
#define OLED_DC    A0
#define OLED_CS    13
#define OLED_RESET A1

// ROTARY ENCODER
const int RotaryEncoder1 = A7 ;   // PRESSED
const int RotaryEncoder2 = 2 ;
const int RotaryEncoder3 = 3 ;
volatile boolean LEFT = false ;
volatile boolean RIGHT = false ;
volatile boolean READY = true ;
int PRESSCNT = 0 ;

// DDS VARIABLES
double FREQA = 100.0 ;
double FREQB = 120.0 ;
double PHASEA = 0.0 ;
double PHASEB = 199.0 ;
double AMPLA = 10.2 ;
double AMPLB = 10.2 ;
const double FREQ_MAX = 200.001 ;
const double FREQ_MIN = 0.999 ;
const double PHASE_MIN = 0.0 ;
const double PHASE_MAX = 359.9 ;
const double AMPL_MIN = -20.1 ;
const double AMPL_MAX = 10.1 ;
// {Fa, Fb, Aa, Ab, Pa, Pb} ;
int CPos[] = {4,4,3,3,3,3} ;
int MinCPos[] = {0,0,3,3,2,2} ;
int MaxCPos[] = {6,6,5,5,5,5} ;
int DotCPos[] = {3,3,4,4,4,4} ;
int MenuI = 0 ;
int MaxMenuI = 5 ;
const double REF = 500.000000 ;

Adafruit_SH1106 display(OLED_MOSI, OLED_CLK, OLED_DC, OLED_RESET, OLED_CS);

#if (SH1106_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SH1106.h!");
#endif



// /////////////////////////////////////////////////////////////
// Serial Communication Routines : EEPROM & DDS
// /////////////////////////////////////////////////////////////

#define EEPROM_24C01_I2CADDR 0x50

// Single-bit serial 2-wire mode 
int DDS_RESET = 5 ;   // Active High Reset Pin
int DDS_SYNCIO = 6 ;
int DDS_SDIO2 = 7 ;
int DDS_SDIO1 = 8 ;
int DDS_SDAT = 9 ;
int DDS_SCLK = 10 ;
int DDS_CS = 11 ;
int DDS_IO_UPDATE = 12 ;


// ///////////////////////////////////////
void ResetDDS()
// ///////////////////////////////////////

{
  digitalWrite(DDS_RESET, HIGH) ;
  delay(9) ;
  digitalWrite(DDS_RESET, LOW) ;
  delay(9) ;
}


// //////////////////////////////////////////////////////////
void Energy()
// //////////////////////////////////////////////////////////

{
  digitalWrite(DDS_IO_UPDATE, HIGH) ;
  delay(1) ;
  digitalWrite(DDS_IO_UPDATE, LOW) ;  
}


// //////////////////////////////////////////////////////////
void WriteDDS1(byte instruct,byte data)
// //////////////////////////////////////////////////////////

{
  digitalWrite(DDS_CS, LOW) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, instruct ) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, data) ;
  digitalWrite(DDS_CS, HIGH) ;
}


// //////////////////////////////////////////////////////////
void WriteDDS2(byte instruct,byte d1,byte d2)
// //////////////////////////////////////////////////////////

{
  digitalWrite(DDS_CS, LOW) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, instruct ) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d1) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d2) ;
  digitalWrite(DDS_CS, HIGH) ;
}


// //////////////////////////////////////////////////////////
void WriteDDS3(byte instruct,byte d1,byte d2,byte d3)
// //////////////////////////////////////////////////////////

{
  digitalWrite(DDS_CS, LOW) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, instruct ) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d1) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d2) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d3) ;
  digitalWrite(DDS_CS, HIGH) ;
}


// //////////////////////////////////////////////////////////
void WriteDDS4(byte instruct,byte d1,byte d2,byte d3,byte d4)
// //////////////////////////////////////////////////////////

{
  digitalWrite(DDS_CS, LOW) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, instruct ) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d1) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d2) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d3) ;
  shiftOut(DDS_SDAT, DDS_SCLK, MSBFIRST, d4) ;
  digitalWrite(DDS_CS, HIGH) ;
}


// //////////////////////////////////////////////////////////
void UpdateFTW()
// //////////////////////////////////////////////////////////

{
  // DATASHEET PAGE 18
  // fout = FTW * fs / 2^32
  // fs / 2^32 is constant. = 0.000000116415321826934814453125
  // 2^32 / fs is constant. = 8’589’934.592
  // ///////////////////////////////////////////////////////
  // CHANNEL 0
  // ///////////////////////////////////////////////////////
  unsigned long  FTW = (unsigned long)(FREQA * 8589934.592 ) ;
  int Byte1 = (0xFF000000 & FTW) >> 24 ;
  int Byte2 = (0x00FF0000 & FTW) >> 16 ;
  int Byte3 = (0x0000FF00 & FTW) >> 8 ;
  int Byte4 = (0x000000FF & FTW) ;
  WriteDDS1(0x00, 0x70) ;
  WriteDDS4(0x04, Byte1, Byte2, Byte3, Byte4) ;
  Energy() ;
  // ///////////////////////////////////////////////////////
  // CHANNEL 1
  // ///////////////////////////////////////////////////////
  FTW = (unsigned long)(FREQB * 8589934.592 ) ;
  Byte1 = (0xFF000000 & FTW) >> 24 ;
  Byte2 = (0x00FF0000 & FTW) >> 16 ;
  Byte3 = (0x0000FF00 & FTW) >> 8 ;
  Byte4 = (0x000000FF & FTW) ;
  WriteDDS1(0x00, 0xB0) ;
  WriteDDS4(0x04, Byte1, Byte2, Byte3, Byte4) ;
  Energy() ;
}


// //////////////////////////////////////////////////////////
void UpdatePTW()
// //////////////////////////////////////////////////////////

{
  // CHANNEL 0 : CSR = 0x70
  // CHANNEL 1 : CSR = 0xB0
  // DATASHEET PAGE 18
  // pout = POW * 360 / 2^14
  // POW = pout * 2^14 / 360
  // 360 / 2^14 is constant. = 0.02197265625
  // 2^14 / 360 is constant. = 16384 / 360 = 45.511111111
  // ///////////////////////////////////////////////////////
  // CHANNEL 0
  // ///////////////////////////////////////////////////////
  int POW = (int)( PHASEA * 45.51111111111111 ) ;
  int EMSB = (POW & 0x3F00) >> 8 ;
  int ELSB = (POW & 0x00FF) ; 
  WriteDDS1(0x00, 0x70) ;
  WriteDDS2(0x05, EMSB, ELSB) ;
  Energy() ;
  // ///////////////////////////////////////////////////////
  // CHANNEL 1  
  // ///////////////////////////////////////////////////////
  POW = (int)( PHASEB * 45.51111111111111 ) ;
  EMSB = (POW & 0x3F00) >> 8 ;
  ELSB = (POW & 0x00FF) ; 
  WriteDDS1(0x00, 0xB0) ;
  WriteDDS2(0x05, EMSB, ELSB) ;
  Energy() ;
}


// //////////////////////////////////////////////////////////
void UpdateASF()
// //////////////////////////////////////////////////////////
// Manual mode allows the user to directly control the output 
// amplitude by manually writing to the amplitude scale factor 
// value in the ACR (Register 0x06). Manual mode is enabled 
// by setting ACR[12] = 1 and ACR[11] = 0. Line 247, 261

{
  // CHANNEL 0 : CSR = 0x70
  // CHANNEL 1 : CSR = 0xB0
  // AMAX 2^10 - 1 = 1023 approx. 10.23 dBm
  // AMIN = 100 ; 
  // ///////////////////////////////////////////////////////
  // CHANNEL 0
  // ///////////////////////////////////////////////////////
  unsigned int ASF = pow(2.71828182846, (( AMPLA + 50.062 )/8.712)) ;
  // Serial.print("ASF #A : ");
  // Serial.println(ASF,DEC);
  int ONE = 0x00 ;
  int TWO = (ASF & 0x000300) >> 8 ;
  TWO |= 0x14 ;
  int TRI = (ASF & 0x0000FF) ; 
  WriteDDS1(0x00, 0x70) ;
  WriteDDS3(0x06, ONE, TWO, TRI) ;
  Energy() ;
  // ///////////////////////////////////////////////////////
  // CHANNEL 1  
  // ///////////////////////////////////////////////////////
  ASF = pow(2.71828182846, (( AMPLB + 50.062 )/8.712)) ;
  // Serial.print("ASF #B : ");
  // Serial.println(ASF,DEC);
  // Serial.println("------------------");
  ONE = 0x00 ;
  TWO = (ASF & 0x000300) >> 8 ;
  TWO |= 0x14 ;
  TRI = (ASF & 0x0000FF) ; 
  WriteDDS1(0x00, 0xB0) ;
  WriteDDS3(0x06, ONE, TWO, TRI) ;
  Energy() ;
}


// /////////////////////////////////////////////////////////////
// ANALOG INPUTS
// /////////////////////////////////////////////////////////////

double SUPPLY = 0.0 ;
int SUPPLY_ARD_PIN = A6 ;

void UpDateSupplyVoltage() 
{
  SUPPLY = map(analogRead(SUPPLY_ARD_PIN),0,1023,0,2048)/100.0 ;
}


// /////////////////////////////////////////////////////////////
// SUBROUTINES DISPLAY.
// /////////////////////////////////////////////////////////////

  
void UpdateDisplay()
{
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0); display.print("****");
  display.setCursor(48,0); display.print("KUMOD");
  display.setCursor(104,0); display.print("****");
  display.drawLine(0, 12, 128, 12, WHITE);
  // --------------------------------------------
  // FREQUENCY CHANNEL A + CHANNEL B
  // --------------------------------------------
  if((MenuI == 0) || (MenuI == 1))
  {
  display.setTextSize(2) ;
  display.setCursor(0, 21);  
  if (FREQA < 100.000) display.print(" ");
  if (FREQA < 10.000) display.print(" ");
  display.print(FREQA,3);
  display.setCursor(90, 21); display.print("MHz");
  // --------------------------------------------
  display.setCursor(0, 45);
  if (FREQB < 100.000) display.print(" ");
  if (FREQB < 10.000) display.print(" ");
  display.print(FREQB,3);
  display.setCursor(90, 45); display.print("MHz");
  }
  // --------------------------------------------
  // AMPLITUDE CHANNEL A + CHANNEL B
  // --------------------------------------------
  if((MenuI == 2) || (MenuI == 3))
  {
  display.setTextSize(2) ;
  display.setCursor(0, 21);  
  display.print(" ");
  if ((AMPLA < 9.99) && (AMPLA > -9.99)) display.print(" ");
  if (AMPLA == 0.000) display.print(" ");
  if (AMPLA > 0.000) display.print("+");
  display.print(AMPLA,1);
  display.setCursor(90, 21); display.print("dBm");
  // --------------------------------------------
  display.setCursor(0, 45);
  display.print(" ");
  if ((AMPLB < 9.99) && (AMPLB > -9.99)) display.print(" ");
  if (AMPLB == 0.000) display.print(" ");
  if (AMPLB > 0.000) display.print("+");
  display.print(AMPLB,1);
  display.setCursor(90, 45); display.print("dBm");
  }
  // --------------------------------------------
  // PHASE CHANNEL A + CHANNEL B
  // --------------------------------------------
  if((MenuI == 4) || (MenuI == 5))
  {
  display.setTextSize(2) ;
  display.setCursor(0, 21); 
  display.print(" ");
  if (PHASEA < 100.000) display.print(" ");
  if (PHASEA < 10.000) display.print(" ");
  display.print(PHASEA,1);
  display.setCursor(90, 21); display.print("Deg");
  // --------------------------------------------
  display.setCursor(0, 45);
  display.print(" ");
  if (PHASEB < 100.000) display.print(" ");
  if (PHASEB < 10.000) display.print(" ");
  display.print(PHASEB,1);
  display.setCursor(90, 45); display.print("Deg");
  }
  // CURSOR VERTICAL
  if(MenuI == 0) display.setCursor(0, 25) ; // FREQ A
  if(MenuI == 1) display.setCursor(0, 49) ; // FREQ B
  if(MenuI == 2) display.setCursor(0, 25) ; // AMPL A
  if(MenuI == 3) display.setCursor(0, 49) ; // AMPL B
  if(MenuI == 4) display.setCursor(0, 25) ; // PHASE A
  if(MenuI == 5) display.setCursor(0, 49) ; // PHASE B
  // CURSOR HORIZONTAL
  if(CPos[MenuI] == 0) display.print("");  
  if(CPos[MenuI] == 1) display.print(" ");
  if(CPos[MenuI] == 2) display.print("  ");
  if(CPos[MenuI] == 3) display.print("   ");
  if(CPos[MenuI] == 4) display.print("    ");
  if(CPos[MenuI] == 5) display.print("     ");
  if(CPos[MenuI] == 6) display.print("      ");
  display.print("_");
  display.display();
}

// /////////////////////////////////////////////////////////////
// S E T U P
// /////////////////////////////////////////////////////////////

void setup()
{
  Serial.begin(115200) ;

  Wire.begin() ;

  // INIT OLED
  display.begin(SH1106_SWITCHCAPVCC);

  // SHOW STARTUP SCREEN
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(WHITE);
  display.setCursor(0,0); display.print("****");
  display.setCursor(48,0); display.print("KUMOD");
  display.setCursor(104,0); display.print("****");
  display.drawLine(0, 12, 128, 12, WHITE);
  display.setTextSize(1);
  display.setCursor(0, 21);
  display.println("A DUAL DDS GENERATOR");
  display.setCursor(0, 33);
  display.println("WITH THE AD9958. ");
  display.setCursor(0, 45);
  display.println("(C) ETH QUANTUMOPTICS");
  display.setCursor(0, 57);
  display.println("BUILT 02.04.2021");
  display.display();

  delay(999) ;
  
  pinMode(RotaryEncoder1, INPUT_PULLUP);
  pinMode(RotaryEncoder2, INPUT_PULLUP);
  pinMode(RotaryEncoder3, INPUT_PULLUP);
  // YELLOW
  attachInterrupt(digitalPinToInterrupt(RotaryEncoder2), 
  RotaryEncoderISR2, FALLING);
  // GREEN
  attachInterrupt(digitalPinToInterrupt(RotaryEncoder3), 
  RotaryEncoderISR3, FALLING);

  delay(1999);


  pinMode(DDS_RESET, OUTPUT) ;
  pinMode(DDS_SYNCIO, OUTPUT) ;
  digitalWrite(DDS_SYNCIO, LOW) ;
  pinMode(DDS_SDIO2, INPUT) ;
  pinMode(DDS_SDIO1, INPUT) ;
  pinMode(DDS_SDAT, OUTPUT) ;
  pinMode(DDS_SCLK, OUTPUT) ;
  pinMode(DDS_CS, OUTPUT) ;
  digitalWrite(DDS_CS, HIGH) ;
  pinMode(DDS_IO_UPDATE, OUTPUT) ;
  digitalWrite(DDS_IO_UPDATE, LOW) ;
  

  // INIT DDS
  ResetDDS() ;
  
  // Channel Select Register (CSR) (0x00) = BOTH
  WriteDDS1(0x00, 0xF0) ;

  // Function Register 1 (FR1) (0x01)
  WriteDDS3(0x01, 0xA8, 0x00, 0x00) ;

  // Function Register 2 (FR2) (0x02)
  WriteDDS2(0x02, 0x00, 0x00) ;

  // Channel Function Register (CFR) (0x03)
  WriteDDS3(0x03, 0x00, 0x03, 0x00) ;

  // Channel Frequency Tuning Word (CFTW0) (0x04)
  UpdateFTW() ;

  // PHASE TUNING WORD (0x05) ... OMITTED

  // Amplitude Control Register (ACR) (0x06)
  // MANUAL CONTROL, PAGE 28
  WriteDDS3(0x06, 0x00, 0x17, 0xFF) ;
  
  Energy() ;

  UpdatePTW() ;

  // CHECK SUPPLY
  UpDateSupplyVoltage() ;
  Serial.print("Supply : ") ;
  Serial.print(SUPPLY,2);
  Serial.println(" Volts");
}


// /////////////////////////////////////////////////////////////
// M A I N L O O P
// /////////////////////////////////////////////////////////////

void loop()
{
  // KEY ROTATED ?
  // //////////////////////////////////
  if(LEFT)
  // //////////////////////////////////
  {
  switch (MenuI) 
    {
    case 0:
    // FREQUENCY A -
    switch (CPos[0]) 
      {
      case 0:
      FREQA -= 100.0 ;
      if(FREQA < FREQ_MIN) FREQA += 100.0 ; // UNDO :-)
      break;  // ---------------
      case 1:
      FREQA -= 10.0 ;
      if(FREQA < FREQ_MIN) FREQA += 10.0 ; 
      break;  // ---------------
      case 2:
      FREQA -= 1.0 ;
      if(FREQA < FREQ_MIN) FREQA += 1.0 ; 
      break;  // ---------------
      case 4:
      FREQA -= 0.1 ;
      if(FREQA < FREQ_MIN) FREQA += 0.1 ; 
      break;  // ---------------
      case 5:
      FREQA -= 0.01 ;
      if(FREQA < FREQ_MIN) FREQA += 0.01 ; 
      break;  // ---------------
      case 6:
      FREQA -= 0.001 ;
      if(FREQA < FREQ_MIN) FREQA += 0.001 ; 
      break;  // ---------------
      }
      break ;
    case 1:
    // FREQUENCY B -
    switch (CPos[1]) 
      {
      case 0:
      FREQB -= 100.0 ;
      if(FREQB < FREQ_MIN) FREQB += 100.0 ; // UNDO :-)
      break;  // ---------------
      case 1:
      FREQB -= 10.0 ;
      if(FREQB < FREQ_MIN) FREQB += 10.0 ; 
      break;  // ---------------
      case 2:
      FREQB -= 1.0 ;
      if(FREQB < FREQ_MIN) FREQB += 1.0 ; 
      break;  // ---------------
      case 4:
      FREQB -= 0.1 ;
      if(FREQB < FREQ_MIN) FREQB += 0.1 ; 
      break;  // ---------------
      case 5:
      FREQB -= 0.01 ;
      if(FREQB < FREQ_MIN) FREQB += 0.01 ; 
      break;  // ---------------
      case 6:
      FREQB -= 0.001 ;
      if(FREQB < FREQ_MIN) FREQB += 0.001 ; 
      break;  // ---------------
      }
    break;
    // ----------------------------
    case 2:
    // AMPLITUDE A -
    switch (CPos[2]) 
      {
      case 3:
      AMPLA -= 1.0 ;
      if(AMPLA < AMPL_MIN) AMPLA += 1.0 ; // UNDO :-)
      break;  // ---------------
      case 5:
      AMPLA -= 0.1 ;
      if(AMPLA < AMPL_MIN) AMPLA += 0.1 ; 
      break;  // ---------------
      }    
    break;
    // ----------------------------
    case 3:
    // AMPLITUDE B -
    switch (CPos[3]) 
      {
      case 3:
      AMPLB -= 1.0 ;
      if(AMPLB < AMPL_MIN) AMPLB += 1.0 ; // UNDO :-)
      break;  // ---------------
      case 5:
      AMPLB -= 0.1 ;
      if(AMPLB < AMPL_MIN) AMPLB += 0.1 ; 
      break;  // ---------------
      }        
    break;
    // ----------------------------
    case 4:
    // PHASE A -
    
    break;
    // ----------------------------
    case 5:
    // PHASE B -
    
    break;
   }  
   UpdateFTW() ;
   UpdatePTW() ;
   UpdateASF() ;
   READY = true ;
   LEFT = false ;
   RIGHT = false ;
  }
  // //////////////////////////////////
  if(RIGHT)
  // //////////////////////////////////
  {
  switch (MenuI) 
    {
    case 0:
    // FREQUENCY A +
    switch (CPos[0]) 
      {
      case 0:
      FREQA += 100.0 ;
      if(FREQA > FREQ_MAX) FREQA -= 100.0 ; // UNDO :-)
      break;  // ---------------
      case 1:
      FREQA += 10.0 ;
      if(FREQA > FREQ_MAX) FREQA -= 10.0 ; 
      break;  // ---------------
      case 2:
      FREQA += 1.0 ;
      if(FREQA > FREQ_MAX) FREQA -= 1.0 ; 
      break;  // ---------------
      case 4:
      FREQA += 0.1 ;
      if(FREQA > FREQ_MAX) FREQA -= 0.1 ; 
      break;  // ---------------
      case 5:
      FREQA += 0.01 ;
      if(FREQA > FREQ_MAX) FREQA -= 0.01 ; 
      break;  // ---------------
      case 6:
      FREQA += 0.001 ;
      if(FREQA > FREQ_MAX) FREQA -= 0.001 ; 
      break;  // ---------------
      }
      break ;
    case 1:
    // FREQUENCY B +
    switch (CPos[1]) 
      {
      case 0:
      FREQB += 100.0 ;
      if(FREQB > FREQ_MAX) FREQB -= 100.0 ; // UNDO :-)
      break;  // ---------------
      case 1:
      FREQB += 10.0 ;
      if(FREQB > FREQ_MAX) FREQB -= 10.0 ; 
      break;  // ---------------
      case 2:
      FREQB += 1.0 ;
      if(FREQB > FREQ_MAX) FREQB -= 1.0 ; 
      break;  // ---------------
      case 4:
      FREQB += 0.1 ;
      if(FREQB > FREQ_MAX) FREQB -= 0.1 ; 
      break;  // ---------------
      case 5:
      FREQB += 0.01 ;
      if(FREQB > FREQ_MAX) FREQB -= 0.01 ; 
      break;  // ---------------
      case 6:
      FREQB += 0.001 ;
      if(FREQB > FREQ_MAX) FREQB -= 0.001 ; 
      break;  // ---------------
      }
    break;
    // ----------------------------
    case 2:
    // AMPLITUDE A +
    switch (CPos[2]) 
      {
      case 3:
      AMPLA += 1.0 ;
      if(AMPLA > AMPL_MAX) AMPLA -= 1.0 ; // UNDO :-)
      break;  // ---------------
      case 5:
      AMPLA += 0.1 ;
      if(AMPLA > AMPL_MAX) AMPLA -= 0.1 ; 
      break;  // ---------------
      }
    break;
    // ----------------------------
    case 3:
    // AMPLITUDE B +
    switch (CPos[3]) 
      {
      case 3:
      AMPLB += 1.0 ;
      if(AMPLB > AMPL_MAX) AMPLB -= 1.0 ; // UNDO :-)
      break;  // ---------------
      case 5:
      AMPLB += 0.1 ;
      if(AMPLB > AMPL_MAX) AMPLB -= 0.1 ; 
      break;  // ---------------
      }    
    break;
    // ----------------------------
    case 4:
    // PHASE A +
    
    break;
    // ----------------------------
    case 5:
    // PHASE B +
    
    break;
   }
   UpdateFTW() ;
   UpdatePTW() ;
   UpdateASF() ;
   READY = true ;
   LEFT = false ;
   RIGHT = false ;
  }
    
  // //////////////////////////////////
  // KEY PRESSED ?
  // //////////////////////////////////
  if(digitalRead(RotaryEncoder1) == LOW) PRESSCNT += 1 ;
  
  UpdateDisplay() ; // 50 ms
  delay(149) ;

  // WAIT FOR KEY RELEASED
  if(digitalRead(RotaryEncoder1) == HIGH)
  {
    // THAT WAS A SHORT ONE : ADVANCE CURSOR
    if((PRESSCNT > 0) && (PRESSCNT < 3))
    {
    CPos[MenuI] += 1 ;
    if(CPos[MenuI] == DotCPos[MenuI]) CPos[MenuI] += 1 ;
    if(CPos[MenuI] > MaxCPos[MenuI]) CPos[MenuI] = MinCPos[MenuI];
    PRESSCNT = 0 ;
    }
    // THAT WAS A LONG ONE : CHANGE MENUE ITEM
    if(PRESSCNT > 3)
    {
    MenuI += 1 ;
    if(MenuI > MaxMenuI) MenuI = 0 ;
    PRESSCNT = 0 ;
    }  
  }
}


// /////////////////////////////////////////////////////////////
// INTERRUPT SERVICE ROUTINES
// /////////////////////////////////////////////////////////////

void RotaryEncoderISR2()
{
  // YELLOW
  if(READY)
  {
  LEFT = false ;
  RIGHT = false ;
  byte autre = digitalRead(RotaryEncoder3) ;
  if (autre > 0) RIGHT = true ;
  if (autre < 1) LEFT = true ;
  }
}

void RotaryEncoderISR3()
{
  // GREEN
  if(READY)
  {
  LEFT = false ;
  RIGHT = false ;
  byte autre = digitalRead(RotaryEncoder2) ;
  if (autre > 0) LEFT = true ;
  if (autre < 1) RIGHT = true ;
  }
}


// /////////////////////////////////////////////////////////////
// END OF FILE.
// /////////////////////////////////////////////////////////////




✈ Downloads








✈ Output Spectrum






As with digital systems, there is a lot of spurious garbage visible. Read more here.





Output Spectrum, two tones added up with a ADP-2-1 from MiniCircuits. Care must be taken, that no spurious signals are there, where the intermodulation products are to be expected (when measuring IP3).




✈ Share your thoughts



The webmaster does not read these comments regularely. Urgent questions should be send via email. Ads or links to completely uncorrelated things will be removed.


Your Browser says that you allow tracking. Mayst we suggest that you check that DNT thing ?

 
t1 = 6585 d

t2 = 198 ms

★ ★ ★  Copyright © 2006 - 2024 by changpuak.ch  ★ ★ ★

Impressum