Once and for all, here is the properly updated Makefile.am for the apps
[debian/gnuradio] / usrp2 / firmware / lib / adf4350.c
1 /*
2  * Copyright 2010 Free Software Foundation, Inc.
3  *
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.
8  *
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.
13  *
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/>.
16  *
17  */
18
19 #include "adf4350.h"
20 #include "adf4350_regs.h"
21 #include "db_wbxng.h"
22 #include <spi.h>
23 #include <hal_io.h>
24 #include <stdio.h>
25 #include <stdint.h>
26
27 #define INPUT_REF_FREQ U2_DOUBLE_TO_FXPT_FREQ(50e6)
28 #define INPUT_REF_FREQ_2X (2*INPUT_REF_FREQ)                            /* input ref freq with doubler turned on */
29 #define MAX_RF_DIV UINT8_C(16)                                          /* max rf divider, divides rf output */
30 #define MIN_VCO_FREQ U2_DOUBLE_TO_FXPT_FREQ(2.2e9)                      /* minimum vco freq */
31 #define MAX_VCO_FREQ U2_DOUBLE_TO_FXPT_FREQ(4.4e9)                      /* minimum vco freq */
32 #define MAX_FREQ MAX_VCO_FREQ                                           /* upper bound freq (rf div = 1) */
33 #define MIN_FREQ DIV_ROUND(MIN_VCO_FREQ, MAX_RF_DIV)                    /* calculated lower bound freq */
34
35 u2_fxpt_freq_t adf4350_get_max_freq(void){
36         return MAX_FREQ;
37 }
38
39 u2_fxpt_freq_t adf4350_get_min_freq(void){
40         return MIN_FREQ;
41 }
42
43 void adf4350_init(struct db_base *dbb){
44         struct db_wbxng_dummy *db = (struct db_wbxng_dummy *) dbb;
45
46         /* Initialize the pin levels. */
47         hal_gpio_write( db->base.is_tx ? GPIO_TX_BANK : GPIO_RX_BANK, PLL_CE, PLL_CE );
48         adf4350_enable(true, dbb);
49         /* Initialize the registers. */
50         adf4350_load_register(5, dbb);
51         adf4350_load_register(4, dbb);
52         adf4350_load_register(3, dbb);
53         adf4350_load_register(2, dbb);
54         adf4350_load_register(1, dbb);
55         adf4350_load_register(0, dbb);
56 }
57
58 /*
59 void adf4350_update(void){
60         // mirror the lock detect pin to the led debug
61         if (adf4350_get_locked()){
62                 io_set_pin(led_pin);
63         }else{
64                 io_clear_pin(led_pin);
65         }
66 }
67 */
68
69 bool adf4350_get_locked(struct db_base *dbb){
70         struct db_wbxng_dummy *db = (struct db_wbxng_dummy *) dbb;
71
72         int pins;
73         pins = hal_gpio_read( db->base.is_tx ? GPIO_TX_BANK : GPIO_RX_BANK );
74         if(pins & PLL_LOCK_DETECT)
75                 return true;
76         return false;
77 }
78
79 void adf4350_enable(bool enable, struct db_base *dbb){
80         struct db_wbxng_dummy *db = (struct db_wbxng_dummy *) dbb;
81
82         if (enable){ /* chip enable */
83                 hal_gpio_write( db->base.is_tx ? GPIO_TX_BANK : GPIO_RX_BANK, PLL_PDBRF, PLL_PDBRF );
84         }else{
85                 hal_gpio_write( db->base.is_tx ? GPIO_TX_BANK : GPIO_RX_BANK, 0, PLL_PDBRF );
86         }
87 }
88
89 void adf4350_write(uint8_t addr, uint32_t data, struct db_base *dbb){
90         struct db_wbxng_dummy *db = (struct db_wbxng_dummy *) dbb;
91
92         //printf("SPI write ADDR 0x%x, WORD 0x%x\n", (int) (addr), (int) (data));
93         data |= addr;
94         spi_transact(SPI_TXONLY,db->common.spi_mask,data,32,SPIF_PUSH_FALL);
95         //spi_read_write(clk_pin, data_pin, ld_pin, &data, 32);
96         /* pulse latch */
97         //io_set_pin(le_pin);
98         //io_clear_pin(le_pin);
99 }
100
101 bool adf4350_set_freq(u2_fxpt_freq_t freq, struct db_base *dbb){
102         struct db_wbxng_dummy *db = (struct db_wbxng_dummy *) dbb;
103
104         /* Set the frequency by setting int, frac, mod, r, div */
105         if (freq > MAX_FREQ || freq < MIN_FREQ) return false;
106
107         /* Set the prescaler and the min N based on the freq. */
108         uint16_t min_int_div;
109         if (freq > U2_DOUBLE_TO_FXPT_FREQ(3e9) ){
110                 db->common.adf4350_regs_prescaler = (uint8_t) 1;
111                 min_int_div = UINT16_C(75);
112         }else{
113                 db->common.adf4350_regs_prescaler = (uint8_t) 0;
114                 min_int_div = UINT16_C(23);
115         }
116
117         /* Ramp up the RF divider until the VCO is within range. */
118         db->common.adf4350_regs_divider_select = (uint8_t) 0;
119         while (freq < MIN_VCO_FREQ){
120                 freq <<= 1; //double the freq
121                 db->common.adf4350_regs_divider_select++; //double the divider
122         }
123
124         /* Ramp up the R divider until the N divider is at least the minimum. */
125         db->common.adf4350_regs_10_bit_r_counter = (uint16_t) (DIV_ROUND((INPUT_REF_FREQ*min_int_div), freq));
126         //printf("Initial R setting: %u, MIN_INT: %u\n", db->common.adf4350_regs_10_bit_r_counter, min_int_div);
127         if (db->common.adf4350_regs_10_bit_r_counter * U2_DOUBLE_TO_FXPT_FREQ(32e6) < INPUT_REF_FREQ){
128                 db->common.adf4350_regs_10_bit_r_counter = (uint16_t) (DIV_ROUND(INPUT_REF_FREQ, U2_DOUBLE_TO_FXPT_FREQ(32e6)));
129                 //printf("Updating R setting: %u, MIN_INT: %u\n", db->common.adf4350_regs_10_bit_r_counter, min_int_div);
130         }
131
132         db->common.adf4350_regs_10_bit_r_counter--;
133         //db->common.adf4350_regs_10_bit_r_counter=1;
134
135         do{
136                 db->common.adf4350_regs_10_bit_r_counter++;
137                 /* throw out some fractional bits in freq to avoid overflow */
138                 u2_fxpt_freq_t some_frac_freq = (U2_DOUBLE_TO_FXPT_FREQ(1.0)/db->common.adf4350_regs_mod);
139                 uint64_t n_mod = DIV_ROUND(freq, some_frac_freq);
140                 n_mod *= db->common.adf4350_regs_10_bit_r_counter;
141                 n_mod *= db->common.adf4350_regs_mod;
142                 n_mod = DIV_ROUND(n_mod, DIV_ROUND(INPUT_REF_FREQ, some_frac_freq));
143                 /* calculate int and frac: regs_mod is a power of 2, this will optimize to a bitwise operation */
144                 db->common.adf4350_regs_int = (uint16_t) (n_mod/db->common.adf4350_regs_mod);
145                 db->common.adf4350_regs_frac = (uint16_t) (n_mod%db->common.adf4350_regs_mod);
146                 //printf("Int %u < Min %u\n", db->common.adf4350_regs_int, min_int_div);
147         }while(db->common.adf4350_regs_int < min_int_div);
148
149         /* calculate the band select so PFD is under 125 KHz */
150         db->common.adf4350_regs_8_bit_band_select_clock_divider_value = \
151                 (uint8_t) (INPUT_REF_FREQ/(U2_DOUBLE_TO_FXPT_FREQ(30e3)*db->common.adf4350_regs_10_bit_r_counter)) + 1;
152
153         /*
154         printf(
155                 "VCO %u KHz, Int %u, Frac %u, Mod %u, R %u, Div %u, BandSelect %u\n",
156                 (uint32_t) ((freq >> U2_FPF_RP)/1000),
157                 (uint32_t) db->common.adf4350_regs_int,
158                 (uint32_t) db->common.adf4350_regs_frac,
159                 (uint32_t) db->common.adf4350_regs_mod,
160                 (uint32_t) db->common.adf4350_regs_10_bit_r_counter,
161                 (uint32_t) (1 << db->common.adf4350_regs_divider_select),
162                 (uint32_t) db->common.adf4350_regs_8_bit_band_select_clock_divider_value
163         );
164         */
165
166         /* load involved registers */
167         adf4350_load_register(5, dbb);
168         adf4350_load_register(3, dbb);
169         adf4350_load_register(1, dbb);
170         adf4350_load_register(2, dbb);
171         adf4350_load_register(4, dbb);
172         adf4350_load_register(0, dbb); /* register 0 must be last */
173         return true;
174 }
175
176 u2_fxpt_freq_t adf4350_get_freq(struct db_base *dbb){
177         struct db_wbxng_dummy *db = (struct db_wbxng_dummy *) dbb;
178
179         /* Calculate the freq from int, frac, mod, ref, r, div:
180          *  freq = (int + frac/mod) * (ref/r)
181          * Keep precision by doing multiplies first:
182          *  freq = (((((((int)*mod) + frac)*ref)/mod)/r)/div)
183          */
184         uint64_t temp;
185         temp = (uint64_t) db->common.adf4350_regs_int;
186         temp *= (uint64_t) db->common.adf4350_regs_mod;
187         temp += (uint64_t) db->common.adf4350_regs_frac;
188         temp *= (uint64_t) (INPUT_REF_FREQ >> U2_FPF_RP);
189         temp /= (uint64_t) db->common.adf4350_regs_mod;
190         temp /= (uint64_t) db->common.adf4350_regs_10_bit_r_counter;
191         temp /= (uint64_t) (1 << db->common.adf4350_regs_divider_select);
192
193         /* Shift 1Hz Radix Point for u2_fxpt_freq_t */
194         temp = temp << U2_FPF_RP;
195
196         /*
197         printf(
198                 "Got Freq %u KHz, Int %u, Frac %u, Mod %u, R %u, Div %u\n",
199                 (uint32_t) ((temp >> U2_FPF_RP)/1000),
200                 (uint32_t) db->common.adf4350_regs_int,
201                 (uint32_t) db->common.adf4350_regs_frac,
202                 (uint32_t) db->common.adf4350_regs_mod,
203                 (uint32_t) db->common.adf4350_regs_10_bit_r_counter,
204                 (uint32_t) (1 << db->common.adf4350_regs_divider_select)
205         );
206         */
207
208         return (u2_fxpt_freq_t) (temp);
209 }