Arduino Library for the MAX2870 Wideband Frequency Synthesizer chip
v1.0.0 First release
v1.0.1 Double buffering of RF frequency divider implemented by default
v1.1.0 Added current frequency read function
v1.1.1 Corrected issue with conversion in ReadCurrentFreq
v1.1.2 Add setPowerLevel function which can be used for frequency bursts
v1.1.3 Added direct entry of frequency parameters for precalculated frequencies of the highest possible precision
v1.1.4 Added configuration of charge pump current and phase detector polarity
This library supports the MAX2870 from Maxim on Arduinos. The chip is a wideband (23.475 MHz to 6 GHz) Phase-Locked Loop (PLL) and Voltage Controlled Oscillator (VCO), covering a very wide range frequency range under digital control. Just add an external PLL loop filter, Reference frequency source and a power supply for a very useful frequency generator for applications as a Local Oscillator or Sweep Generator.
The chip generates the frequency using a programmable Fractional-N and Integer-N Phase-Locked Loop (PLL) and Voltage Controlled Oscillator (VCO) with an external loop filter and frequency reference. The chip is controlled by a SPI interface, which is controlled by a microcontroller such as the Arduino.
The library provides an SPI control interface for the MAX2870, and also provides functions to calculate and set the frequency, which greatly simplifies the integration of this chip into a design. The calculations are done using the excellent Big Number Arduino Library by Nick Gammon, as the integter calculations require great than 32bit integers that are not available on the Arduino. The library also exposes all of the PLL variables, such as FRAC, Mod and INT, so they examined as needed.
Requires the BitFieldManipulation library: http://github.com/brycecherry75/BitFieldManipulation
Requires the BeyondByte library: http://github.com/brycecherry75/BeyondByte
A low phase noise stable oscillator is required for this module. Typically, an Ovenized Crystal Oscillator (OCXO) in the 10 MHz to 100 MHz range is used.
The library is documented in the docs directory, and was created using Doxygen.
An example program using the library is provided in the source directory example2870.ino.
init(SSpin, LockPinNumber, Lock_Pin_Used, CEpin, CE_Pin_Used): initialize the MAX2870 with SPI SS pin, lock pin and true/false for lock pin use and CE pin use - CE pin is typically LOW (disabled) on reset if used; depending on your board, this pin along with the RF Power Down pin may have a pullup or pulldown resistor fitted and certain boards have the RF Power Down pin (low active) on the header
SetStepFreq(frequency): sets the step frequency in Hz - default is 100 kHz - returns an error code
ReadR()/ReadInt()/ReadFraction()/ReadMod(): returns a uint16_t value for the currently programmed register
ReadOutDivider()/ReadOutDivider_PowerOf2()/ReadRDIV2()/ReadRefDoubler(): returns a uint8_t value for the currently programmed register - ReadOutDivider() is automatically converted from a binary exponent to an actual division ratio and ReadOutDivider_PowerOf2() is a binary exponent
ReadPFDfreq(): returns a double for the PFD value
setf(*frequency, PowerLevel, AuxPowerLevel, AuxFrequencyDivider, PrecisionFrequency, FrequencyTolerance, CalculationTimeout): set the frequency (in Hz with char string) power level/auxiliary power level (1-4 in 3dBm steps from -5dBm), mode for auxiliary frequency output (MAX2870AUX(DIVIDED/FUNDAMENTAL)), true/false for precision frequency mode (step size is ignored if true), frequency tolerance (in Hz with uint32_t) under precision frequency mode (rounded to the nearest integer), calculation timeout (in mS with uint32_t - recommended value is 30000 in most cases, 0 to disable) under precision frequency mode - returns an error or warning code
setrf(frequency, R_divider, ReferenceDivisionType): set the reference frequency and reference divider R and reference frequency division type (MAX2870REF(UNDIVIDED/HALF/DOUBLE)) - default is 10 MHz/1/undivided - returns an error code
setfDirect(R_divider, INT_value, MOD_value, FRAC_value, RF_DIVIDER_value, FRACTIONAL_MODE): RF divider value is (1/2/4/8/16/32/64) and fractional mode is a true/false bool - these paramaters will not be checked for invalid values
setPowerLevel/setAuxPowerLevel(PowerLevel): set the power level (0 to disable or 1-4) and write to the MAX2870 in one operation - returns an error code
WriteSweepRegs(regs): high speed write for registers when used for frequency sweep (regs is uint32_t and size is as per MAX2870_RegsToWrite
ReadSweepRegs(regs): high speed read for registers when used for frequency sweep (regs is uint32_t and size is as per MAX2870_RegsToWrite
ReadCurrentFreq(freq): calculation of currently programmed frequency (freq is uint8_t and size is as per MAX2870_ReadCurrentFrequency_ArraySize)
setCPcurrent(Current): set charge pump current in mA floating
setPDpolarity(INVERTING/NONINVERTING): set phase detector polarity for your VCO loop filter
A Python script (MAX2870pf.py) can be used for calculating the required values for setfDirect for speed.
Please note that you should install the provided BigNumber library in your Arduino library directory.
Under non-precision mode, unusual step frequencies e.g. VCO (RF frequency * divider) = 1500.00353 MHz and PFD = 10 MHz (REFIN / R) should be avoided along with a PFD having decimal place(s) to avoid slow GCD calculations for FRAC/MOD and a subsequent FRAC/MOD range error - step sizes for a 10 MHz PFD which do not have this issue are any multiple of 2500/3125/4000 Hz as per this formula (all frequencies are in Hz):
MOD = PFD / step size
FRAC = (N remainder * MOD)
factor = GCD(MOD, FRAC)
MOD = MOD / factor
FRAC = FRAC / factor
At all stages, MOD and FRAC are rounded down to the nearest integer.
Under worst possible conditions (tested with 3.999997551 GHz RF/10 MHz PFD/0 Hz tolerance target error which will go through the entire permissible range of MOD values) on a 16 MHz AVR Arduino, precision frequency mode configuration takes no longer than 45 seconds.
Default settings which may need to be changed as required BEFORE execution of MAX2870 library functions (defaults listed):
Phase Detector Polarity (Register 2/Bit 6 = 1): Positive (passive or noninverting active loop filter)
Error codes:
Common to all of the following subroutines:
MAX2870_ERROR_NONE
SetStepFreq:
MAX2870_ERROR_STEP_FREQUENCY_EXCEEDS_PFD
setf:
MAX2870_ERROR_RF_FREQUENCY
MAX2870_ERROR_POWER_LEVEL
MAX2870_ERROR_AUX_POWER_LEVEL
MAX2870_ERROR_AUX_FREQ_DIVIDER
MAX2870_ERROR_ZERO_PFD_FREQUENCY
MAX2870_ERROR_MOD_RANGE
MAX2870_ERROR_FRAC_RANGE
MAX2870_ERROR_N_RANGE
MAX2870_ERROR_RF_FREQUENCY_AND_STEP_FREQUENCY_HAS_REMAINDER
MAX2870_ERROR_PFD_EXCEEDED_WITH_FRACTIONAL_MODE
MAX2870_ERROR_PRECISION_FREQUENCY_CALCULATION_TIMEOUT
setrf:
MAX2870_ERROR_DOUBLER_EXCEEDED
MAX2870_ERROR_R_RANGE
MAX2870_ERROR_REF_FREQUENCY
MAX2870_ERROR_REF_MULTIPLIER_TYPE
setf and setrf:
MAX2870_ERROR_PFD_AND_STEP_FREQUENCY_HAS_REMAINDER
MAX2870_ERROR_PFD_LIMITS
setPDpolarity:
MAX2870_ERROR_POLARITY_INVALID
Warning codes:
setf:
MAX2870_WARNING_FREQUENCY_ERROR
Copy the src/
directory to your Arduino sketchbook directory (named the directory example2870
), and install the libraries in your Arduino library directory. You can also install the MAX2870 files separatly as a library.