Merge commit 'v3.3.0' into upstream
[debian/gnuradio] / usrp2 / firmware / lib / db_tvrx.c
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2008,2009 Free Software Foundation, Inc.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <i2c.h>
20 #include <lsdac.h>
21 #include <memory_map.h>
22 #include <db_base.h>
23 #include <hal_io.h>
24 #include <stdio.h>
25
26 bool tvrx_init(struct db_base *db);
27 bool tvrx_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
28 bool tvrx_set_gain(struct db_base *db, u2_fxpt_gain_t gain);
29
30 #define I2C_ADDR 0x60
31 #define REF_FREQ (U2_DOUBLE_TO_FXPT_FREQ(4e6)/640*8)
32
33 #define ref_div 640  /* choices are 640, 512, 1024 */
34
35 #if (ref_div == 640)
36 #define ref_div_byte 0
37 #else
38 #if (ref_div == 512)
39 #define ref_div_byte 0x6
40 #else
41 #define ref_div_byte 0x2
42 #endif
43 #endif
44
45 #define fast_tuning 0x40
46
47 #define control_byte_1 (0x88|fast_tuning|ref_div_byte)
48
49
50 struct db_tvrx_common {
51   // TVRX common stuff
52   u2_fxpt_freq_t first_if;
53   u2_fxpt_freq_t second_if;
54 };
55
56 struct db_tvrx_dummy {
57   struct db_base        base;
58   struct db_tvrx_common common;
59 };
60
61 struct db_tvrx1 {
62   struct db_base        base;
63   struct db_tvrx_common common;
64 };
65
66 struct db_tvrx2 {
67   struct db_base        base;
68   struct db_tvrx_common common;
69 };
70
71 struct db_tvrx3 {
72   struct db_base        base;
73   struct db_tvrx_common common;
74 };
75
76 /* The class instances */
77 struct db_tvrx1 db_tvrx1 = {
78   .base.dbid = 0x0003,
79   .base.is_tx = false,
80   .base.output_enables = 0x0000,
81   .base.used_pins = 0x0000,
82   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(50e6),
83   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(860e6),
84   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
85   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(95),
86   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(1),
87   .base.is_quadrature = false,
88   .base.i_and_q_swapped = false,
89   .base.spectrum_inverted = false,
90   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
91   .base.init = tvrx_init,
92   .base.set_freq = tvrx_set_freq,
93   .base.set_gain = tvrx_set_gain,
94   .base.set_tx_enable = 0,
95   .base.atr_mask = 0x0000,
96   .base.atr_txval = 0,
97   .base.atr_rxval = 0,
98   // .base.atr_tx_delay =
99   // .base.atr_rx_delay =
100   .base.set_antenna = 0,
101   .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(43.75e6),
102   .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(5.75e6),
103 };
104
105 #if 0
106 struct db_tvrx2 db_tvrx2 = {
107   .base.dbid = 0x000c,
108   .base.is_tx = false,
109   .base.output_enables = 0x0000,
110   .base.used_pins = 0x0000,
111   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(50e6),
112   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(860e6),
113   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
114   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(95),
115   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(1),
116   .base.is_quadrature = false,
117   .base.i_and_q_swapped = false,
118   .base.spectrum_inverted = false,
119   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
120   .base.init = tvrx_init,
121   .base.set_freq = tvrx_set_freq,
122   .base.set_gain = tvrx_set_gain,
123   .base.set_tx_enable = 0,
124   .base.atr_mask = 0x0000,
125   .base.atr_txval = 0,
126   .base.atr_rxval = 0,
127   // .base.atr_tx_delay =
128   // .base.atr_rx_delay =
129   .base.set_antenna = 0,
130   .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
131   .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(56e6),     // Fs - 44e6
132 };
133 #endif
134
135 struct db_tvrx3 db_tvrx3 = {
136   .base.dbid = 0x0040,
137   .base.is_tx = false,
138   .base.output_enables = 0x0000,
139   .base.used_pins = 0x0000,
140   .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(50e6),
141   .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(860e6),
142   .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
143   .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(95),
144   .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(1),
145   .base.is_quadrature = false,
146   .base.i_and_q_swapped = false,
147   .base.spectrum_inverted = false,
148   .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
149   .base.init = tvrx_init,
150   .base.set_freq = tvrx_set_freq,
151   .base.set_gain = tvrx_set_gain,
152   .base.set_tx_enable = 0,
153   .base.atr_mask = 0x0000,
154   .base.atr_txval = 0,
155   .base.atr_rxval = 0,
156   // .base.atr_tx_delay =
157   // .base.atr_rx_delay =
158   .base.set_antenna = 0,
159   .common.first_if = U2_DOUBLE_TO_FXPT_FREQ(44e6),
160   .common.second_if = U2_DOUBLE_TO_FXPT_FREQ(56e6),     // Fs - 44e6
161 };
162
163 bool
164 tvrx_init(struct db_base *dbb)
165 {
166   struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
167   db->base.set_gain(dbb,U2_DOUBLE_TO_FXPT_GAIN(94.0));
168   return true;
169 }
170
171 bool
172 tvrx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
173 {
174   *dc = 0;
175   if (freq < dbb->freq_min || freq > dbb->freq_max)
176     return false;
177
178   struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
179
180   u2_fxpt_freq_t target_lo_freq = freq + db->common.first_if;
181   int n_div = u2_fxpt_freq_round_to_int(((1LL<<20) * target_lo_freq)/REF_FREQ);
182   
183   u2_fxpt_freq_t actual_lo_freq = REF_FREQ * n_div;
184   u2_fxpt_freq_t actual_freq = actual_lo_freq - db->common.first_if;
185   if(n_div > 32767)
186     return false;
187
188   if (0)
189     printf("n_div = %d, actual_freq = %d, actual_lo_freq = %d\n",
190            n_div, u2_fxpt_freq_round_to_int(actual_freq),
191            u2_fxpt_freq_round_to_int(actual_lo_freq));
192
193   unsigned char buf[4];
194   buf[0] = (n_div>>8) & 0xff;
195   buf[1] = n_div & 0xff;
196   buf[2] = control_byte_1;
197   buf[3] = ((actual_freq < U2_DOUBLE_TO_FXPT_FREQ(158e6)) ? 0xa8 :  // VHF LOW
198             (actual_freq < U2_DOUBLE_TO_FXPT_FREQ(464e6)) ? 0x98 :  // VHF HIGH
199             0x38);  // UHF
200
201   *dc = actual_freq - db->common.second_if;
202   return i2c_write(I2C_ADDR,buf,4);
203 }
204
205 bool
206 tvrx_set_gain(struct db_base *dbb, u2_fxpt_gain_t gain)
207 {
208   //struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
209   int rfgain;
210   int ifgain;
211   if(gain>U2_DOUBLE_TO_FXPT_GAIN(95.0))
212     return false;
213   if(gain<0)
214     return false;
215
216   if(gain>U2_DOUBLE_TO_FXPT_GAIN(60.0)) {
217     rfgain = U2_DOUBLE_TO_FXPT_GAIN(60.0);
218     ifgain = gain-U2_DOUBLE_TO_FXPT_GAIN(60.0);
219   } else {
220     rfgain = gain;
221     ifgain = 0;
222   }
223   
224   int rf_slope_q8 = 256 * 4096 * 2.5 / 60.0 / 1.22 / 3.3;
225   int rf_offset_q8 = 128 * 256 * 4096 * 1.25 / 1.22 / 3.3;
226   int if_slope_q8 = 256 * 4096 * 2.25 / 35.0 / 1.22 / 3.3;
227   int if_offset_q8 = 128 * 256 * 4096 * 1.4 / 1.22 / 3.3;
228
229   
230   int rfdac = (rfgain*rf_slope_q8 + rf_offset_q8)>>15;
231   int ifdac = (ifgain*if_slope_q8 + if_offset_q8)>>15;
232   lsdac_write_rx(0,rfdac);
233   lsdac_write_rx(1,ifdac);
234
235   if (0)
236     printf("Setting gain %d, rf %d, if %d\n",gain,rfdac,ifdac);
237
238   return true;
239 }
240
241
242 bool
243 tvrx_lock_detect(struct db_base *dbb)
244 {
245   // struct db_tvrx_dummy *db = (struct db_tvrx_dummy *) dbb;
246   return true;
247 }