[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Commit-gnuradio] r8366 - usrp2/trunk/firmware/lib
From: |
matt |
Subject: |
[Commit-gnuradio] r8366 - usrp2/trunk/firmware/lib |
Date: |
Sat, 10 May 2008 17:38:03 -0600 (MDT) |
Author: matt
Date: 2008-05-10 17:37:56 -0600 (Sat, 10 May 2008)
New Revision: 8366
Added:
usrp2/trunk/firmware/lib/db_tvrx.c
Modified:
usrp2/trunk/firmware/lib/Makefile.am
Log:
first cut at TVRX support, untested
Modified: usrp2/trunk/firmware/lib/Makefile.am
===================================================================
--- usrp2/trunk/firmware/lib/Makefile.am 2008-05-10 23:35:01 UTC (rev
8365)
+++ usrp2/trunk/firmware/lib/Makefile.am 2008-05-10 23:37:56 UTC (rev
8366)
@@ -27,6 +27,7 @@
db_basic.c \
db_init.c \
db_rfx.c \
+ db_tvrx.c \
dbsm.c \
eeprom.c \
ethernet.c \
Added: usrp2/trunk/firmware/lib/db_tvrx.c
===================================================================
--- usrp2/trunk/firmware/lib/db_tvrx.c (rev 0)
+++ usrp2/trunk/firmware/lib/db_tvrx.c 2008-05-10 23:37:56 UTC (rev 8366)
@@ -0,0 +1,396 @@
+/* -*- c++ -*- */
+/*
+ * Copyright 2008 Free Software Foundation, Inc.
+ *
+ * This program 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 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <i2c.h>
+#include <lsdac.h>
+#include <memory_map.h>
+#include <db_base.h>
+#include <hal_io.h>
+#include <ad9510.h>
+#include <stdio.h>
+#include <mdelay.h>
+
+bool tvrx_init(struct db_base *db);
+bool tvrx_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t
*dc);
+bool tvrx_set_gain(struct db_base *db, u2_fxpt_gain_t gain);
+
+#define I2C_ADDR 0x60
+#define ref_freq (U2_DOUBLE_TO_FXPT_FREQ(4e6)/640*8)
+
+#define ref_div 640 /* choices are 640, 512, 1024 */
+
+#if (ref_div == 640)
+#define ref_div_byte 0
+#else
+#if (ref_div == 512)
+#define ref_div_byte 0x6
+#else
+#define ref_div_byte 0x2
+#endif
+#endif
+
+#define fast_tuning 0x40
+
+#define control_byte_1 (0x88|fast_tuning|ref_div_byte)
+
+
+struct db_tvrx_common {
+ // TVRX common stuff
+ u2_fxpt_freq_t first_if;
+ u2_fxpt_freq_t second_if;
+};
+
+struct db_tvrx_dummy {
+ struct db_base base;
+ struct db_tvrx_common common;
+};
+
+struct db_tvrx1 {
+ struct db_base base;
+ struct db_tvrx_common common;
+};
+
+struct db_tvrx2 {
+ struct db_base base;
+ struct db_tvrx_common common;
+};
+
+struct db_tvrx3 {
+ struct db_base base;
+ struct db_tvrx_common common;
+};
+
+/* The class instances */
+struct db_tvrx1 db_tvrx1 = {
+ .base.dbid = 0x0003,
+ .base.is_tx = false,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_step_size = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = false,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = tvrx_init,
+ .base.set_freq = tvrx_set_freq,
+ .base.set_gain = tvrx_set_gain,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x0000,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(43.75e6),
+ .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(5.75e6),
+};
+
+struct db_tvrx2 db_tvrx2 = {
+ .base.dbid = 0x000c,
+ .base.is_tx = false,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_step_size = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = false,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = tvrx_init,
+ .base.set_freq = tvrx_set_freq,
+ .base.set_gain = tvrx_set_gain,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x0000,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
+ .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
+};
+
+struct db_tvrx3 db_tvrx3 = {
+ .base.dbid = 0x0040,
+ .base.is_tx = false,
+ .base.output_enables = 0x0000,
+ .base.used_pins = 0x0000,
+ //.base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.freq_step_size = U2_DOUBLE_TO_FXPT_FREQ(xxx),
+ //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
+ .base.is_quadrature = false,
+ .base.i_and_q_swapped = false,
+ .base.spectrum_inverted = false,
+ //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
+ .base.init = tvrx_init,
+ .base.set_freq = tvrx_set_freq,
+ .base.set_gain = tvrx_set_gain,
+ .base.set_tx_enable = 0,
+ .base.atr_mask = 0x0000,
+ .base.atr_txval = 0,
+ .base.atr_rxval = 0,
+ // .base.atr_tx_delay =
+ // .base.atr_rx_delay =
+ .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
+ .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
+};
+
+bool
+tvrx_init(struct db_base *dbb)
+{
+ struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
+ return true;
+}
+
+bool
+tvrx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
+{
+ *dc = 0;
+ struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
+
+ u2_fxpt_freq_t target_lo_freq = freq + db->common.first_if;
+ int N_DIV = u2_fxpt_freq_round_to_int(((1LL<<20) * target_lo_freq)/ref_freq);
+
+ u2_fxpt_freq_t actual_lo_freq = ref_freq * N_DIV;
+ u2_fxpt_freq_t actual_freq = actual_lo_freq - db->common.first_if;
+ if(N_DIV > 32767)
+ return false;
+
+ printf("N_DIV = %d, actual_freq = %d, actual_lo_freq = %d\n",
+ N_DIV,
u2_fxpt_freq_round_to_int(actual_freq),u2_fxpt_freq_round_to_int(actual_freq));
+
+ char buf[4];
+ buf[0] = (N_DIV>>8) & 0xff;
+ buf[1] = N_DIV & 0xff;
+ buf[2] = control_byte_1;
+ buf[3] = (freq < U2_DOUBLE_TO_FXPT_FREQ(158e6)) ? 0xa8 : // VHF LOW
+ (freq < U2_DOUBLE_TO_FXPT_FREQ(464e6)) ? 0x98 : // VHF HIGH
+ 0x38; // UHF
+
+ *dc = actual_freq - db->common.second_if;
+ return i2c_write(I2C_ADDR,buf,4);
+}
+
+bool
+tvrx_set_gain(struct db_base *dbb, u2_fxpt_gain_t gain)
+{
+ struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
+ int rfgain;
+ int ifgain;
+ if(gain>U2_DOUBLE_TO_FXPT_GAIN(95.0))
+ return false;
+ if(gain<0)
+ return false;
+
+ if(gain>U2_DOUBLE_TO_FXPT_GAIN(60.0)) {
+ rfgain = U2_DOUBLE_TO_FXPT_GAIN(60.0);
+ ifgain = gain-U2_DOUBLE_TO_FXPT_GAIN(60.0);
+ } else {
+ rfgain = gain;
+ ifgain = 0;
+ }
+
+ int rf_slope_q8 = 256 * 4096 * 2.25 / 60.0 / 1.22 / 3.3;
+ int rf_offset_q8 = 256 * 4096 * 1.25 / 1.22 / 3.3;
+ int if_slope_q8 = 256 * 4096 * 2.1 / 35.0 / 1.22 / 3.3;
+ int if_offset_q8 = 256 * 4096 * 1.4 / 1.22 / 3.3;
+
+ lsdac_write_rx(0,(rfgain*rf_slope_q8 + rf_offset_q8)>>15);
+ lsdac_write_rx(1,(ifgain*if_slope_q8 + if_offset_q8)>>15);
+
+ /*
+ def _set_rfagc(self,gain):
+ assert gain <= 60 and gain >= 0
+ # FIXME this has a 0.5V step between gain = 60 and gain = 59.
+ # Why are there two cases instead of a single linear case?
+ if gain == 60:
+ voltage = 4
+ else:
+ voltage = gain/60.0 * 2.25 + 1.25
+ dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain
+
+ assert dacword>=0 and dacword<4096
+ self._u.write_aux_dac(self._which, 1, dacword)
+
+ def _set_ifagc(self,gain):
+ assert gain <= 35 and gain >= 0
+ voltage = gain/35.0 * 2.1 + 1.4
+ dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain
+
+ assert dacword>=0 and dacword<4096
+ self._u.write_aux_dac(self._which, 0, dacword)
+
+
+ lsdac_write_rx(int which_dac, int value);
+
+ */
+ return true;
+}
+
+
+bool
+tvrx_lock_detect(struct db_base *dbb)
+{
+ struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
+ return true;
+}
+
+/*
+class db_tv_rx(db_base.db_base):
+ def __init__(self, usrp, which, first_IF, second_IF):
+ """
+ Control Microtune 4937 based USRP daughterboard.
+
+ @param usrp: instance of usrp.source_c
+ @param which: which side: 0 or 1 corresponding to RX_A or RX_B
respectively
+ @type which: int
+ """
+ # sets _u and _which
+ db_base.db_base.__init__(self, usrp, which)
+
+ self._i2c_addr = (0x60, 0x61)[which]
+
+ self._first_IF = first_IF
+ self._second_IF = second_IF
+ self._reference_divisor = 640
+ self._fast_tuning = False
+ self._inverted = False # FIXME get rid of this
+
+ g = self.gain_range() # initialize gain
+ self.set_gain(float(g[0]+g[1]) / 2)
+
+ self.bypass_adc_buffers(False)
+
+ # Gain setting
+ def _set_rfagc(self,gain):
+ assert gain <= 60 and gain >= 0
+ # FIXME this has a 0.5V step between gain = 60 and gain = 59.
+ # Why are there two cases instead of a single linear case?
+ if gain == 60:
+ voltage = 4
+ else:
+ voltage = gain/60.0 * 2.25 + 1.25
+ dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain
+
+ assert dacword>=0 and dacword<4096
+ self._u.write_aux_dac(self._which, 1, dacword)
+
+ def _set_ifagc(self,gain):
+ assert gain <= 35 and gain >= 0
+ voltage = gain/35.0 * 2.1 + 1.4
+ dacword = int(4096*voltage/1.22/3.3) # 1.22 = opamp gain
+
+ assert dacword>=0 and dacword<4096
+ self._u.write_aux_dac(self._which, 0, dacword)
+
+ def _set_pga(self,pga_gain):
+ assert pga_gain >=0 and pga_gain <=20
+ if(self._which == 0):
+ self._u.set_pga (0, pga_gain)
+ else:
+ self._u.set_pga (2, pga_gain)
+
+ def gain_range(self):
+ return (0, 115, 1)
+
+ def set_gain(self,gain):
+ assert gain>=0 and gain<=115
+ if gain>60:
+ rfgain = 60
+ gain = gain - 60
+ else:
+ rfgain = gain
+ gain = 0
+ if gain > 35:
+ ifgain = 35
+ gain = gain - 35
+ else:
+ ifgain = gain
+ gain = 0
+ pgagain = gain
+ self._set_rfagc(rfgain)
+ self._set_ifagc(ifgain)
+ self._set_pga(pgagain)
+
+ def freq_range(self):
+ return (50e6, 860e6, 10e3)
+
+ def set_freq(self, target_freq):
+ """
+ @returns (ok, actual_baseband_freq) where:
+ ok is True or False and indicates success or failure,
+ actual_baseband_freq is the RF frequency that corresponds to DC in
the IF.
+ """
+ r = self.freq_range()
+ if target_freq < r[0] or target_freq > r[1]:
+ return (False, 0)
+
+ target_lo_freq = target_freq + self._first_IF; # High side mixing
+ f_ref = 4e6 / self._reference_divisor # frequency steps
+
+ divisor = int((target_lo_freq + (f_ref * 4)) / (f_ref * 8))
+ actual_lo_freq = (f_ref * 8 * divisor)
+ actual_freq = actual_lo_freq - self._first_IF;
+
+ if (divisor & ~0x7fff) != 0: # must be 15-bits or less
+ return (False, 0)
+
+ # build i2c command string
+ buf = [0] * 4
+ buf[0] = (divisor >> 8) & 0xff # DB1
+ buf[1] = divisor & 0xff # DB2
+ buf[2] = control_byte_1(self._fast_tuning, self._reference_divisor)
+ buf[3] = control_byte_2(actual_freq, True)
+
+ ok = self._u.write_i2c(self._i2c_addr, int_seq_to_str (buf))
+
+ return (ok, actual_freq - self._second_IF)
+
+ def is_quadrature(self):
+ """
+ Return True if this board requires both I & Q analog channels.
+
+ This bit of info is useful when setting up the USRP Rx mux register.
+ """
+ return False
+
+# hook this daughterboard class into the auto-instantiation framework
+
+# With MT4937DI5-3x7702 with second downconversion
+db_instantiator.add(usrp_dbid.TV_RX,
+ lambda usrp, which : (db_tv_rx(usrp, which, 43.75e6,
5.75e6),))
+
+# With MT4937DI5-3x8680, and 3x8769 without second downconversion
+db_instantiator.add(usrp_dbid.TV_RX_REV_2,
+ lambda usrp, which : (db_tv_rx(usrp, which, 44e6, 20e6),))
+
+# With MT4937DI5-3x7901 without second downconversion, basically the same as
tvrx2
+db_instantiator.add(usrp_dbid.TV_RX_REV_3,
+ lambda usrp, which : (db_tv_rx(usrp, which, 44e6, 20e6),))
+
+*/
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Commit-gnuradio] r8366 - usrp2/trunk/firmware/lib,
matt <=