~ubuntu-branches/ubuntu/trusty/gnuradio/trusty

« back to all changes in this revision

Viewing changes to usrp2/firmware/lib/db_dbsrx.c

  • Committer: Bazaar Package Importer
  • Author(s): Kamal Mostafa
  • Date: 2010-03-13 07:46:01 UTC
  • mfrom: (2.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20100313074601-zjsa893a87bozyh7
Tags: 3.2.2.dfsg-1ubuntu1
* Fix build for Ubuntu lucid (LP: #260406)
  - add binary package dep for libusrp0, libusrp2-0: adduser
  - debian/rules clean: remove pre-built Qt moc files

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- c++ -*- */
 
2
/*
 
3
 * Copyright 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 <db_base.h>
 
21
#include <lsdac.h>
 
22
#include <memory_map.h>
 
23
#include <clocks.h>
 
24
#include <stdio.h>
 
25
#include <hal_io.h>
 
26
 
 
27
#define min(X,Y) ((X) < (Y) ? (X) : (Y))
 
28
#define max(X,Y) ((X) > (Y) ? (X) : (Y))
 
29
#define abs(X) ((X) < (0) ? ((-1)*(X)) : (X))
 
30
 
 
31
#define I2C_ADDR 0x67
 
32
#define REFCLK_DIVISOR 25   // Gives a 4 MHz clock
 
33
#define REFCLK_FREQ U2_DOUBLE_TO_FXPT_FREQ(MASTER_CLK_RATE/REFCLK_DIVISOR)
 
34
#define REFCLK_FREQ_INT u2_fxpt_freq_round_to_int(REFCLK_FREQ)
 
35
 
 
36
#define VMAXGAIN .75
 
37
#define VMINGAIN 2.6
 
38
#define RFGAINMAX 60
 
39
#define BBGAINMAX 24
 
40
#define DACFULLSCALE 3.3
 
41
 
 
42
bool db_dbsrx_init(struct db_base *db);
 
43
bool db_dbsrx_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
 
44
bool db_dbsrx_set_gain(struct db_base *db, u2_fxpt_gain_t gain);
 
45
 
 
46
struct db_dbsrx_common {
 
47
  int d_n;
 
48
  int d_div2;
 
49
  int d_osc;
 
50
  int d_cp;
 
51
  int d_r_reg;
 
52
  int d_fdac;
 
53
  int d_m;
 
54
  int d_dl;
 
55
  int d_ade;
 
56
  int d_adl;
 
57
  int d_gc2;
 
58
  int d_diag;
 
59
};
 
60
 
 
61
struct db_dbsrx_dummy {
 
62
  struct db_base base;
 
63
  struct db_dbsrx_common common;
 
64
};
 
65
 
 
66
struct db_dbsrx {
 
67
  struct db_base base;
 
68
  struct db_dbsrx_common common;
 
69
};
 
70
 
 
71
struct db_dbsrx db_dbsrx = {
 
72
  .base.dbid = 0x000d,
 
73
  .base.is_tx = false,
 
74
  .base.output_enables = 0x0000,
 
75
  .base.used_pins = 0x0000,
 
76
  .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(500e6),
 
77
  .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2.6e9),
 
78
  .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
 
79
  .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(RFGAINMAX+BBGAINMAX),
 
80
  .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(1),
 
81
  .base.is_quadrature = true,
 
82
  .base.i_and_q_swapped = false,
 
83
  .base.spectrum_inverted = false,
 
84
  .base.default_lo_offset = U2_DOUBLE_TO_FXPT_FREQ(0),
 
85
  .base.init = db_dbsrx_init,
 
86
  .base.set_freq = db_dbsrx_set_freq,
 
87
  .base.set_gain = db_dbsrx_set_gain,
 
88
  .base.set_tx_enable = 0,
 
89
  .base.atr_mask = 0x0000,
 
90
  .base.atr_txval = 0,
 
91
  .base.atr_rxval = 0,
 
92
  //.base.atr_tx_delay =
 
93
  //.base.atr_rx_delay =
 
94
  .common.d_n = 950,
 
95
  .common.d_div2 = 0,
 
96
  .common.d_osc = 5,
 
97
  .common.d_cp = 3,
 
98
  .common.d_r_reg = 1,
 
99
  .common.d_fdac = 127,
 
100
  .common.d_m = 2,
 
101
  .common.d_dl = 1,
 
102
  .common.d_ade = 0,
 
103
  .common.d_adl = 0,
 
104
  .common.d_gc2 = 31,
 
105
  .common.d_diag = 0,
 
106
};
 
107
 
 
108
bool
 
109
db_dbsrx_init(struct db_base *dbb){
 
110
  struct db_dbsrx_dummy *db = (struct db_dbsrx_dummy *) dbb;
 
111
  db->base.set_gain(dbb, (db->base.gain_max + db->base.gain_min)/2);
 
112
  clocks_enable_rx_dboard(true, REFCLK_DIVISOR);  // Gives 4 MHz clock
 
113
 
 
114
  return true;
 
115
}
 
116
 
 
117
/**************************************************
 
118
 * Registers
 
119
 **************************************************/
 
120
static int
 
121
_read_adc (void){
 
122
  unsigned char readback[2];
 
123
  i2c_read(I2C_ADDR, readback, 2*sizeof(unsigned char));
 
124
  int adc_val = (readback[0] >> 2)&7;
 
125
  //printf("READBACK[0] %d, [1] %d\n",readback[0],readback[1]);
 
126
  //printf("ADC: %d\n",adc_val);
 
127
  return adc_val;
 
128
}
 
129
 
 
130
static void
 
131
_write_reg (int regno, int v){
 
132
  //regno is in [0,5], v is value to write to register"""
 
133
  unsigned char args[2];
 
134
  args[0] = (unsigned char)regno;
 
135
  args[1] = (unsigned char)v;
 
136
  i2c_write(I2C_ADDR, args, 2*sizeof(unsigned char));
 
137
  //printf("Reg %d, Val %x\n",regno,v);
 
138
}
 
139
 
 
140
static void _send_reg_0(struct db_dbsrx_dummy *db){
 
141
  _write_reg(0,(db->common.d_div2<<7) + (db->common.d_n>>8));
 
142
}
 
143
 
 
144
static void _send_reg_1(struct db_dbsrx_dummy *db){
 
145
  _write_reg(1,db->common.d_n & 255);
 
146
}
 
147
 
 
148
static void _send_reg_2(struct db_dbsrx_dummy *db){
 
149
  _write_reg(2,db->common.d_osc + (db->common.d_cp<<3) + (db->common.d_r_reg<<5));
 
150
}
 
151
 
 
152
static void _send_reg_3(struct db_dbsrx_dummy *db){
 
153
  _write_reg(3,db->common.d_fdac);
 
154
}
 
155
 
 
156
static void _send_reg_4(struct db_dbsrx_dummy *db){
 
157
  _write_reg(4,db->common.d_m + (db->common.d_dl<<5) + (db->common.d_ade<<6) + (db->common.d_adl<<7));
 
158
}
 
159
 
 
160
static void _send_reg_5(struct db_dbsrx_dummy *db){
 
161
  _write_reg(5,db->common.d_gc2 + (db->common.d_diag<<5));
 
162
}
 
163
 
 
164
/**************************************************
 
165
 * Helpers for setting the freq
 
166
 **************************************************/
 
167
static void
 
168
_set_div2(struct db_dbsrx_dummy *db, int div2){
 
169
  db->common.d_div2 = div2;
 
170
  _send_reg_0(db);
 
171
}
 
172
 
 
173
// FIXME  How do we handle ADE and ADL properly?
 
174
static void
 
175
_set_ade(struct db_dbsrx_dummy *db, int ade){
 
176
  db->common.d_ade = ade;
 
177
  _send_reg_4(db);
 
178
}
 
179
 
 
180
static void
 
181
_set_r(struct db_dbsrx_dummy *db, int r){
 
182
  db->common.d_r_reg = r;
 
183
  _send_reg_2(db);
 
184
}
 
185
 
 
186
static void
 
187
_set_n(struct db_dbsrx_dummy *db, int n){
 
188
  db->common.d_n = n;
 
189
  _send_reg_0(db);
 
190
  _send_reg_1(db);
 
191
}
 
192
 
 
193
static void
 
194
_set_osc(struct db_dbsrx_dummy *db, int osc){
 
195
  db->common.d_osc = osc;
 
196
  _send_reg_2(db);
 
197
}
 
198
 
 
199
static void
 
200
_set_cp(struct db_dbsrx_dummy *db, int cp){
 
201
  db->common.d_cp = cp;
 
202
  _send_reg_2(db);
 
203
}
 
204
 
 
205
/**************************************************
 
206
 * Set the freq
 
207
 **************************************************/
 
208
 
 
209
 
 
210
bool
 
211
db_dbsrx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc){
 
212
  struct db_dbsrx_dummy *db = (struct db_dbsrx_dummy *) dbb;
 
213
 
 
214
  if(!(freq>=db->base.freq_min && freq<=db->base.freq_max)) {
 
215
    return false;
 
216
  }
 
217
 
 
218
  u2_fxpt_freq_t vcofreq;
 
219
  if(freq < U2_DOUBLE_TO_FXPT_FREQ(1150e6)) {
 
220
    _set_div2(db, 0);
 
221
    vcofreq = 4 * freq;
 
222
  }
 
223
  else {
 
224
    _set_div2(db, 1);
 
225
    vcofreq = 2 * freq;
 
226
  }
 
227
  
 
228
  _set_ade(db, 1);
 
229
  int rmin = max(2, u2_fxpt_freq_round_to_int(REFCLK_FREQ/2e6)); //TODO? remove max()
 
230
  //int rmax = min(128, u2_fxpt_freq_round_to_int(REFCLK_FREQ/500e3)); //TODO? remove min()
 
231
  int n = 0;
 
232
  u2_fxpt_freq_t best_delta = U2_DOUBLE_TO_FXPT_FREQ(10e6);
 
233
  u2_fxpt_freq_t delta;
 
234
 
 
235
  int r_reg = 0;
 
236
  while ((r_reg<7) && ((2<<r_reg) < rmin)) {
 
237
    r_reg++;
 
238
  }
 
239
  //printf ("r_reg = %d, r = %d\n",r_reg,2<<r_reg);
 
240
  int best_r = r_reg;
 
241
  int best_n = 0;
 
242
 
 
243
  while(r_reg <= 7) {
 
244
    n = u2_fxpt_freq_round_to_int(freq/REFCLK_FREQ_INT*(2<<r_reg));
 
245
    //printf("LOOP: r_reg %d, best_r %d, best_n %d, best_delta %d\n",
 
246
    //r_reg,best_r,best_n,u2_fxpt_freq_round_to_int(best_delta));
 
247
 
 
248
    //printf("N: %d\n",n);
 
249
    if(n<256) {
 
250
      r_reg++;
 
251
      continue;
 
252
    }
 
253
    delta = abs(n*REFCLK_FREQ/(2<<r_reg) - freq);
 
254
    if(delta < best_delta) {
 
255
      best_r = r_reg;
 
256
      best_n = n;
 
257
      best_delta = delta;
 
258
    }
 
259
    if(best_delta < U2_DOUBLE_TO_FXPT_FREQ(75e3)) {
 
260
      break;
 
261
    }
 
262
    r_reg++;
 
263
  }
 
264
 
 
265
  //printf("BEST R: %d  Best Delta %d  Best N %d\n",
 
266
  // best_r,u2_fxpt_freq_round_to_int(best_delta),best_n);
 
267
  _set_r(db, best_r);
 
268
  _set_n(db, best_n);
 
269
 
 
270
  int vco;
 
271
  if(vcofreq < U2_DOUBLE_TO_FXPT_FREQ(2433e6))
 
272
    vco = 0;
 
273
  else if(vcofreq < U2_DOUBLE_TO_FXPT_FREQ(2711e6))
 
274
    vco=1;
 
275
  else if(vcofreq < U2_DOUBLE_TO_FXPT_FREQ(3025e6))
 
276
    vco=2;
 
277
  else if(vcofreq < U2_DOUBLE_TO_FXPT_FREQ(3341e6))
 
278
    vco=3;
 
279
  else if(vcofreq < U2_DOUBLE_TO_FXPT_FREQ(3727e6))
 
280
    vco=4;
 
281
  else if(vcofreq < U2_DOUBLE_TO_FXPT_FREQ(4143e6))
 
282
    vco=5;
 
283
  else if(vcofreq < U2_DOUBLE_TO_FXPT_FREQ(4493e6))
 
284
    vco=6;
 
285
  else
 
286
    vco=7;
 
287
  //printf("Initial VCO choice %d\n",vco);  
 
288
  _set_osc(db, vco);
 
289
  
 
290
 
 
291
  int adc_val = 0;
 
292
  while(adc_val == 0 || adc_val == 7) {
 
293
    adc_val = _read_adc();
 
294
    //printf("adc %d\n",adc_val);
 
295
 
 
296
    if(adc_val == 0) {
 
297
      if(vco <= 0) {
 
298
        return false;
 
299
      }
 
300
      else {
 
301
        vco = vco - 1;
 
302
      }
 
303
    }
 
304
    else if(adc_val == 7) {
 
305
      if(vco >= 7) {
 
306
        return false;
 
307
      }
 
308
      else {
 
309
        vco = vco + 1;
 
310
      }
 
311
    }
 
312
    _set_osc(db, vco);
 
313
  }
 
314
  
 
315
  if(adc_val == 1 || adc_val == 2) {
 
316
    _set_cp(db, 1);
 
317
  }
 
318
  else if(adc_val == 3 || adc_val == 4) {
 
319
    _set_cp(db, 2);
 
320
  }
 
321
  else {
 
322
    _set_cp(db, 3);
 
323
  }
 
324
  //printf("Final VCO choice %d\n",vco);  
 
325
 
 
326
  *dc = db->common.d_n * REFCLK_FREQ / (2<<db->common.d_r_reg);
 
327
  return true;
 
328
 
 
329
}
 
330
 
 
331
/**************************************************
 
332
 * Helpers for setting the gain
 
333
 **************************************************/
 
334
 
 
335
static void
 
336
_set_gc2(struct db_dbsrx_dummy *db, int gc2){
 
337
  db->common.d_gc2 = gc2;
 
338
  _send_reg_5(db);
 
339
}
 
340
 
 
341
/**************************************************
 
342
 * Set the gain
 
343
 **************************************************/
 
344
bool
 
345
db_dbsrx_set_gain(struct db_base *dbb, u2_fxpt_gain_t gain){
 
346
  struct db_dbsrx_dummy *db = (struct db_dbsrx_dummy *) dbb;
 
347
  
 
348
  u2_fxpt_gain_t rfgain, bbgain;
 
349
 
 
350
  if(!(gain >= db->base.gain_min && gain <= db->base.gain_max)) {
 
351
    return false;
 
352
  }
 
353
  
 
354
  if(gain < U2_DOUBLE_TO_FXPT_GAIN(RFGAINMAX)) {
 
355
    rfgain = gain;
 
356
    bbgain = 0;
 
357
  }
 
358
  else {
 
359
    rfgain = U2_DOUBLE_TO_FXPT_GAIN(RFGAINMAX);
 
360
    bbgain = gain - U2_DOUBLE_TO_FXPT_GAIN(RFGAINMAX);
 
361
  }
 
362
 
 
363
  int rf_gain_slope_q8 = 256 * 4096 * (VMAXGAIN-VMINGAIN) / RFGAINMAX / DACFULLSCALE;
 
364
  int rf_gain_offset_q8 = 128 * 256 * 4096 * VMINGAIN / DACFULLSCALE;
 
365
  
 
366
  int rfdac = (rfgain*rf_gain_slope_q8 + rf_gain_offset_q8)>>15;
 
367
 
 
368
  //printf("Set RF Gain %d, %d\n",rfgain,rfdac);
 
369
  lsdac_write_rx(1,rfdac);
 
370
  
 
371
  // Set GC2
 
372
  int bb_gain_slope_q8 = 256*(0-31)/(BBGAINMAX-0);
 
373
 
 
374
  int gc2 = u2_fxpt_gain_round_to_int((bb_gain_slope_q8 * bbgain)>>8) + 31;
 
375
  //printf("Set BB Gain: %d, gc2 %d\n",bbgain,gc2);
 
376
 
 
377
  _set_gc2(db, gc2);
 
378
 
 
379
  return true;
 
380
}
 
381
 
 
382
/**************************************************
 
383
 * Helpers for setting the bw
 
384
 **************************************************/
 
385
static void
 
386
_set_m(struct db_dbsrx_dummy *db, int m){
 
387
  db->common.d_m = m;
 
388
  _send_reg_4(db);
 
389
}
 
390
  
 
391
static void
 
392
_set_fdac(struct db_dbsrx_dummy *db, int fdac){
 
393
  db->common.d_fdac = fdac;
 
394
  _send_reg_3(db);
 
395
}