Skip to content

Instantly share code, notes, and snippets.

@edy555
Created October 2, 2013 17:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save edy555/6797579 to your computer and use it in GitHub Desktop.
Save edy555/6797579 to your computer and use it in GitHub Desktop.
Control script to configure Analog Devices ADF4351 via USB HID
#!/usr/bin/env python
import hid
import math
verbose = False
class ADF4351:
DIV1 = 0
DIV2 = 1
DIV4 = 2
DIV8 = 3
DIV16 = 4
DIV32 = 5
DIV64 = 6
REG0 = 0
REG1 = 1
REG2 = 2
REG3 = 3
REG4 = 4
REG5 = 5
REG0_DEF = ( ("unused", 1),
("int", 16),
("frac", 12),
("control", 3, REG0))
REG1_DEF = ( ("unused", 3),
("phaseadjust", 1),
("prescaler", 1),
("phase", 12, 1),
("mod", 12),
("control", 3, REG1))
REG2_DEF = ( ("unused", 1),
("lownoisespurmode", 2),
("muxout", 3, 0b110),
("refdoubler", 1),
("rdiv2", 1),
("rcounter", 10),
("doublebuffer", 1),
("chargepump", 4),
("ldf", 1),
("ldp", 1),
("pdpolar", 1, 1),
("powerdown", 1),
("cpthreestate", 1),
("counterreset", 1),
("control", 3, REG2))
REG3_DEF = ( ("unused", 8),
("bandselectclockmode", 1),
("abp", 1),
("chargecancel", 1),
("unused", 2),
("csr", 1),
("unused", 1),
("clkdivmode", 2),
("clockdivider", 12),
("control", 3, REG3))
REG4_DEF = ( ("unused", 8),
("feedbackselect", 1),
("rfdividerselect", 3),
("bandselectclockdivider", 8, 16),
("vcopowerdown", 1),
("mtld", 1),
("auxoutputselect", 1),
("auxoutputenable", 1, 1),
("auxoutputpower", 2, 3),
("rfoutputenable", 1, 1),
("outputpower", 2, 3),
("control", 3, REG4))
REG5_DEF = ( ("unused", 8),
("ldpinmode", 2, 0b01),
("unused", 1),
("unused", 2),
("unused", 16),
("control", 3, REG5))
CONFIG_DEFAULT = { "int":300, "frac":494, "mod":4000, "rcounter":48,
"chargepump": 15, "pdpolar":1, "bandselectclockmode":1 }
DEFAULT_PDFREQUENCY = 1e6
def get_config_reg(self, conf, bitdef):
#ary = bytearray()
ary = []
byte = 0
i = 8
for k in bitdef:
s = 1
d = 0
if not isinstance(k, str):
if len(k) > 2:
d = k[2]
s = k[1]
k = k[0]
v = conf.get(k)
if v is None:
v = d
while s > 0:
if i >= s:
i -= s
s = 0
if v:
byte |= v << i
else:
n = s - i
s -= i
i = 0
if v:
byte |= v >> n
if i == 0:
ary.append(byte & 0xff)
byte = 0
i = 8
return ary
def __init__(self, conf = {}, h = None):
c = {}
c.update(ADF4351.CONFIG_DEFAULT)
c.update(conf)
self.conf = c
if not h:
h = hid.device(0x04d8, 0x003f)
self.h = h
self.pdfreq = ADF4351.DEFAULT_PDFREQUENCY
def close(self):
self.h.close()
def setPDFrequency(self, pdfreq):
self.pdfreq = pdfreq
def write_reg(self, conf, bitdef):
reg = self.get_config_reg(conf, bitdef)
head = [0xc1, 32]
self.h.write(head + reg)
if verbose:
print ''.join(["%02x"%x for x in head + reg])
def setup(self):
conf = self.conf
self.write_reg(conf, ADF4351.REG5_DEF)
self.write_reg(conf, ADF4351.REG4_DEF)
self.write_reg(conf, ADF4351.REG3_DEF)
self.write_reg(conf, ADF4351.REG2_DEF)
self.write_reg(conf, ADF4351.REG1_DEF)
self.write_reg(conf, ADF4351.REG0_DEF)
def setIntFrac(self, int, frac):
self.conf.update({"int": int, "frac":frac })
self.setup()
def setFrequency(self, freq):
f = self.pdfreq
mod = self.conf["mod"]
i = int(freq / f)
diff = freq - i * f
frac = int(diff * mod / f)
self.setIntFrac(i, frac)
if verbose:
print "int:%d frac:%d"%(i, frac)
if __name__ == '__main__':
import binascii
from optparse import OptionParser
def getDivFromFrequency(freq):
n = int(math.log(4400e6 / freq, 2))
if n > 6:
n = 6
if n < 0:
n = 0
return n
parser = OptionParser(usage="%prog: [options]")
parser.add_option("-v", dest="verbose", action="store_true", default=False,
help="print verbose")
parser.add_option("-d", dest="divide", type="int",
help="rf divider value")
parser.add_option("-e", dest="prescaler", action="store_true", default=False,
help="select prescaler 8/9")
parser.add_option("-p", dest="power", type="int", default=None,
help="aux output power (0/1/2/3)")
parser.add_option("-l", dest="loop", action="store_true", default=False,
help="repeat executions")
(options, args) = parser.parse_args()
freq = 300.1234e6
verbose = options.verbose
if len(args) >= 1:
freq = float(args[0])
div = options.divide or getDivFromFrequency(freq)
prescaler = options.prescaler
power = options.power
try:
if verbose:
print "set frequency:%g div:%d"%(freq,div)
pll = ADF4351(conf={"powerdown":0, "rfdividerselect": div, "prescaler": prescaler, "auxoutputpower":power})
#pll.setPDFrequency(1e6)
#pll.setup()
pll.setFrequency(freq)
#pll.close()
except IOError, ex:
print ex
@spyhound
Copy link

I keep getting "open failed" under ubuntu 14.04 as root at the line:
h = hid.device(0x04d8, 0x003f)
Did you install a driver for this device? I have tried changing the vendor and product id to the ones found by lsusb with the same result.

@edy555
Copy link
Author

edy555 commented May 21, 2014

No, I did not installed any drivers. Generally to use HID device no drivers is needed.
What kind of USB device do you use?
The output of 'lsusb -v' might be useful to investigate the problem.

@ekspla
Copy link

ekspla commented Oct 27, 2016

いつもブログの方をウォッチさせていただいています。
汎用のUSB HID-SPIブリッジとして使えそうなので、追試してみました。(Win32, Python-2.7.12, HIDAPI 0.7.99-post19)
環境によるものかHIDAPIバージョンが違うのか、若干の修正で動きましたのでご参考まで。
line 122:
h = hid.device()
h.open(0x4d8, 0x3f)
line 134:
head = [0x0, 0xc1, 32]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment