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

Your IP is 3.14.15.94
ec2-3-14-15-94.us-east-2.com
Info
Valid HTML 4.01 Transitional Creative Commons Lizenzvertrag
rss
เราจะทำแบบวิศวกรผู้ยิ่งใหญ่
We love the King
2. May 2024
Your valuable opinion :
5 stars

Avg. 5.00 from 4 votes.



SNSD - Kissing You
Arduino-Shield-REINHARD.php    41121 Bytes    31-05-2023 09:40:11


Arduino/Genuino 10 GHz Synthesizer "MEGAMOD"


Shield "REINHARD" (2849)



This is a shield to evaluate the performance of the Analog Devices ADF 5355 Synthesizer. Together with a rotary encoder, an Nokia 5110/3310 lcd or an 1.3" 128x64 Blue Graphic OLED display, an attenuator and some amplifying, this forms a fully functional synthesizer.



Arduino Shield REINHARD



  FREQUENCY RANGE

  54 MHz ... 9.1 GHz (software limited)

  FREQUENCY RESOLUTION

  1 Hz

  OUTPUT POWER

  - 30 dBm ... + 13 dBm

  SYSTEM CLOCK

  Onboard 100 MHz VCXO

  NEEDS

  External 10 MHz or internal OCXO ;-)

  POWER SUPPLY

  7.5 V, 800 mA





✈ Motivation




Designing an ultra high frequency synthesizer is very challenging. The price of the components increases proportional to the frequency. (or more :-) We did not optimise for cost, as this mayst have compromised the performance. The device is used in our IMPACT Experiment as a reliable uhf frequency source. It is phase-locked to our master 10 MHz Reference, which generates a 100 MHz (vcxo) clock to serve as a reference for the ADF5355. The integer boundary spurs shall be attacked by smart programming.




✈ The building Blocks • Functional Description




Arduino Shield REINHARD Block Diagram


The Reference clock for the ADF5355 is built with a VCXO (ABLNO-V-100.000MHz-T2) running at 100 MHz. It is phase-locked to an external 10 MHz input by a HMC-1031 pll. The lock status as well as the amplitude of the 10 MHz signal is monitored with an AD8307. In case of lock, a green led (D2) will light up.

The 100 MHz Reference is then ac-coupled to the ADF5355. This VCO/PLL is supplied with three ADM7150 (2 x 3.3 V, 1 x 5.0 V) as they promise "Ultralow Noise, High PSRR" - to be precise, 1.6 µV rms total integrated noise from 10 Hz to 100 kHz.

As the ADF5355 has an differential output for the "fundamental" frequency and a separetd "doubler" output, there are two paths. The lower frequency range (up to approx. 6.8 GHz) is biased with a TCBT-14 and a TCBT-14R, and then summed up with a TCM1-83x-1+. Then followed by a lowpass (LFCN-6700). The doubled output passes a highpass-filter (HFCN-5500) and is then amplified by a GVA-123+. Both signal paths lead to a switch (HMC232ALP4E). The "common" path leads to an attenautor (HMC424) is then amplified by another GVA-123+ and enters a second attenuator (HMC424) before leaving the board via an sma connector.

As the attenuators demand for negative controls, a dc/dc converter (LM2660M) generates a - 5.0 V supply. The I2C signals are isolated and down-shifted with an ISO1541. An MCP23017-E/SS takes care of the serial to parallel conversion. It outputs 0 V or - 4.9 V.

We used two attenuators (HMC424ALP3E) which offer 0.5 dB - 31.5 dB (up to 13 GHz) each. This total attenuation range of 0.5 dB - 63 dB is partly used for attenuation and partly for calibration - to allow a flat amplitude response, as FR4 starts degrading above 2 GHz.




✈ Downloads










✈ A trustworthy 10 MHz Reference is the key ...




This device needs a reliable 10 MHz Reference input to work satisfactory. If you don't have a GPS disciplined 10 MHz source or a Rubidium Standard, you may want to use a 10 MHz OCXO, or a 10 MHz XCXO. In this case the shield "TIMEBASE MOD V1" mayst be useful. It also allows for first experiments when using the shield "REINHARD". If you don't use it, the reference circuit built with the HMC1031MS8E and the ABLNO-V-100.000MHz-T2 will run at its lowest frequency (as there is no 10 MHz input). This is approx. 100 MHz - 12 ppm ≈ 99.988 MHz. You can check the availability of a 10 MHz source by reading the input of the pin A6 which is the output of the AD8307.



Arduino Shield REINHARD, REFERENCE OSCILLATOR
The Reference Shield, based on a TCXO and Voltage Regulator




ADEF5355 Synthesizer


The final assembly, ready to be shipped to our labs




Megamod inside


Two additional amplifiers are equipped here for extra power.




✈ Arduino Sketch - The Code



Double click on code to select ...



// /////////////////////////////////////////////////////////////////////
//
// ADF5355 TEST SKETCH BY ALEXANDER SSE FRANK
// THE MOST IMPORANT ROUTINES ARE FROM MIRCO TOMOTHY DILL
// SOME ROUTINES ARE FROM JOËL STEINEMANN (MICROMOD PROJECT)
// INTENDED FOR "MEGAMOD", VERSION "megamod-2018-06-20"
// LAST STABLE VERSION (N-1) IS megamod-2018-06-20
//
// /////////////////////////////////////////////////////////////////////

// CALIBRATION VALUES FOR ATTENUATOR
// FREQUENCY IS INDEX * 200 MHz + 100 MHz
// I.E. AC[0] = 15.5 MEANS 15.5 dB ATTENUATION AT 100 MHz

// Megamod mit 122.88MHz extern 12.07.2018, MD

float AC[56] ;


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

// PINS ADF5355

#define CLOCKPIN A0
#define DATAPIN A1
#define LE A2
#define CE A3

// VARIABLES

unsigned long long FreqVCO = 6000000000 ;
unsigned long long FreqOUT = 6000000000 ;
unsigned long long FreqRangeSwitchValue = 6800000001 ;
unsigned long FreqREF = 100000000 ;  // 100 MHz
unsigned long FreqPFD = 100000000 ;  // 100 MHz
unsigned long long FMIN = 5800000000 ;
unsigned long long FMAX = 6200000000 ;

float LMAX = 7.5 ;  // GVA-123+ : MAX 7.4 dBm @ 10 GHz
float LMIN = LMAX - 47.5 ;
float LACT = 7.0 ;
float ATT = 0.0 ;
float CAL = 0.0 ;
// NOTE : A ZX60-14012L-S+ MAYST BE USED TO INCREASE LMAX TO +10dBm
// USES +12V, MAX. 70mA, COST EURO 255 :)
// A DC/DC CONVERTER IS NECESSARY
const int RangeHigh = 0x40 ;   // Switch B, BIT 7 OF MCP23017, PORT A
const int RangeLow = 0x80 ;    // Switch A, BIT 6 OF MCP23017, PORT A
unsigned int Range = RangeLow ;
const int MCPADR = 0x27;
const int ATTREGADR = 0x12;    // ATTENUATOR, MCP REG A
const int CALREGADR = 0x13;    // CALIBRATION, MCP REG B
unsigned int CALBYTE;
unsigned int ATTBYTE;

unsigned long OUTDivider = 64 ;
unsigned long OUTDoubler = 0 ;
double N_Calculation = 0;  // N-Value helps for Calculations: N*PFD = VCO

// REGISTER 12
unsigned long PHASE_RESYNC_CLOCK_DIVIDER = 0x01 ;  // NORMAL OPERATION
// REGISTER 11
// *** RESERVED ***
// REGISTER 10
unsigned long ADC_CLK_DIV = 255 ;  // = Ceiling(((fPFD/100'000) − 2)/4)
unsigned long ADC_CONVERSION = 1 ; // ENABLED (RECOMMENDED)
unsigned long ADC_ENABLE = 1 ;     // ENABLED (RECOMMENDED)
// REGISTER 9
unsigned long VCO_BAND_DIV = 52 ;  // = Ceiling(fPFD/2'400'000)
unsigned long TIMEOUT = 205 ;       // NOTHING RECOMMENDED ???
unsigned long ALC_WAIT = 0x1E ;    // ALC Wait > (50 µs × fPFD)/Timeout
unsigned long SLC_WAIT = 0xC ;     
// Synthesizer Lock Timeout > (20 µs × fPFD)/Timeout
// REGISTER 7
unsigned long LE_SYNCHRONIZATION = 1 ;
unsigned long LOCK_DETECT_CYCLE_COUNT  = 0x3 ;   // EQUALS 8192
unsigned long LOSS_OF_LOCK_MODE  = 0x1 ;         // REF CLOCK IS NEVER REMOVED
unsigned long FRACTIONAL_N_LD_PRECISION  = 0x3 ; // 12 ns
unsigned long LOCK_DETECT_MODE = 0x0 ;           // FRACTIONAL-N
// REGISTER 6
//  Note that this function requires digital lock detect to be enabled !
unsigned long GATED_BLEED = 0 ;    // 1 = ENABLED
// Do not use negative bleed when operating in integer-N mode, 
// that is, when FRAC1 = FRAC2 = 0,
// or when fPFD is greater than 100 MHz
unsigned long NEGATIVE_BLEED = 1 ;             // 1 = ENABLED
unsigned long FEEDBACK_SELECT = 0x1 ;          // FUNDAMENTAL
unsigned long RF_DIVIDER_SELECT = 0 ;          
// CORRESPONDS TO OUTDivider = 1 , 6 FOR OUTDivider = 64;
unsigned long RFOUTA = 1 ;                     // ENBALED
unsigned long RFOUTB = 0 ;                     // ENABLED
unsigned long BLEED_CURRENT = 0xC ;            // 26.25µA
unsigned long MUTE_TILL_LOCK_DETECT  = 0x0 ;   // DISABLED
unsigned long OUTPUT_POWER = 0x3 ;             // 0x3 for +5dBm
// REGISTER 5
// *** RESERVED ***
// REGISTER 4
unsigned long REFERENCE_DOUBLER  = 0x0 ;       // DISABLED
unsigned long REFERENCE_DIVIDE_BY_2  = 0x0 ;   // DISABLED
unsigned long R_DIVIDER = 0x1 ;                // DIVIDE BY 1
unsigned long MUXOUT = 0x6 ;                   // DIGITAL LOCK DETECT
unsigned long DOUBLE_BUFFERED  = 0x0 ;         // DISABLED
unsigned long CURRENT_SETTING = 0x2 ;          // 0.9 mA
unsigned long REFIN = 0x0 ;                    
// SINGLE, RECOMMENDED - 0X1 FOR DIFFERENTIAL
unsigned long MUX_LOGIC = 0x1 ;                
// 0x1 is 3.3 V LOGIC LEVEL, 0x0 is 1.8 V
unsigned long PD_POLARITY = 0x1 ;              // FOR PASSIVE LOOP FILTER
unsigned long POWER_DOWN = 0x0 ;               // NORMAL OPERATION
unsigned long CP_THREE_STATE = 0x0 ;           // NORMAL OPERATION
unsigned long COUNTER_RESET = 0x0 ;            // NORMAL OPERATION
// REGISTER 3
unsigned long SD_LOAD_RESET = 0x0 ;            
// Sigma Delta Modulator Reset Disabled
unsigned long PHASE_RESYNC = 0x0 ;             // Hmmmmm ?
unsigned long PHASE_ADJUST = 0x0 ;             // Hmmmmm ?
unsigned long PHASE_VALUE = 0x0 ;              // PHASE ADJUST NOT NEEDED
// REGISTER 2
unsigned long FRAC2_WORD = 0x3272 ;            // 0 ... 16383
unsigned long MOD2_WORD = 0x3FFF ;             // 2 ... 16383 (MOD2 == 16383)
// REGISTER 1
unsigned long FRAC1_WORD = 0xB19330 ;          // 0 ... 16777215
// REGISTER 0
unsigned long VCO_AUTOCAL = 0x1 ;              
// enable automatic calibration. Recommended mode of operation.
unsigned long PRESCALER = 0x1 ;                
// 0x1 = PRESCALER : 8/9, 0x0 = PRESCALER : 4/5
unsigned long INTEGER_VALUE = 0x88 ;           // 23 ... 65535 TBD


// OLED 128x64 with SH1106 Controller
// E.G. DM-OLED13-625
#define OLED_MOSI  29
#define OLED_CLK   27
#define OLED_DC    35
#define OLED_CS    37
#define OLED_RESET 31
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

unsigned int ActiveDisplay = 1 ;  // AMPLITUDE
boolean ShowCursor = true ;
unsigned int CursorPosition = 6 ;

// Menue Intem to be displayed
unsigned int MenueItem = 0 ;

// STATE OF THE ROTARY ENCODER
const int RE2 = 49 ;  // PRESSED
const int RE1 = 47 ;
const int RE0 = 45 ;
unsigned long StartMilli ;
unsigned long DurationMilli ;
boolean PressedLong = false ;

// "INTERRUPT" VARIABLES
unsigned int RE_now = 0;
unsigned int RE_old = 0;
unsigned int RE_xor = 0 ;
unsigned int RE_one = 0 ;
unsigned int RE_two = 0 ;
unsigned int RE_eval = 0x0 ;  //0 = LEFT(-),1=RIGHT(+),2=PRESSED
unsigned long RE_time0 = 0 ;
unsigned long RE_time1 = 0 ;
unsigned long RE_time2 = 0 ;

// REFERENCE
const int Locked = A7 ;
const int RefInputLevelPin = A6 ;
unsigned int RefInputLevel = 0 ;

// /////////////////////////////////////////////////////////////

void setup()
{
  delay(5000);

  Serial.begin(115200);
  Wire.begin();

  pinMode(CLOCKPIN, OUTPUT);
  pinMode(DATAPIN, OUTPUT);
  pinMode(LE, OUTPUT);
  pinMode(CE, OUTPUT);

  digitalWrite(CLOCKPIN, LOW);
  digitalWrite(DATAPIN, LOW);
  digitalWrite(LE, HIGH);
  digitalWrite(CE, HIGH);

  // INIT OLED
  display.begin(SH1106_SWITCHCAPVCC);
  // SHOW STARTUP SCREEN
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Megamod");
  display.setTextSize(1);
  display.setCursor(0,21);
  display.println("AN UHF SYNTHESISER");
  display.setCursor(0,33);
  display.println("BASED ON THE ADF 5355");
  display.setCursor(0,45);
  display.println("(C) ETH QUANTUMOPTICS");
  display.setCursor(0,57);
  display.println("BUILT 31.07.2018");
  display.display();
  delay(999);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Megamod");
  display.setTextSize(1);
  display.setCursor(0,21);
  display.println("FIRMWARE WRITTEN BY");
  display.setCursor(0,33);
  display.println("MR. JOEL STEINEMANN");
  display.setCursor(0,45);
  display.println("MR. MIRCO DILL");
  display.setCursor(0,57);
  display.println("MR. ALEXANDER FRANK");
  display.display();
  delay(999);
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(0,0);
  display.println("Megamod");
  display.setTextSize(1);
  display.setCursor(0,21);
  display.println("HARDWARE DESIGNED BY");
  display.setCursor(0,33);
  display.println("MR. MIRCO DILL");
  display.setCursor(0,45);
  display.println("MR. ALEXANDER FRANK");
  display.setCursor(0,57);
  display.println("MR. TILMAN ESSLINGER");
  display.display();
  delay(999);

  // KNOB - ROTARY ENCODER
  pinMode(RE2, INPUT_PULLUP);
  pinMode(RE1, INPUT_PULLUP);
  pinMode(RE0, INPUT_PULLUP);

  // REFERENCE
  pinMode(Locked, INPUT);
  pinMode(RefInputLevel, INPUT);

  RE_now = (digitalRead(RE2) << 2 ) | (digitalRead(RE1) 
  << 1 ) | digitalRead(RE0);
  RE_old = RE_now ;

  if (digitalRead(!Locked)) MenueItem  = 9 ;
/*
  // ATTENUATION NEEDED FOR LMAX OUTPUT - CHECK THAT
  AC[0] = 15.5 ; //  100 MHz
  AC[1] = 15.5 ; //  300 MHz
  AC[2] = 15.5 ; //  500 MHz
  AC[3] = 15.5 ; //  700 MHz
  AC[4] = 15.5 ; //  900 MHz
  AC[5] = 15.5 ; // 1100 MHz
  AC[6] = 15.0 ; // 1300 MHz
  AC[7] = 15.0 ; // 1500 MHz
  AC[8] = 15.0 ; // 1700 MHz
  AC[9] = 15.0 ; // 1900 MHz
  AC[10] = 15.0 ; // 2100 MHz
  AC[11] = 12.0 ; // 2300 MHz
  AC[12] = 12.0 ; // 2500 MHz
  AC[13] = 12.0 ; // 2700 MHz
  AC[14] = 12.0 ; // 2900 MHz
  AC[15] = 12.0 ; // 3100 MHz
  AC[16] = 10.0 ; // 3300 MHz
  AC[17] = 10.0 ; // 3500 MHz
  AC[18] = 10.0 ; // 3700 MHz
  AC[19] = 10.0 ; // 3900 MHz
  AC[20] = 10.0 ; // 4100 MHz
*/
  // just test values
  AC[0] = 0 ; //  100 MHz
  AC[1] = 0 ; //  300 MHz
  AC[2] = 0 ; //  500 MHz
  AC[3] = 0 ; //  700 MHz
  AC[4] = 0 ; //  900 MHz
  AC[5] = 0 ; // 1100 MHz
  AC[6] = 0 ; // 1300 MHz
  AC[7] = 0 ; // 1500 MHz
  AC[8] = 0 ; // 1700 MHz
  AC[9] = 0 ; // 1900 MHz
  AC[10] = 0 ; // 2100 MHz
  AC[11] = 0 ; // 2300 MHz
  AC[12] = 0 ; // 2500 MHz
  AC[13] = 0 ; // 2700 MHz
  AC[14] = 0 ; // 2900 MHz
  AC[15] = 0 ; // 3100 MHz
  AC[16] = 0 ; // 3300 MHz
  AC[17] = 0 ; // 3500 MHz
  AC[18] = 0 ; // 3700 MHz
  AC[19] = 0 ; // 3900 MHz
  AC[20] = 0 ; // 4100 MHz


  // INIT MCP23017, ALL OUTPUT, A0,A1,A2 = HIGH
  Wire.beginTransmission(MCPADR);
  Wire.write(0x00); // IODIRA register
  Wire.write(0x00); // set all of port A to outputs
  Wire.endTransmission();
  Wire.beginTransmission(MCPADR);
  Wire.write(0x01); // IODIRB register
  Wire.write(0x00); // set all of port B to outputs
  Wire.endTransmission();
  //ProgramADF5355(FreqOUT);

}



void loop()
{
  switch (MenueItem)
  {
    case 0:
      ShowFrequencyMenue() ;
      ActiveDisplay = 0 ;
      MenueItem = 2 ;
      ProgramADF5355(FreqOUT);
      SetRFLevel(LACT, FreqVCO);
      break;

    case 1:
      ShowAmplitudeMenue() ;
      ActiveDisplay = 1 ;
      MenueItem = 2 ;
      SetRFLevel(LACT, FreqVCO);
      break;

    case 2:
      // //////////////////////////////////////////////////////////////
      // READ THE ROTARY ENCODER EVERY 1 ms
      // Timer Interrupt does not work here
      // //////////////////////////////////////////////////////////////
      RE_xor = 0x00 ;
      while (RE_xor == 0x00)
      {
        CheckRE() ;
        delay(1) ;
      }
      RE_time0 = millis();
      RE_one = RE_xor ;
      delay(10);
      // NOW WAIT FOR THE SECOND TRANSITION ...
      RE_xor = 0x00 ;
      while (RE_xor == 0x00)
      {
        CheckRE() ;
        delay(1) ;
      }
      RE_time1 = millis();
      RE_two = RE_xor ;
      // TIME DURATION
      RE_time2 = RE_time1 - RE_time0 ;
      PressedLong = false ;
      if (RE_time2 > 999 ) PressedLong = true ;
      // NOW EVALUATE
      //Serial.print("RE_one : ");Serial.println(RE_one);
      //Serial.print("RE_two : ");Serial.println(RE_two);
      //Serial.print("RE_time2 : ");Serial.println(RE_time2);
      RE_eval = 0xFF ;
      if ((RE_one == 0x4) & (RE_two == 0x2)) RE_eval = 0x1; // RIGHT
      if ((RE_one == 0x2) & (RE_two == 0x4)) RE_eval = 0x0; // LEFT
      if ((RE_one == 0x1) & (RE_two == 0x1)) RE_eval = 0x2; // PRESSED

      // //////////////////////////////////////////////////////////////
      // ROTATION = LEFT = -
      // //////////////////////////////////////////////////////////////
      if ((RE_eval == 0x0) && (ActiveDisplay == 0))
        {
          switch (CursorPosition)
          {
            case 0: // -1 GHZ
              if (FreqOUT > (FMIN + 1E9)) FreqOUT -= 1E9 ;
              break;
            case 1: // -100 MHz
              if (FreqOUT > (FMIN + 1E8)) FreqOUT -= 1E8 ;
              break;
            case 2: // -10 MHz
              if (FreqOUT > (FMIN + 1E7)) FreqOUT -= 1E7 ;
              break;
            case 3: // -1 MHz
              if (FreqOUT > (FMIN + 1E6)) FreqOUT -= 1E6 ;
              break;
            case 4: // -100 kHz
              if (FreqOUT > (FMIN + 1E5)) FreqOUT -= 1E5 ;
              break;
            case 5: // -10 kHz
              if (FreqOUT > (FMIN + 1E4)) FreqOUT -= 1E4 ;
              break;
            case 6: // -1 kHz
              if (FreqOUT > (FMIN + 1E3)) FreqOUT -= 1E3 ;
              break;
            case 7: // -100 Hz
              if (FreqOUT > (FMIN + 1E2)) FreqOUT -= 1E2 ;
              break;
            case 8: // -10 Hz
              if (FreqOUT > (FMIN + 1E1)) FreqOUT -= 1E1 ;
              break;
            case 9: // -1 Hz
              if (FreqOUT > (FMIN + 1E0)) FreqOUT -= 1E0 ;
              break;
          }
          MenueItem = ActiveDisplay ;
        }
      // //////////////////////////////////////////////////////////////
      // ROTATION = LEFT = -
      // //////////////////////////////////////////////////////////////
      if ((RE_eval == 0x0) && (ActiveDisplay == 1))
        {
          // DECREASE LEVEL
          LACT -= 0.5 ;
          if (LACT < LMIN) LACT = LMIN ;
          MenueItem = ActiveDisplay ;
        }
      // //////////////////////////////////////////////////////////////
      // ROTATION = RIGHT = +
      // //////////////////////////////////////////////////////////////
      if ((RE_eval == 0x1) && (ActiveDisplay == 0))
        {
          switch (CursorPosition)
          {
            case 0: // +1 GHZ
              if (FreqOUT < (FMAX - 1E9)) FreqOUT += 1E9 ;
              break;
            case 1: // +100 MHz
              if (FreqOUT < (FMAX - 1E8)) FreqOUT += 1E8 ;
              break;
            case 2: // +10 MHz
              if (FreqOUT < (FMAX - 1E7)) FreqOUT += 1E7 ;
              break;
            case 3: // +1 MHz
              if (FreqOUT < (FMAX - 1E6)) FreqOUT += 1E6 ;
              break;
            case 4: // +100 kHz
              if (FreqOUT < (FMAX - 1E5)) FreqOUT += 1E5 ;
              break;
            case 5: // +10 kHz
              if (FreqOUT < (FMAX - 1E4)) FreqOUT += 1E4 ;
              break;
            case 6: // +1 kHz
              if (FreqOUT < (FMAX - 1E3)) FreqOUT += 1E3 ;
              break;
            case 7: // +100 Hz
              if (FreqOUT < (FMAX - 1E2)) FreqOUT += 1E2 ;
              break;
            case 8: // +10 Hz
              if (FreqOUT < (FMAX - 1E1)) FreqOUT += 1E1 ;
              break;
            case 9: // +1 Hz
              if (FreqOUT < (FMAX - 1E0)) FreqOUT += 1E0 ;
              break;
          }
          MenueItem = ActiveDisplay ;
        }
      // //////////////////////////////////////////////////////////////
      // ROTATION = RIGHT = +
      // //////////////////////////////////////////////////////////////
      if ((RE_eval == 0x1) && (ActiveDisplay == 1))
        {
          // INCREASE LEVEL
          LACT += 0.5 ;
          if (LACT > LMAX) LACT = LMAX ;
          MenueItem = ActiveDisplay ;
        }
      // //////////////////////////////////////////////////////////////
      // ROTARY ENCODER WAS PRESSED
      // //////////////////////////////////////////////////////////////
      if (RE_eval == 0x2)
        {
          // CASE 1 : FREQUENCY MODE AND SHORT PRESS
          if ((ActiveDisplay == 0) && !PressedLong)
          {
            // MOVE CURSOR ONE POSITION RIGHT
            CursorPosition += 1;
            if (CursorPosition > 9) CursorPosition = 0 ;
            MenueItem = ActiveDisplay ;
          }
          // CASE 2 : FREQUENCY MODE AND LONG PRESS
          else if ((ActiveDisplay == 0) && PressedLong)
          {
            // SWITCH TO AMPLITUDE MODE
            ActiveDisplay = 1 ;
            MenueItem = ActiveDisplay ;
          }
          // CASE 3 : AMPLITUDE MODE AND SHORT PRESS
          else if ((ActiveDisplay == 1) && !PressedLong)
          {
            // NOTHING TO DO HERE
            delay(1);
          }
          // CASE 4 : AMPLITUDE MODE AND LONG PRESS
          else if ((ActiveDisplay == 1) && PressedLong)
          {
            // SWITCH TO FREQUENCY MODE
            ActiveDisplay = 0 ;
            MenueItem = ActiveDisplay ;
          }
        }
      break;

    default:
      ShowErrorMenue() ;
      MenueItem = 2 ;
      delay(999);
      ActiveDisplay = 0 ;
      MenueItem = ActiveDisplay ;
      break;
  }
}

// /////////////////////////////////////////////////////////////////////
// SUBROUTINES FOR THE ADF5355.
// /////////////////////////////////////////////////////////////////////

void WriteADF5355( unsigned long data )
{
  // SEE P.7 "Write Timing Diagram"
  // 4 LSB FORM THE ADDRESS
  /*
  unsigned long pointa = 0x1 << 31 ;
  for (int i=0 ; i<32; i++)
  {
    if ((pointa & data) > 0) digitalWrite(DATAPIN, HIGH);
    else digitalWrite(DATAPIN, LOW);
    digitalWrite(CLOCKPIN, HIGH);
    digitalWrite(CLOCKPIN, LOW);
    pointa = pointa >> 1;
  }
  digitalWrite(LE, HIGH);
  digitalWrite(LE, LOW);
  */

  digitalWrite(LE, LOW);
  for (int i=31 ; i>=0 ; i--)
  {
    digitalWrite(DATAPIN, bitRead(data, i));
    digitalWrite(CLOCKPIN, HIGH);
    digitalWrite(CLOCKPIN, LOW);
  }
  digitalWrite(LE, HIGH);

  Serial.println(data, HEX);
}

void ProgramADF5355( unsigned long long OutputFrequency )
{
  unsigned long BitStaengeli ;
  FreqOUT = OutputFrequency;
  Serial.println("REGISTERS:");

  // REGISTER 12, PAGE 16
  BitStaengeli = PHASE_RESYNC_CLOCK_DIVIDER << 16
  | 0x1 << 10 | 0x1 << 4 | 0xC ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 11, PAGE 32 (ALL RESERVED)
  WriteADF5355( 0x0061300B ) ;

  // REGISTER 10, PAGE 32
  BitStaengeli = 0x00C00000 | ADC_CLK_DIV << 6 
  | ADC_CONVERSION << 5 | ADC_ENABLE << 4 | 0xA ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 9, PAGE 32
  BitStaengeli = VCO_BAND_DIV << 24 | TIMEOUT << 14 
  | ALC_WAIT << 9 | SLC_WAIT << 4 | 0x9 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 8, PAGE 31 (ALL RESERVED)
  WriteADF5355( 0x102D0428 ) ;

  // REGISTER 7, PAGE 30
  BitStaengeli = 0x1 << 28 | LE_SYNCHRONIZATION << 25 
  | LOCK_DETECT_CYCLE_COUNT << 8 | LOSS_OF_LOCK_MODE << 7;
  BitStaengeli = BitStaengeli | FRACTIONAL_N_LD_PRECISION << 5 
  | LOCK_DETECT_MODE << 4  | 0x7 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 6, PAGE 30
  if ( FreqOUT >= 53125000 )
  {
    FreqVCO = FreqOUT;
    OUTDivider = 64 ;
    RF_DIVIDER_SELECT = 6 ;
    RFOUTA = 1 ;  // ENABLED
    RFOUTB = 0 ;  // ENABLED
    FEEDBACK_SELECT = 1 ;
  }
  if ( FreqOUT >= 106250000 )
  {
    FreqVCO = FreqOUT;
    OUTDivider = 32 ;
    RF_DIVIDER_SELECT = 5 ;
    RFOUTA = 1 ;  // ENABLED
    RFOUTB = 0 ;  // ENABLED
    FEEDBACK_SELECT = 1 ;
  }
  if ( FreqOUT >= 212500000 )
  {
    FreqVCO = FreqOUT;
    OUTDivider = 16 ;
    RF_DIVIDER_SELECT = 4 ;
    RFOUTA = 1 ;  // ENABLED
    RFOUTB = 0 ;  // ENABLED
    FEEDBACK_SELECT = 1 ;
  }
  if ( FreqOUT >= 425000000 )
  {
    FreqVCO = FreqOUT;
    OUTDivider = 8 ;
    RF_DIVIDER_SELECT = 3 ;
    RFOUTA = 1 ;  // ENABLED
    RFOUTB = 0 ;  // ENABLED
    FEEDBACK_SELECT = 1 ;
  }
  if ( FreqOUT >= 850000000 )
  {
    FreqVCO = FreqOUT;
    OUTDivider = 4 ;
    RF_DIVIDER_SELECT = 2 ;
    RFOUTA = 1 ;  // ENABLED
    RFOUTB = 0 ;  // ENABLED
    FEEDBACK_SELECT = 1 ;
  }
  if ( FreqOUT >= 1700000000 )
  {
    FreqVCO = FreqOUT;
    OUTDivider = 2 ;
    RF_DIVIDER_SELECT = 1 ;
    RFOUTA = 1 ;  // ENABLED
    RFOUTB = 0 ;  // ENABLED
    FEEDBACK_SELECT = 1 ;
  }
  if ( FreqOUT >= 3400000000 )
  {
    FreqVCO = FreqOUT;
    OUTDivider = 1 ;
    RF_DIVIDER_SELECT = 0 ;
    RFOUTA = 1 ;  // ENABLED
    RFOUTB = 0 ;  // ENABLED
    FEEDBACK_SELECT = 0 ; // DIRECTLY FROM VCO
  }
  if ( FreqOUT >= 6800000000 )
  {
    FreqVCO = FreqOUT / 2 ;
    OUTDivider = 1 ;
    RF_DIVIDER_SELECT = 0 ;
    RFOUTA = 1 ;  // ENABLED
    RFOUTB = 0 ;  // ENABLED
    FEEDBACK_SELECT = 0 ; // DIRECTLY FROM VCO
  }

  // calculate INTEGER_VALUE, FRAC1_WORD, FRAC2_WORD
  FreqPFD = FreqREF * ((1 + REFERENCE_DOUBLER) 
  / (R_DIVIDER *(1 + REFERENCE_DIVIDE_BY_2)));
  double FreqOUT_double = FreqVCO;
  N_Calculation = (FreqOUT_double * OUTDivider / FreqPFD);
  INTEGER_VALUE = N_Calculation;  
  // INTEGER_VALUE now contains N without decimals
  FRAC1_WORD = (N_Calculation - INTEGER_VALUE) * 16777216;
  FRAC2_WORD=((N_Calculation-INTEGER_VALUE)*16777216-FRAC1_WORD)*MOD2_WORD;
  // ///////////////////////////////////////////////

  BLEED_CURRENT = round(4*0.9/N_Calculation/0.00375);

  BitStaengeli = GATED_BLEED << 30 | NEGATIVE_BLEED 
  << 29 | 0xA << 25 | FEEDBACK_SELECT << 24 ;
  BitStaengeli = BitStaengeli | RF_DIVIDER_SELECT << 21 
  | BLEED_CURRENT << 13 | MUTE_TILL_LOCK_DETECT << 11 ;
  BitStaengeli = BitStaengeli | RFOUTB << 10 | RFOUTA 
  << 6 | OUTPUT_POWER << 4 | 0x6 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 5, PAGE 27 (ALL RESERVED)
  WriteADF5355( 0x00800025 ) ;

  // REGISTER 4, PAGE 26 (ALL RESERVED)
  // WITH R DIVIDER DOUBLED
 // R_DIVIDER *= 2 ;
  BitStaengeli = MUXOUT << 27 | REFERENCE_DOUBLER << 26 
  | REFERENCE_DIVIDE_BY_2 << 25 | R_DIVIDER << 15 ;
  BitStaengeli = BitStaengeli | DOUBLE_BUFFERED << 14 
  | CURRENT_SETTING << 10 | REFIN << 9 ;
  BitStaengeli = BitStaengeli | MUX_LOGIC << 8 | PD_POLARITY << 7 
  | POWER_DOWN << 6 | CP_THREE_STATE << 5 ;
  BitStaengeli = BitStaengeli | COUNTER_RESET << 4 | 0x4 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 3, PAGE 25 (ALL RESERVED)
  BitStaengeli = SD_LOAD_RESET << 30 | PHASE_RESYNC << 29 
  | PHASE_ADJUST << 28 | PHASE_VALUE << 4 | 0x3 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 2, PAGE 24
  // FOR HALFED FPFD
  BitStaengeli = FRAC2_WORD << 18 | MOD2_WORD << 4 | 0x2 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 1, PAGE 23
  // FOR HALFED FPFD
  BitStaengeli = FRAC1_WORD << 4 | 0x1 ;
  WriteADF5355( BitStaengeli ) ;
  delayMicroseconds(161);

  // REGISTER 0, PAGE 22
  // AUTOCALIBRATION ENABLED
  if ( N_Calculation >= 75 )
  {
    PRESCALER = 0x1;
  }
  else
  {
    PRESCALER = 0x0;
  }
  VCO_AUTOCAL = 0x1;
  BitStaengeli = VCO_AUTOCAL << 21 | PRESCALER << 20 
  | INTEGER_VALUE << 4 | 0x0 ;
  WriteADF5355( BitStaengeli ) ;
/*
  // RE-WERITE REGISTERS 4, 2, 1 & 0
  
  // REGISTER 4, PAGE 26 (ALL RESERVED)
  // WITH R DIVIDER AS DESIRED
  R_DIVIDER /= 2 ;
  BitStaengeli = MUXOUT << 27 | REFERENCE_DOUBLER << 26 
  | REFERENCE_DIVIDE_BY_2 << 25 | R_DIVIDER << 15 ;
  BitStaengeli = BitStaengeli | DOUBLE_BUFFERED << 14 
  | CURRENT_SETTING << 10 | REFIN << 9 ;
  BitStaengeli = BitStaengeli | MUX_LOGIC << 8 | PD_POLARITY << 7 
  | POWER_DOWN << 6 | CP_THREE_STATE << 5 ;
  BitStaengeli = BitStaengeli | COUNTER_RESET << 4 | 0x4 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 2, PAGE 24
  // FOR DESIRED FPFD
  BitStaengeli = FRAC2_WORD << 18 | MOD2_WORD << 4 | 0x2 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 1, PAGE 23
  // FOR DESIRED FPFD
  BitStaengeli = FRAC1_WORD << 4 | 0x1 ;
  WriteADF5355( BitStaengeli ) ;

  // REGISTER 0, PAGE 22
  // AUTOCALIBRATION DISABLED
  if ( N_Calculation >= 75 )
  {
    PRESCALER = 0x1;
  }
  else
  {
    PRESCALER = 0x0;
  }
  VCO_AUTOCAL = 0x0;
  BitStaengeli = VCO_AUTOCAL << 21 | PRESCALER << 20 
  | INTEGER_VALUE << 4 | 0x0 ;
  WriteADF5355( BitStaengeli ) ;
*/
}


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


void ShowFrequencyMenue ()
{
  char str[20];
  sprintf(str, "%10lld", FreqOUT);
  int len=strlen(str);
  int offset = 0;
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(0,0);
  display.println("FREQUENCY");
  for (int i=0; i<10; i++)
  {
    if (i>=0) offset = 0;
    if (i>=1) offset = 5;
    if (i>=4) offset = 10;
    if (i>=7) offset = 15;
    display.setTextColor(WHITE);
    display.setCursor(i*11+offset,20);
    if (i<10-len) display.print(" ");
    else display.print(str[i]);
    if ((ShowCursor) && (CursorPosition == i))
    {
      display.setCursor(i*11+offset,26);
      display.print("_");
    }
  }
  ShowInfo();
  display.display();
}

void ShowAmplitudeMenue ()
{
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(0,0);
  display.println("AMPLITUDE");
  display.setCursor(0,20);
  if (LACT > 0.0) display.print("+");
  if (LACT == 0.0) display.print(" ");
  display.print(LACT,1);
  display.print(" dBm ");
  ShowInfo();
  display.display();
}



void ShowErrorMenue ()
{
  display.clearDisplay();
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.setCursor(0,0);
  display.println("ERROR 0x89");
  display.setCursor(0,20);
  display.print("UNLOCKED");
  ShowInfo();
  display.display();
}

void ShowInfo()
{
  display.drawLine(0, 40, 128, 40, WHITE);
  display.setTextSize(1);
  display.setCursor(0,46);
  display.println("PRESS ->  ROTATE +/-");
  display.setCursor(0,57);
  display.print("REFERENCE ");
  if (digitalRead(Locked)) display.print("LOCKED ");
  else display.print("UNLOCKED ");
  RefInputLevel = analogRead(RefInputLevelPin) / 75 ;
  display.print(RefInputLevel);
}

// CHECK ROTARY ENCODER
void CheckRE()
{
RE_old = RE_now ;
RE_now = (digitalRead(RE2) << 2 ) | (digitalRead(RE1) 
<< 1 ) | digitalRead(RE0);
RE_xor = RE_now ^ RE_old ;
}


// /////////////////////////////////////////////////////////////////////
// SUBROUTINES ATTENUATOR.
// /////////////////////////////////////////////////////////////////////


// SET RF LEVEL / BOTH ATTENUATORS
void SetRFLevel(float RFLevel, long long Frequency)
{
  ATT = LMAX - RFLevel ;
  unsigned int IndexCalValue = (int)(Frequency / 200000000); // FLOOR
  CAL = AC[IndexCalValue] ;
  // HMC232ALP4E SWITCH
  if (FreqOUT > FreqRangeSwitchValue) Range = RangeHigh ;
  else Range = RangeLow ;
  // //////////////////////////////////////
  /*
  // ATT *= 2;
  // CAL *= 2;
  

  unsigned int CALBYTE = (int)(CAL * 2.0) ;
  unsigned int ATTBYTE = (int)(ATT * 2.0) ; 

  */
  // /////////////////////////////////////
  // REVERSE THE ORDER TO MATCH MCP23017 LAYOUT
  // CALBYTE:
  CALBYTE = 0xFF;
  if ( CAL >=   8 )
  {
    CALBYTE -= 0x02;
    CAL -=   8;
  }
  if ( CAL >=   4 )
  {
    CALBYTE -= 0x04;
    CAL -=   4;
  }
  if ( CAL >=   2 )
  {
    CALBYTE -= 0x08;
    CAL -=   2;
  }
  if ( CAL >=   1 )
  {
    CALBYTE -= 0x10;
    CAL -=   1;
  }
  if ( CAL >= 0.5 )
  {
    CALBYTE -= 0x20;
    CAL -= 0.5;
  }
  if ( ATT >= 32 )    
// use LSB of CALREG (-16dB) to increase level range from 31.5dBm to 47.5dBm
  {
    CALBYTE -= 0x01;
    ATT -= 16;
  }
  // ATTBYTE:
  ATTBYTE = 0xFF;
  if ( ATT >=  16 )
  {
    ATTBYTE -= 0x01;
    ATT -=  16;
  }
  if ( ATT >=   8 )
  {
    ATTBYTE -= 0x02;
    ATT -=   8;
  }
  if ( ATT >=   4 )
  {
    ATTBYTE -= 0x04;
    ATT -=   4;
  }
  if ( ATT >=   2 )
  {
    ATTBYTE -= 0x08;
    ATT -=   2;
  }
  if ( ATT >=   1 )
  {
    ATTBYTE -= 0x10;
    ATT -=   1;
  }
  if ( ATT >= 0.5 )
  {
    ATTBYTE -= 0x20;
    ATT -= 0.5;
  }
  if (Range == RangeHigh) ATTBYTE -= RangeHigh;
  if (Range == RangeLow) ATTBYTE -= RangeLow;
  //Serial.print("ATT: "); Serial.println(ATT, BIN);
  Serial.print("CALBYTE: "); Serial.println(CALBYTE, BIN);
  Serial.print("ATTBYTE: "); Serial.println(ATTBYTE, BIN);
  
  // WRITE NEW REGISTERS
  Wire.beginTransmission(MCPADR);
  Wire.write(ATTREGADR); // address port A
  Wire.write(ATTBYTE);  // value to send
  Wire.endTransmission();
  
  Wire.beginTransmission(MCPADR);
  Wire.write(CALREGADR); // address port B
  Wire.write(CALBYTE);  // value to send
  Wire.endTransmission();
}

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





✈ Hints




No need to send emails to my boss. He can not build this shield.




✈ 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 = 6503 d

t2 = 379 ms

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

Impressum