adf435x is a suite of software and firmware for controlling the Analog Devices ADF4351 (and ADF4350) series of wide-band RF PLL synthesizers.
The software is developed and maintained on Linux Debian Stable and should work on systems with a libusb-1.0
implementation, e.g. FreeBSD, MacOS or even Windows (with the help of Zadig).
The suite consists of the following components:
- adf435x - A python library that can control the ADF4350/1 via various hardware interface back-ends.
- adf435xctl - A command line tool to control the ADF4350/1 manually.
- adf435xgui - A QT-based user interface for the ADF4351 Eval board, see the README.
- adf435xinit - A command line tool to transfer the FX2 firmware to the RAM of the EVAL-ADF4351 board.
- fx2adf435xfw.ihx - A firmware file for upload to the RAM of the Cypress FX2 that replaces the proprietary firmware for the EVAL-ADF4351 board.
- fx2adf435xfw.iic - The same firmware in the file format for permanent storage in the large EEPROM of the Cypress FX2.
-
Install depedencies:
On Debian/Ubuntu:
sudo apt install python3-setuptools python3-usb
- Build a Debian package:
make deb
- Install the Debian package:
make debinstall
This code sets the output frequency to 100 MHz:
from adf435x.interfaces import FX2
from adf435x import freq_make_regs
intf = FX2()
freq = 100
regs = freq_make_regs(freq)
intf.set_regs(regs[::-1])
See also adf435xctl
and the examples/
sub-directory.
Requires adf435x to be installed.
usage: adf435xctl [-h] [--device-type DEVICE_TYPE] [--freq FREQ] [--ref-freq REF_FREQ] [--r-counter R_COUNTER]
[--ref-doubler] [--ref-div2] [--feedback-select FEEDBACK_SELECT]
[--band-select-clock-divider BAND_SELECT_CLOCK_DIVIDER]
[--band-select-clock-mode BAND_SELECT_CLOCK_MODE] [--int INT] [--frac FRAC] [--mod MOD]
[--phase-value PHASE_VALUE] [--prescaler-4-5] [--low-noise-spur-mode LOW_NOISE_SPUR_MODE]
[--mux-out MUX_OUT] [--double-buff-r4] [--charge-pump-current CHARGE_PUMP_CURRENT] [--ldp LDP]
[--pd-polarity PD_POLARITY] [--powerdown] [--cp-three-state] [--counter-reset] [--abp ABP]
[--charge-cancel] [--csr] [--clk-div-mode CLK_DIV_MODE] [--clock-divider-value CLOCK_DIVIDER_VALUE]
[--output-divider OUTPUT_DIVIDER] [--vco-powerdown] [--mute-till-lock-detect]
[--aux-output-select AUX_OUTPUT_SELECT] [--aux-output-enable] [--aux-output-power AUX_OUTPUT_POWER]
[--output-disable] [--output-power OUTPUT_POWER] [--ld-pin-mode LD_PIN_MODE] [--r0 R0] [--r1 R1]
[--r2 R2] [--r3 R3] [--r4 R4] [--r5 R5] [--interface INTERFACE] [--lock-detect] [-v] [-V]
[--init-none | --init-stand-alone | --init-always]
Control program for ADF4350/1 eval board
options:
-h, --help show this help message and exit
--device-type DEVICE_TYPE
default = 1
--freq FREQ, -f FREQ default = 50.0
--ref-freq REF_FREQ default = 25.0
--r-counter R_COUNTER
default = 250
--ref-doubler default = False
--ref-div2 default = False
--feedback-select FEEDBACK_SELECT
default = 1
--band-select-clock-divider BAND_SELECT_CLOCK_DIVIDER
default = None
--band-select-clock-mode BAND_SELECT_CLOCK_MODE
default = 0
--int INT default = 100
--frac FRAC default = 0
--mod MOD default = 2
--phase-value PHASE_VALUE
default = None
--prescaler-4-5 default = False
--low-noise-spur-mode LOW_NOISE_SPUR_MODE
default = 0
--mux-out MUX_OUT default = 0
--double-buff-r4 default = False
--charge-pump-current CHARGE_PUMP_CURRENT
default = 2.5
--ldp LDP default = 10.0
--pd-polarity PD_POLARITY
default = 1
--powerdown default = False
--cp-three-state default = False
--counter-reset default = False
--abp ABP default = 10
--charge-cancel default = False
--csr default = False
--clk-div-mode CLK_DIV_MODE
default = 0
--clock-divider-value CLOCK_DIVIDER_VALUE
default = 150
--output-divider OUTPUT_DIVIDER
default = 1
--vco-powerdown default = False
--mute-till-lock-detect
default = False
--aux-output-select AUX_OUTPUT_SELECT
default = 0
--aux-output-enable default = False
--aux-output-power AUX_OUTPUT_POWER
default = -4.0
--output-disable default = False
--output-power OUTPUT_POWER
default = 5.0
--ld-pin-mode LD_PIN_MODE
default = 1
--r0 R0
--r1 R1
--r2 R2
--r3 R3
--r4 R4
--r5 R5
--interface INTERFACE
INTERFACE: FX2 (default), BusPirate, tinyADF, NONE
--lock-detect query adf435x digital lock detect state
-v increase verbosity
-V, --version show adf435x version and exit
--init-none clear init settings and exit
--init-stand-alone set current settings as init for no-USB mode and exit
--init-always set current settings as init for power-on and exit
adf435x version 0.3.8
Sets the output frequency to 1000 MHz.
The program adf435xctl
returns 0
(no error) on success, otherwise != 0
.
./adf435xctl --freq=1000
Sets the output frequency to 1000 MHz, sets MUXOUT pin to reflect LD (6 = digital lock detect) and checks the pin status.
When locked, the command prints "LOCKED" and returns 0
(no error), otherwise it prints "NOLOCK" and returns 1
(error).
./adf435xctl --freq=1000 --lock-detect
This allows to chain the program.
./adf435xctl --freq=1000 --lock-detect && echo SUCCESS
The Cypress FX2 firmware is intended for the Anlog Devices board EVAL-ADF435x or compatible settings, e.g. a combination of a ADF4351 breakout board with a Cypress FX2 eval board. It controls the ADF435x synthesizer chip by bit-banging three of FX2's GPIOs. The firmware supports these vendor commands:
USB_REQ_SET_REG
(0xDD) - write 4 or 5 byte - an optional 5th byte is ignored to be compatible with the Analog Devices evaluation software. The 4 byte register content is written to the ADF435x registers via the SPI connection.USB_REQ_EE_REGS
(0xDE) - store or clear the default register settings in EEPROM.USB_REQ_GET_MUX
(0xDF) - read 1 byte wherebit 0
reflects the state of theMUXOUT
pin of ADF435x. The other bits 1..7 are reserved and currently set to0
.USB_REQ_CYPRESS_EEPROM_SB
(0xA2) - read or write EEPROM, defaults to small, but detects large address mode.USB_REQ_CYPRESS_EXT_RAM
(0xA3) - read or write the RAMUSB_REQ_CYPRESS_EEPROM_DB
(0xA9) - read or write the large EEPROM on the eval board.
The firmware requires the following wiring:
FX2 Pin | ADF4350/1 Pin | |
---|---|---|
33 (PA0) | --> | 3 (LE) |
34 (PA1) | --> | 1 (CLK) |
35 (PA2) | --> | 2 (DATA) |
25 (PB0) | <-- | 30 (MUXOUT) |
The PB0 - MUXOUT connection is required only if you want to read the state of the MUXOUT pin, e.g. to get the LD (lock detect) condition (set MUXOUT bits of reg 2 to 6).
- First init/update all the sub-modules within the git repository, silence the message about changed submodule:
git submodule update --init
-
Install AutoTools and the SDCC (Small Devices C Compiler).
On Debian/Ubuntu:
sudo apt install make sdcc
- Build the firmware:
make firmware
You will get the firmware files fx2adf435xfw.ihx
and fx2adf435xfw.iic
Another Cypress FW based on fx2lib is located in firmware/fx2.fx2lib. It supports only a reduced functionality compared to the counterpart in firmware/fx2 and has a more complex syntax.
If you didn't already store the firmware permanently in EEPROM (see later), the upload must be performed each time the module is connected to the PC. This has the advantage, that you cannot brick your device, even when you upload corrupt FW. Just disconnect and reconnect and upload the correct FW.
Install cycfx2prog.
On Debian/Ubuntu:
sudo apt install cycfx2prog
- Connect the FX2 board to the USB, a typical FX2 eval board should come up with VID:PID
04b4:8613
, while an Analog Devices ADF435x eval board clone announces typically as0456:b40d
or0456:b403
. - Load the firware file
fx2adf435xfw.ihx
to the unconfigured Cypress FX2 RAM with the following command:
cycfx2prog prg:fx2adf435xfw.ihx run
or use the command ./adf435xinit
.
If the eval board clone announces already as e.g. 0456:b40d
, modify the upload command:
cycfx2prog -id=0x0456.0xb40d prg:fx2adf435xfw.ihx run
- The device will now renumerate with the VID:PID
0456:b40d
as an "ANALOG DEVICES" "EVAL-ADF4351".
If you're an experienced FX2 hacker you can also store the firmware file fx2adf435xfw.iic
permanently in the large 8K or 16K EEPROM of the FX2 board.
For technical details see the Cypress AN50963.
Even with this approach you cannot brick your device, if the storage fails, just deactivate the EEPROM
(e.g. with a jumper on the FX2 board) and repeat the programming.
See the complete documentation for details.
You can use the simple command line tool fx2eeprom.
- Prepare the tools
apt install cycfx2prog libusb-1.0-0-dev
git clone https://github.com/Ho-Ro/fx2eeprom.git
cd fx2eeprom
make
- Copy the file
fx2adf435xfw.iic
into thefx2eeprom
directory. - Activate the large EEPROM, on my Chinese eval board by removing the jumper
JP1
. - Connect the device, check the VID:PID, e.g. with
lsusb
orsudo dmesg
, it's typically0x0456
:0xb40d
(ADF435x eval board) or0x0456
:0xb403
(ADF4xxx interface). - Write the firmware into EEPROM, use the VID:PID as above.
./fx2eeprom w 0x0456 0xb40d < fx2adf435xfw.iic
- Disconnect and reconnect the eval board, it will now come up with VID/PID
0456:b40d
as an "ANALOG DEVICES" "EVAL-ADF4351" and can be used immediately from now on.
Another possibility is to use the GUI program cyusb that has a lot of additional features.
- Build and install it following the instructions.
- Make sure you do not have another Cypress FX2 based device (e.g. a Salae LA clone) connected to your PC.
- Deactivate the large EEPROM - on my Chinese eval board by setting the jumper
JP1
in the center of the board, this changes the EEPROM address lineA0
from HI to LO and alters its I2C address from0xA2
to0xA0
. As the FX2 reads its VID/PID setting on power-on either from a small EEPROM at0xA0
or a large EEPROM at0xA2
the I2C read is not possible and the device comes up with the FX2 default setting04b4:8613
- Connect the board to USB where it will enumerate as
04b4:8613
. - Remove the address jumper
J1
, this enables the large EEPROM access again without changing the USB IDs. - Start the program
cyusb
, the board is detected with VID:PID04b4:8613
(Cypress FX2 chip). - Select this device, open the
Program
tab, selectDownload to Large EEPROM
. - Select the file
fx2adf435xfw.iic
and start the download. After success close the program. - Disconnect and reconnect the eval board, it will now come up with VID/PID
0456:b40d
as an "ANALOG DEVICES" "EVAL-ADF4351" and can be used immediately from now on.
These components can be used if you want to control a simple ADF435x breakout board without communication processor with different interfaces, that provide the simple three-wire interface to the ADF4351:
stm32adf435xfw.bin - An (untested) firmware for the STM32F103,
see README_stm32.md
.
It's also possible to use the Bus Pirate
as the interface for the SPI
communications, simply using the adf435x.interfaces.BusPirate
class.
Another optional (very slow) interface is the experimental DigiSpark Tiny85 module
with Arduino SW that receives USB serial commands, simply using the adf435x.interfaces.tinyADF
class.