2 * Copyright 2008 Free Software Foundation, Inc.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #include <memory_map.h>
29 bool rfx_init_rx(struct db_base *db);
30 bool rfx_init_tx(struct db_base *db);
31 bool rfx_set_freq(struct db_base *db, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc);
32 bool rfx_set_gain_rx(struct db_base *db, u2_fxpt_gain_t gain);
33 bool rfx_set_gain_tx(struct db_base *db, u2_fxpt_gain_t gain);
34 bool rfx_set_tx_enable(struct db_base *, bool on);
36 // Control Latch Defines
37 #define P 0 // Prescalar value for setting in regs, must match the next line...
38 #define PRESCALER 8 // Presacalar value for computations
39 #define PD 0 // Power down, 0 = normal operation
40 #define PL 0 // PLL power output
41 #define MTLD 1 // Mute till lock detect
42 #define CPGAIN 0 // Charge pump gain, use setting 1, also in N-reg
43 #define CP3S 0 // Charge pump tri-state, 0 = normal operation
44 #define PDP 1 // Phase detector polarity
45 #define MUXOUT 1 // Digital lock detect, active high
46 #define CR 0 // normal operation
47 #define PC 1 // core power
50 #define DIVSEL 0 // N Counter always operates on full rate
61 #define phdet_freq (U2_DOUBLE_TO_FXPT_FREQ(100e6/R_DIV))
64 #define POWER_UP (1 << 7) // Low enables power supply
65 #define ANT_SW (1 << 6) // On TX DB, 0 = TX, 1 = RX, on RX DB 0 = main ant, 1 = RX2
66 #define MIX_EN (1 << 5) // Enable appropriate mixer
67 #define LOCKDET_MASK (1 << 2) // Input pin
69 struct db_rfx_common {
76 u2_fxpt_freq_t freq_offset;
81 struct db_rfx_common common;
85 struct db_rfx_400_rx {
87 struct db_rfx_common common;
90 struct db_rfx_400_tx {
92 struct db_rfx_common common;
95 struct db_rfx_900_rx {
97 struct db_rfx_common common;
100 struct db_rfx_900_tx {
102 struct db_rfx_common common;
105 struct db_rfx_1200_rx {
107 struct db_rfx_common common;
110 struct db_rfx_1200_tx {
112 struct db_rfx_common common;
115 struct db_rfx_1800_rx {
117 struct db_rfx_common common;
120 struct db_rfx_1800_tx {
122 struct db_rfx_common common;
125 struct db_rfx_2400_rx {
127 struct db_rfx_common common;
130 struct db_rfx_2400_tx {
132 struct db_rfx_common common;
137 * The class instances
139 struct db_rfx_400_rx db_rfx_400_rx = {
142 .base.output_enables = 0x00E0,
143 .base.used_pins = 0x00FF,
144 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(400e6),
145 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(500e6),
146 .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
147 .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(45),
148 .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.022),
149 .base.is_quadrature = true,
150 .base.i_and_q_swapped = true,
151 .base.spectrum_inverted = false,
152 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
153 .base.init = rfx_init_rx,
154 .base.set_freq = rfx_set_freq,
155 .base.set_gain = rfx_set_gain_rx,
156 .base.set_tx_enable = 0,
157 .base.atr_mask = 0x00E0,
158 .base.atr_txval = POWER_UP,
159 .base.atr_rxval = POWER_UP|MIX_EN,
160 // .base.atr_tx_delay =
161 // .base.atr_rx_delay =
165 .common.spi_mask = SPI_SS_RX_DB,
166 .common.freq_mult = 2,
167 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(0)
171 struct db_rfx_400_tx db_rfx_400_tx = {
174 .base.output_enables = 0x00E0,
175 .base.used_pins = 0x00FF,
176 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(400e6),
177 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(500e6),
178 //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
179 //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
180 //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
181 .base.is_quadrature = true,
182 .base.i_and_q_swapped = true,
183 .base.spectrum_inverted = false,
184 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
185 .base.init = rfx_init_tx,
186 .base.set_freq = rfx_set_freq,
187 .base.set_gain = rfx_set_gain_tx,
188 .base.set_tx_enable = rfx_set_tx_enable,
189 .base.atr_mask = 0x00E0,
190 .base.atr_txval = POWER_UP|MIX_EN,
191 .base.atr_rxval = POWER_UP|ANT_SW,
192 // .base.atr_tx_delay =
193 // .base.atr_rx_delay =
197 .common.spi_mask = SPI_SS_TX_DB,
198 .common.freq_mult = 2,
199 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6)
202 struct db_rfx_900_rx db_rfx_900_rx = {
205 .base.output_enables = 0x00E0,
206 .base.used_pins = 0x00FF,
207 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(800e6),
208 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1000e6),
209 .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
210 .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
211 .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
212 .base.is_quadrature = true,
213 .base.i_and_q_swapped = true,
214 .base.spectrum_inverted = false,
215 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
216 .base.init = rfx_init_rx,
217 .base.set_freq = rfx_set_freq,
218 .base.set_gain = rfx_set_gain_rx,
219 .base.set_tx_enable = 0,
220 .base.atr_mask = 0x00E0,
222 .base.atr_rxval = MIX_EN,
223 // .base.atr_tx_delay =
224 // .base.atr_rx_delay =
228 .common.spi_mask = SPI_SS_RX_DB,
229 .common.freq_mult = 2,
230 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(0)
234 struct db_rfx_900_tx db_rfx_900_tx = {
237 .base.output_enables = 0x00E0,
238 .base.used_pins = 0x00FF,
239 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(800e6),
240 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1000e6),
241 //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
242 //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
243 //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
244 .base.is_quadrature = true,
245 .base.i_and_q_swapped = true,
246 .base.spectrum_inverted = false,
247 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
248 .base.init = rfx_init_tx,
249 .base.set_freq = rfx_set_freq,
250 .base.set_gain = rfx_set_gain_tx,
251 .base.set_tx_enable = rfx_set_tx_enable,
252 .base.atr_mask = 0x00E0,
253 .base.atr_txval = MIX_EN,
254 .base.atr_rxval = ANT_SW,
255 // .base.atr_tx_delay =
256 // .base.atr_rx_delay =
260 .common.spi_mask = SPI_SS_TX_DB,
261 .common.freq_mult = 2,
262 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6)
265 struct db_rfx_1200_rx db_rfx_1200_rx = {
268 .base.output_enables = 0x00E0,
269 .base.used_pins = 0x00FF,
270 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1150e6),
271 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1350e6),
272 .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
273 .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
274 .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
275 .base.is_quadrature = true,
276 .base.i_and_q_swapped = true,
277 .base.spectrum_inverted = false,
278 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
279 .base.init = rfx_init_rx,
280 .base.set_freq = rfx_set_freq,
281 .base.set_gain = rfx_set_gain_rx,
282 .base.set_tx_enable = 0,
283 .base.atr_mask = 0x00E0,
285 .base.atr_rxval = MIX_EN,
286 // .base.atr_tx_delay =
287 // .base.atr_rx_delay =
291 .common.spi_mask = SPI_SS_RX_DB,
292 .common.freq_mult = 2,
293 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(0)
297 struct db_rfx_1200_tx db_rfx_1200_tx = {
300 .base.output_enables = 0x00E0,
301 .base.used_pins = 0x00FF,
302 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1150e6),
303 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(1350e6),
304 //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
305 //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
306 //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
307 .base.is_quadrature = true,
308 .base.i_and_q_swapped = true,
309 .base.spectrum_inverted = false,
310 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
311 .base.init = rfx_init_tx,
312 .base.set_freq = rfx_set_freq,
313 .base.set_gain = rfx_set_gain_tx,
314 .base.set_tx_enable = rfx_set_tx_enable,
315 .base.atr_mask = 0x00E0,
316 .base.atr_txval = MIX_EN,
317 .base.atr_rxval = ANT_SW,
318 // .base.atr_tx_delay =
319 // .base.atr_rx_delay =
323 .common.spi_mask = SPI_SS_TX_DB,
324 .common.freq_mult = 2,
325 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6)
328 struct db_rfx_1800_rx db_rfx_1800_rx = {
331 .base.output_enables = 0x00E0,
332 .base.used_pins = 0x00FF,
333 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1600e6),
334 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2000e6),
335 .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
336 .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
337 .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
338 .base.is_quadrature = true,
339 .base.i_and_q_swapped = true,
340 .base.spectrum_inverted = false,
341 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
342 .base.init = rfx_init_rx,
343 .base.set_freq = rfx_set_freq,
344 .base.set_gain = rfx_set_gain_rx,
345 .base.set_tx_enable = 0,
346 .base.atr_mask = 0x00E0,
348 .base.atr_rxval = MIX_EN,
349 // .base.atr_tx_delay =
350 // .base.atr_rx_delay =
354 .common.spi_mask = SPI_SS_RX_DB,
355 .common.freq_mult = 1,
356 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(0)
360 struct db_rfx_1800_tx db_rfx_1800_tx = {
363 .base.output_enables = 0x00E0,
364 .base.used_pins = 0x00FF,
365 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(1600e6),
366 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2000e6),
367 //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
368 //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
369 //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
370 .base.is_quadrature = true,
371 .base.i_and_q_swapped = true,
372 .base.spectrum_inverted = false,
373 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
374 .base.init = rfx_init_tx,
375 .base.set_freq = rfx_set_freq,
376 .base.set_gain = rfx_set_gain_tx,
377 .base.set_tx_enable = rfx_set_tx_enable,
378 .base.atr_mask = 0x00E0,
379 .base.atr_txval = MIX_EN,
380 .base.atr_rxval = ANT_SW,
381 // .base.atr_tx_delay =
382 // .base.atr_rx_delay =
386 .common.spi_mask = SPI_SS_TX_DB,
387 .common.freq_mult = 1,
388 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6)
392 struct db_rfx_2400_rx db_rfx_2400_rx = {
395 .base.output_enables = 0x00E0,
396 .base.used_pins = 0x00FF,
397 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(2300e6),
398 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2700e6),
399 .base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(0),
400 .base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(70),
401 .base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(0.034),
402 .base.is_quadrature = true,
403 .base.i_and_q_swapped = true,
404 .base.spectrum_inverted = false,
405 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
406 .base.init = rfx_init_rx,
407 .base.set_freq = rfx_set_freq,
408 .base.set_gain = rfx_set_gain_rx,
409 .base.set_tx_enable = 0,
410 .base.atr_mask = 0x00E0,
412 .base.atr_rxval = MIX_EN,
413 // .base.atr_tx_delay =
414 // .base.atr_rx_delay =
418 .common.spi_mask = SPI_SS_RX_DB,
419 .common.freq_mult = 1,
420 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(0)
424 struct db_rfx_2400_tx db_rfx_2400_tx = {
427 .base.output_enables = 0x00E0,
428 .base.used_pins = 0x00FF,
429 .base.freq_min = U2_DOUBLE_TO_FXPT_FREQ(2300e6),
430 .base.freq_max = U2_DOUBLE_TO_FXPT_FREQ(2700e6),
431 //.base.gain_min = U2_DOUBLE_TO_FXPT_GAIN(xxx),
432 //.base.gain_max = U2_DOUBLE_TO_FXPT_GAIN(xxx),
433 //.base.gain_step_size = U2_DOUBLE_TO_FXPT_GAIN(xxx),
434 .base.is_quadrature = true,
435 .base.i_and_q_swapped = true,
436 .base.spectrum_inverted = false,
437 //.base.lo_offset = U2_DOUBLE_TO_FXPT_FREQ(4e6),
438 .base.init = rfx_init_tx,
439 .base.set_freq = rfx_set_freq,
440 .base.set_gain = rfx_set_gain_tx,
441 .base.set_tx_enable = rfx_set_tx_enable,
442 .base.atr_mask = 0x00E0,
443 .base.atr_txval = MIX_EN,
444 .base.atr_rxval = ANT_SW,
445 // .base.atr_tx_delay =
446 // .base.atr_rx_delay =
450 .common.spi_mask = SPI_SS_TX_DB,
451 .common.freq_mult = 1,
452 .common.freq_offset = U2_DOUBLE_TO_FXPT_FREQ(12.5e6)
457 rfx_init_tx(struct db_base *dbb)
459 //struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
460 clocks_enable_tx_dboard(true, 0);
462 // Set the freq now to get the one time 10ms delay out of the way.
464 dbb->set_freq(dbb, dbb->freq_min, &dc);
469 rfx_init_rx(struct db_base *dbb)
471 //struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
472 clocks_enable_rx_dboard(true, 0);
475 dbb->set_gain(dbb,U2_DOUBLE_TO_FXPT_GAIN(45.0));
477 // Set the freq now to get the one time 10ms delay out of the way.
479 dbb->set_freq(dbb, dbb->freq_min, &dc);
485 rfx_set_freq(struct db_base *dbb, u2_fxpt_freq_t freq, u2_fxpt_freq_t *dc)
487 static unsigned char first = true;
490 struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
491 u2_fxpt_freq_t desired_n = (U2_DOUBLE_TO_FXPT_FREQ(1.0)*db->common.freq_mult*(freq+db->common.freq_offset))/phdet_freq;
492 int N_DIV = u2_fxpt_freq_round_to_int(desired_n);
493 int B = N_DIV/PRESCALER;
494 int A = N_DIV - PRESCALER*B;
499 int R = (R_RSV<<22)|(R_BSC<<20)|(R_TMB<<19)|(R_LDP<<18)|(R_ABP<<16)|(R_DIV<<2)|1;
500 int N = (DIVSEL<<23)|(db->common.DIV2<<22)|(CPGAIN<<21)|(B<<8)|(N_RSV<<7)|(A<<2)|2;
501 int C = (P<<22)|(PD<<20)|(db->common.CP2<<17)|(db->common.CP1<<14)|(PL<<12)|
502 (MTLD<<11)|(CPGAIN<<10)|(CP3S<<9)|(PDP<<8)|(MUXOUT<<5)|(CR<<4)|(PC<<2)|0;
504 spi_transact(SPI_TXONLY,db->common.spi_mask,R,24,SPIF_PUSH_FALL);
505 spi_transact(SPI_TXONLY,db->common.spi_mask,C,24,SPIF_PUSH_FALL);
510 spi_transact(SPI_TXONLY,db->common.spi_mask,N,24,SPIF_PUSH_FALL);
512 //printf("A = %d, B = %d, N_DIV = %d\n",A, B, N_DIV);
513 *dc = (N_DIV * phdet_freq) / db->common.freq_mult;
518 rfx_set_gain_tx(struct db_base *dbb, u2_fxpt_gain_t gain)
520 // There is no analog gain control on TX
525 rfx_set_gain_rx(struct db_base *dbb, u2_fxpt_gain_t gain)
527 struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
529 int offset_q8 = (int)(1.2/3.3*4096*(1<<15));
530 int range_q15 = (int)(-1.0*4096/3.3*256*128);
531 int slope_q8 = range_q15/db->base.gain_max;
533 int dacword = ((slope_q8 * gain) + offset_q8)>>15;
534 //printf("DACWORD %d\n",dacword);
535 lsdac_write_rx(1,dacword);
541 rfx_set_tx_enable(struct db_base *dbb, bool on)
543 struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
551 rfx_lock_detect(struct db_base *dbb)
553 struct db_rfx_dummy *db = (struct db_rfx_dummy *) dbb;
555 pins = hal_gpio_read( db->base.is_tx ? GPIO_TX_BANK : GPIO_RX_BANK );
556 if(pins & LOCKDET_MASK)
562 def select_rx_antenna(self, which_antenna):
564 Specify which antenna port to use for reception.
565 @param which_antenna: either 'TX/RX' or 'RX2'
567 if which_antenna in (0, 'TX/RX'):
568 self._u.write_io(self._which, 0, RX2_RX1N)
569 elif which_antenna in (1, 'RX2'):
570 self._u.write_io(self._which, RX2_RX1N, RX2_RX1N)
572 raise ValueError, "which_antenna must be either 'TX/RX' or 'RX2'"
574 def set_gain(self, gain):
578 @param gain: gain in decibels
581 maxgain = self.gain_range()[1] - self._u.pga_max()
582 mingain = self.gain_range()[0]
584 pga_gain = gain-maxgain
585 assert pga_gain <= self._u.pga_max()
593 dac_value = (agc_gain*(V_maxgain-V_mingain)/(maxgain-mingain) + V_mingain)*4096/V_fullscale
594 assert dac_value>=0 and dac_value<4096
595 return self._u.write_aux_dac(self._which, 0, int(dac_value)) and \
596 self._set_pga(int(pga_gain))
598 def gain_range(self):
599 return (self._u.pga_min(), self._u.pga_max() + 70, 0.05) -- For 900-2400
600 return (self._u.pga_min(), self._u.pga_max() + 45, 0.035) -- For 400