1 #include "max2871.h"
2 #include "max2871_regs.h"
3 
4 #if (defined DEBUG)
5 #include <stdio.h>
6 #define LOG printf
7 #else
8 #define LOG(x,...)
9 #include <libopencm3/lpc43xx/ssp.h>
10 #include <libopencm3/lpc43xx/scu.h>
11 #include "hackrf_core.h"
12 #endif
13 
14 #include <stdint.h>
15 #include <string.h>
16 
17 static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v);
18 static void max2871_write_registers(max2871_driver_t* const drv);
19 static void delay_ms(int ms);
20 
max2871_setup(max2871_driver_t * const drv)21 void max2871_setup(max2871_driver_t* const drv)
22 {
23 	/* Configure GPIO pins. */
24 	scu_pinmux(SCU_VCO_CE, SCU_GPIO_FAST);
25 	scu_pinmux(SCU_VCO_SCLK, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
26 	/* Only used for the debug pin config: scu_pinmux(SCU_VCO_SCLK, SCU_GPIO_FAST); */
27 	scu_pinmux(SCU_VCO_SDATA, SCU_GPIO_FAST);
28 	scu_pinmux(SCU_VCO_LE, SCU_GPIO_FAST);
29 	scu_pinmux(SCU_VCO_MUX, SCU_GPIO_FAST | SCU_CONF_FUNCTION4);
30 	scu_pinmux(SCU_SYNT_RFOUT_EN, SCU_GPIO_FAST);
31 
32 	/* Set GPIO pins as outputs. */
33 	gpio_output(drv->gpio_vco_ce);
34 	gpio_output(drv->gpio_vco_sclk);
35 	gpio_output(drv->gpio_vco_sdata);
36 	gpio_output(drv->gpio_vco_le);
37 	gpio_output(drv->gpio_synt_rfout_en);
38 
39 	/* MUX is an input */
40 	gpio_input(drv->gpio_vco_mux);
41 
42 	/* set to known state */
43 	gpio_set(drv->gpio_vco_ce); /* active high */
44 	gpio_clear(drv->gpio_vco_sclk);
45 	gpio_clear(drv->gpio_vco_sdata);
46 	gpio_set(drv->gpio_vco_le); /* active low */
47 	gpio_set(drv->gpio_synt_rfout_en); /* active high */
48 
49 	max2871_regs_init();
50 	int i;
51 	for(i = 5; i >= 0; i--) {
52 		max2871_spi_write(drv, i, max2871_get_register(i));
53 		delay_ms(20);
54 	}
55 
56 	max2871_set_INT(1);
57 	max2871_set_N(4500);
58 	max2871_set_FRAC(0);
59 	max2871_set_CPL(0);
60 	max2871_set_CPT(0);
61 	max2871_set_P(1);
62 	max2871_set_M(0);
63 	max2871_set_LDS(0);
64 	max2871_set_SDN(0);
65 	max2871_set_MUX(0x0C);  /* Register 6 readback */
66 	max2871_set_DBR(0);
67 	max2871_set_RDIV2(0);
68 	max2871_set_R(1); /* 40 MHz f_PFD */
69 	max2871_set_REG4DB(1);
70 	max2871_set_CP(15); /* ?: CP charge pump current 0-15 */
71 	max2871_set_LDF(1); /* INT-N */
72 	max2871_set_LDP(0); /* ?: Lock-Detect Precision */
73 	max2871_set_PDP(1);
74 	max2871_set_SHDN(0);
75 	max2871_set_TRI(0);
76 	max2871_set_RST(0);
77 	max2871_set_VCO(0);
78 	max2871_set_VAS_SHDN(0);
79 	max2871_set_VAS_TEMP(1);
80 	max2871_set_CSM(0);
81 	max2871_set_MUTEDEL(1);
82 	max2871_set_CDM(0);
83 	max2871_set_CDIV(0);
84 	max2871_set_SDLDO(0);
85 	max2871_set_SDDIV(0);
86 	max2871_set_SDREF(0);
87 	max2871_set_BS(20*40); /* For 40 MHz f_PFD */
88 	max2871_set_FB(1); /* Do not put DIVA into the feedback loop */
89 	max2871_set_DIVA(0);
90 	max2871_set_SDVCO(0);
91 	max2871_set_MTLD(1);
92 	max2871_set_BDIV(0);
93 	max2871_set_RFB_EN(0);
94 	max2871_set_BPWR(0);
95 	max2871_set_RFA_EN(0);
96 	max2871_set_APWR(3);
97 	max2871_set_SDPLL(0);
98 	max2871_set_F01(1);
99 	max2871_set_LD(1);
100 	max2871_set_ADCS(0);
101 	max2871_set_ADCM(0);
102 
103 	max2871_write_registers(drv);
104 
105 	max2871_set_frequency(drv, 3500);
106 }
107 
delay_ms(int ms)108 static void delay_ms(int ms)
109 {
110 	uint32_t i;
111 	while(ms--) {
112 		for (i = 0; i < 20000; i++) {
113 			__asm__("nop");
114 		}
115 	}
116 }
117 
118 
serial_delay(void)119 static void serial_delay(void)
120 {
121 	uint32_t i;
122 
123 	for (i = 0; i < 2; i++)
124 		__asm__("nop");
125 }
126 
127 
128 /* SPI register write
129  *
130  * Send 32 bits:
131  *  First 29 bits are data
132  *  Last 3 bits are register number */
max2871_spi_write(max2871_driver_t * const drv,uint8_t r,uint32_t v)133 static void max2871_spi_write(max2871_driver_t* const drv, uint8_t r, uint32_t v) {
134 #if DEBUG
135 	LOG("0x%04x -> reg%d\n", v, r);
136 #else
137 
138 	uint32_t bits = 32;
139 	uint32_t msb = 1 << (bits -1);
140 	uint32_t data = v | r;
141 
142 	/* make sure everything is starting in the correct state */
143 	gpio_set(drv->gpio_vco_le);
144 	gpio_clear(drv->gpio_vco_sclk);
145 	gpio_clear(drv->gpio_vco_sdata);
146 
147 	/* start transaction by bringing LE low */
148 	gpio_clear(drv->gpio_vco_le);
149 
150 	while (bits--) {
151 		if (data & msb)
152 			gpio_set(drv->gpio_vco_sdata);
153 		else
154 			gpio_clear(drv->gpio_vco_sdata);
155 		data <<= 1;
156 
157 		serial_delay();
158 		gpio_set(drv->gpio_vco_sclk);
159 
160 		serial_delay();
161 		gpio_clear(drv->gpio_vco_sclk);
162 	}
163 
164 	gpio_set(drv->gpio_vco_le);
165 #endif
166 }
167 
max2871_spi_read(max2871_driver_t * const drv)168 static uint32_t max2871_spi_read(max2871_driver_t* const drv)
169 {
170 	uint32_t bits = 32;
171 	uint32_t data = 0;
172 
173 	max2871_spi_write(drv, 0x06, 0x0);
174 
175 	serial_delay();
176 	gpio_set(drv->gpio_vco_sclk);
177 	serial_delay();
178 	gpio_clear(drv->gpio_vco_sclk);
179 	serial_delay();
180 
181 	while (bits--) {
182 		gpio_set(drv->gpio_vco_sclk);
183 		serial_delay();
184 
185 		gpio_clear(drv->gpio_vco_sclk);
186 		serial_delay();
187 
188 		data <<= 1;
189 		data |= gpio_read(drv->gpio_vco_mux) ? 1 : 0;
190 	}
191 	return data;
192 }
193 
max2871_write_registers(max2871_driver_t * const drv)194 static void max2871_write_registers(max2871_driver_t* const drv)
195 {
196 	int i;
197 	for(i = 5; i >= 0; i--) {
198 		max2871_spi_write(drv, i, max2871_get_register(i));
199 	}
200 }
201 
202 /* Set frequency (MHz). */
max2871_set_frequency(max2871_driver_t * const drv,uint16_t mhz)203 uint64_t max2871_set_frequency(max2871_driver_t* const drv, uint16_t mhz)
204 {
205 	int n = mhz / 40;
206 	int diva = 0;
207 
208 	while(n * 40 < 3000) {
209 		n *= 2;
210 		diva += 1;
211 	}
212 
213 	max2871_set_RFA_EN(0);
214 	max2871_write_registers(drv);
215 
216 	max2871_set_N(n);
217 	max2871_set_DIVA(diva);
218 	max2871_write_registers(drv);
219 
220 	while(max2871_spi_read(drv) & MAX2871_VASA);
221 
222 	max2871_set_RFA_EN(1);
223 	max2871_write_registers(drv);
224 
225 	return (mhz/40)*40 * 1000000;
226 }
227 
max2871_enable(max2871_driver_t * const drv)228 void max2871_enable(max2871_driver_t* const drv)
229 {
230 	gpio_set(drv->gpio_vco_ce);
231 }
max2871_disable(max2871_driver_t * const drv)232 void max2871_disable(max2871_driver_t* const drv)
233 {
234 	gpio_clear(drv->gpio_vco_ce);
235 }
236 
237