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.
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
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.
The Reference Shield, based on a TCXO and Voltage Regulator
The final assembly, ready to be shipped to our labs
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 ?