summaryrefslogtreecommitdiff
path: root/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py')
-rwxr-xr-xgnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py186
1 files changed, 186 insertions, 0 deletions
diff --git a/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py b/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py
new file mode 100755
index 0000000000..b46c896f73
--- /dev/null
+++ b/gnuradio-core/src/python/gnuradio/gruimpl/lmx2306.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python
+#
+# Copyright 2004 Free Software Foundation, Inc.
+#
+# This file is part of GNU Radio
+#
+# GNU Radio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# GNU Radio is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Radio; see the file COPYING. If not, write to
+# the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+
+'''Control National LMX2306 based frequency synthesizer'''
+
+from gnuradio import gr
+from gnuradio import eng_notation
+from gnuradio.eng_option import eng_option
+from optparse import OptionParser
+
+# bottom two bits of 21 bit word select which register to program
+
+R_REG = 0x0
+AB_REG = 0x1
+F_REG = 0x2
+
+F_counter_reset = (1 << 2)
+F_phase_detector_polarity = (1 << 7)
+
+F_LD_tri_state = (0 << 4)
+F_LD_R_divider_output = (4 << 4)
+F_LD_N_divider_output = (2 << 4)
+F_LD_serial_data_output = (6 << 4)
+F_LD_digital_lock_detect = (1 << 4)
+F_LD_open_drain = (5 << 4)
+F_LD_high = (3 << 4)
+F_LD_low = (7 << 4)
+
+# F_default = F_LD_digital_lock_detect | F_phase_detector_polarity
+F_default = F_LD_open_drain | F_phase_detector_polarity
+
+#
+# 4 control pins:
+# CE always high
+# LE load enable. When LE goes high, data stored in the shift register
+# is loaded into one of the three registers
+# CLK data is clocked in on the rising edge
+# DATA single data bit. Entered MSB first
+
+DB_CLK = (1 << 0)
+DB_DATA = (1 << 1)
+DB_LE = (1 << 2)
+DB_CE = (1 << 3)
+
+class lmx2306 (object):
+ '''Control the National LMX2306 PLL'''
+ __slots__ = ['pp', 'shadow', 'fosc', 'r', 'step_size', 'verbose']
+ def __init__ (self, fosc, step_size, which_pp = 0):
+ '''FOSC is the frequency of the reference oscillator,
+ STEP_SIZE is the step between valid frequencies,
+ WHICH_PP specifies which parallel port to use
+ '''
+ self.pp = gr.make_ppio (which_pp)
+ self.shadow = DB_CE
+ self.pp.lock ()
+ self.pp.write_data (self.shadow)
+ self.pp.unlock ()
+ self.verbose = False
+ self._set_fosc (fosc)
+ self._set_step (step_size)
+
+
+ def program (self, r, a, b):
+ if self.verbose:
+ print "lmx2306: r = %d a = %d b = %d" % (r, a, b)
+ self.pp.lock ()
+ self._write_word (F_REG | F_default | F_counter_reset)
+ self._write_word (R_REG | ((r & 0x3fff) << 2))
+ self._write_word (AB_REG | ((a & 0x1f) << 2) | ((b & 0x1fff) << 7))
+ self._write_word (F_REG | F_default)
+ self.pp.unlock ()
+
+ def set_freq (self, freq):
+ '''Set the PLL frequency to FREQ
+
+ Return the actual freq value set. It will be rounded down to a
+ multiple of step_size
+ '''
+ divisor = int (freq / self.step_size)
+ actual = divisor * self.step_size
+ (a, b) = self._compute_ab (divisor)
+ self.program (self.r, a, b)
+ return actual
+
+ # ----------------------------------------------------------------
+
+ def _set_fosc (self, ref_oscillator_freq):
+ self.fosc = ref_oscillator_freq
+
+ def _set_step (self, step_size):
+ r = int (self.fosc / step_size)
+ if r * step_size != self.fosc:
+ raise ValueError, "step_size is not a factor of self.fosc"
+ if r < 3 or r > 16383:
+ raise ValueError, "r is out of range"
+ self.r = r
+ self.step_size = step_size
+
+ def _compute_ab (self, divisor):
+ b = divisor / 8
+ a = divisor - (b * 8)
+ if b < 3 or b > 8191 or a > b:
+ raise ValueError, "Invalid divisor"
+ return (a, b)
+
+ def _write_word (self, w):
+ for i in range(21):
+ if w & (1 << 20):
+ self._set_DATA_1 ()
+ else:
+ self._set_DATA_0 ()
+ w = (w << 1) & 0x0ffffff
+ self._set_CLK_1 ()
+ self._set_CLK_0 ()
+ self._set_LE_1 ()
+ self._set_LE_0 ()
+
+ def _set_LE_0 (self):
+ self.shadow = self.shadow & ~DB_LE
+ self.pp.write_data (self.shadow)
+
+ def _set_LE_1 (self):
+ self.shadow = self.shadow | DB_LE
+ self.pp.write_data (self.shadow)
+
+ def _set_CLK_0 (self):
+ self.shadow = self.shadow & ~DB_CLK
+ self.pp.write_data (self.shadow)
+
+ def _set_CLK_1 (self):
+ self.shadow = self.shadow | DB_CLK
+ self.pp.write_data (self.shadow)
+
+ def _set_DATA_0 (self):
+ self.shadow = self.shadow & ~DB_DATA
+ self.pp.write_data (self.shadow)
+
+ def _set_DATA_1 (self):
+ self.shadow = self.shadow | DB_DATA
+ self.pp.write_data (self.shadow)
+
+if __name__ == '__main__':
+ parser = OptionParser (option_class=eng_option)
+ parser.add_option ("-o", "--fosc", type="eng_float", default=32e6,
+ help="set reference oscillator freq to FREQ", metavar="FREQ")
+ parser.add_option ("-s", "--step-size", type="eng_float", default=10e3,
+ help="set the frequency step size to STEP_SIZE")
+ parser.add_option ("-f", "--freq", type="eng_float", default=430e6,
+ help="set VCO frequency to FREQ")
+ parser.add_option ("-v", "--verbose", action="store_true", default=False)
+ (options, args) = parser.parse_args ()
+
+ if options.verbose:
+ print "fosc = %s step = %s fvco = %s" % (
+ eng_notation.num_to_str (options.fosc),
+ eng_notation.num_to_str (options.step_size),
+ eng_notation.num_to_str (options.freq))
+
+ lmx = lmx2306 (options.fosc, options.step_size)
+ lmx.verbose = options.verbose
+
+ actual = lmx.set_freq (options.freq)
+
+ if options.verbose:
+ print "fvco_actual = %s delta = %s" % (
+ eng_notation.num_to_str (actual),
+ eng_notation.num_to_str (options.freq - actual))