source: PlatformSupport/CustomPeripherals/pcores/radio_controller_axi_v3_01_a/src/radio_controller.c

Last change on this file was 6211, checked in by murphpo, 6 years ago

Fixed mapping of RF vs AD chip select masks in Tx DCO code

File size: 33.9 KB
Line 
1/*****************************************************************
2* File: w3_ad_controller.c
3* Copyright (c) 2016 Mango Communications, all rights reseved
4* Released under the WARP License
5* See https://warpproject.org/license for details
6*****************************************************************/
7
8/** \file radio_controller.c
9
10\mainpage
11This is the driver for the radio_controller core, which implements an SPI master for controlling
12the AD9963 analog converters for the WARP v3 RF interfaces.
13
14@version 3.01.a
15@author Patrick Murphy
16@copyright (c) 2016 Mango Communications, Inc. All rights reserved.<br>
17Released under the WARP open source license (see http://warpproject.org/license)
18
19\brief Main source for radio_controller driver
20
21*/
22
23
24#include "radio_controller.h"
25#include "xparameters.h"
26
27#if defined XPAR_W3_IIC_EEPROM_NUM_INSTANCES && defined XPAR_W3_AD_CONTROLLER_NUM_INSTANCES
28#include "w3_ad_controller.h"
29#include "w3_iic_eeprom.h"
30#endif
31
32// Arrays below generated with max2829_pll_tune_val_gen.py in radio_controller src folder
33static u16 rc_tuningParams_24GHz_freqs[14] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484 };
34static u16 rc_tuningParams_24GHz_reg3[14] = { 0xa0, 0x20a1, 0x30a1, 0xa1, 0x20a2, 0x30a2, 0xa2, 0x20a3, 0x30a3, 0xa3, 0x20a4, 0x30a4, 0xa4, 0x10a5 };
35static u16 rc_tuningParams_24GHz_reg4[14] = { 0x3333, 0x888, 0x1ddd, 0x3333, 0x888, 0x1ddd, 0x3333, 0x888, 0x1ddd, 0x3333, 0x888, 0x1ddd, 0x3333, 0x2666 };
36
37static u16 rc_tuningParams_5GHz_freqs[44] = { 5180, 5190, 5200, 5220, 5230, 5240, 5260, 5270, 5280, 5300, 5310, 5320, 5500, 5510, 5520, 5540, 5550, 5560, 5580, 5590, 5600, 5620, 5630, 5640, 5660, 5670, 5680, 5700, 5710, 5720, 5745, 5755, 5765, 5785, 5795, 5805, 5825, 5860, 5870, 5875, 5880, 5885, 5890, 5865 };
38static u16 rc_tuningParams_5GHz_reg3[44] = { 0x30cf, 0x10cf, 0xd0, 0xd0, 0x30d1, 0x10d1, 0x20d2, 0xd2, 0x30d3, 0xd4, 0x20d4, 0xd4, 0xdc, 0x20dc, 0xdc, 0x10dd, 0xde, 0x20de, 0x30df, 0x10df, 0xe0, 0xe0, 0x30e1, 0x10e1, 0x20e2, 0xe2, 0x30e3, 0xe4, 0x20e4, 0xe4, 0xe5, 0x30e6, 0x10e6, 0x20e7, 0xe7, 0x30e8, 0xe9, 0x20ea, 0xea, 0xeb, 0x30eb, 0x20eb, 0x10eb, 0x10ea };
39static u16 rc_tuningParams_5GHz_reg4[44] = { 0xccc, 0x2666, 0x0, 0x3333, 0xccc, 0x2666, 0x1999, 0x3333, 0xccc, 0x0, 0x1999, 0x3333, 0x0, 0x1999, 0x3333, 0x2666, 0x0, 0x1999, 0xccc, 0x2666, 0x0, 0x3333, 0xccc, 0x2666, 0x1999, 0x3333, 0xccc, 0x0, 0x1999, 0x3333, 0x3333, 0xccc, 0x2666, 0x1999, 0x3333, 0xccc, 0x0, 0x1999, 0x3333, 0x0, 0xccc, 0x1999, 0x2666, 0x2666 };
40/**
41\defgroup user_functions Functions
42\brief Functions to call from user code
43\addtogroup user_functions
44
45Example:
46\code{.c}
47//Assumes user code sets RC_BASEADDR to base address of radio_controller core, as set in xparameters.h
48
49//Initialize the radio controller logic
50radio_controller_init(RC_CONTROLLER, 1, 1);
51
52\endcode
53
54@{
55*/
56
57/**
58\brief Initializes the radio controller core and the selected MAX2829 transceivers. The selected transceivers
59are reset, configured with sane defaults and set to the Standby state. User code should call this function once
60at boot for all RF interfaces.
61\param ba Base memory address of radio_controller pcore
62\param rfSel Selects RF interface to initialize (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
63\param clkDiv_SPI Clock divider for SPI serial clock (set to 3 for 160MHz bus)
64\param clkDiv_TxDelays Clock divider for Tx sequencing state machine (set to 1 for normal operation)
65\return Returns -1 if any MAX2829 indicates no PLL lock after init; otherwise returns 0
66*/
67int radio_controller_init(u32 ba, u32 rfSel, u8 clkDiv_SPI, u8 clkDiv_TxDelays) {
68
69    //Sanity check arguments
70    if(((rfSel & RC_ANY_RF)==0) || (clkDiv_SPI>7) || (clkDiv_TxDelays>3))
71        return RC_INVALID_PARAM;
72
73    //Radio controller init procedure:
74    // -Set clock dividers for MAX2829 SPI and TxTiming state machines
75    // -Set MAX2829 state to RESET
76    // -Set MAX2829 state to SHDN
77    // -Configure MAX2829 to sane defaults (see comments above each radio_controller_SPI_setRegBits call below)
78
79   
80    /************ FIXME: reg2 in user_logic.v init value is bogus *************/
81    Xil_Out32(ba+RC_SLV_REG2_OFFSET, 0);
82   
83    u32 rfCtrlMask = 0;
84    u32 pll_lock_status;
85    u32 pll_lock_wait_tries = 0;
86   
87    radio_controller_setClkDiv_SPI(ba, clkDiv_SPI);
88    radio_controller_setClkDiv_TxDelays(ba, clkDiv_TxDelays);
89
90    //Convert the user-supplied masks to the masks for the control registers
91    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
92    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
93    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
94    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
95
96    radio_controller_setMode_shutdown(ba, rfCtrlMask);
97    radio_controller_setMode_reset(ba, rfCtrlMask);
98    rc_usleep(1000);
99    radio_controller_setMode_shutdown(ba, rfCtrlMask);
100    rc_usleep(1000);
101   
102    //MAX2829 reg2:
103    // -MIMO mode (reg2[13]=1)
104    // -Other bits set to defaults
105    radio_controller_SPI_write(ba, rfSel, 2, 0x3007);
106   
107    //MAX2829 reg5:
108    // -40MHz reference clock (reg5[3:1]=[0 1 0])
109    // -MIMO mode (reg5[13]=1)
110    // -Other bits set to defaults
111    radio_controller_SPI_write(ba, rfSel, 5, 0x3824);
112
113    //MAX2829 reg8:
114    // -RSSI output in [0.5,2.5]v (reg8[11]=1)
115    // -RSSI output always on in Rx mode (reg8[10]=1)
116    // -Other bits set to defaults
117    radio_controller_SPI_write(ba, rfSel, 8, 0x0C25);
118   
119    //MAX2829 reg9:
120    // -Max linearity for Tx PA driver (reg9[9:8]=[1 1]
121    // -Max linearity for Tx VGA (reg9[7:6]=[1 1])
122    // -Max linearity for upconverter (reg9[3:2]=[1 1])
123    // -Tx baseband gain set to (max-3dB) (reg9[1:0]=[1 0])
124    radio_controller_SPI_write(ba, rfSel, 9, 0x03CD);
125
126
127    //Finally bring the MAX2829 out of shutdown
128    // The PLL should lock (LD -> 1) shortly after this call
129    radio_controller_setMode_standby(ba, rfCtrlMask);
130
131    pll_lock_status = 0;
132   
133    while(pll_lock_status != (RC_REG11_LD & rfCtrlMask)) {
134        rc_usleep(5000);
135        pll_lock_status = Xil_In32(ba + RC_SLV_REG11_OFFSET) & RC_REG11_LD & rfCtrlMask;
136        pll_lock_wait_tries++;
137        if(pll_lock_wait_tries > 1000) {
138            xil_printf("Radios didn't lock! RC stat reg: 0x%08x\n", Xil_In32(ba + RC_SLV_REG11_OFFSET));
139            return -1;
140        }
141    }
142//  xil_printf("Radios locked after %d tries\n", pll_lock_wait_tries);
143
144
145    //Set sane defaults
146    radio_controller_setTxDelays(ba, 150, 0, 0, 250);
147    radio_controller_setTxGainTiming(ba, 0xF, 3);
148
149    return 0;
150}
151
152/**
153\brief Sets the selected RF interfaces to the Transmit state. The corresponding MAX2829s, PAs and RF switches are all
154set to the correct state for transmission. This call initiates the Tx sequencing state machine. Refer to the
155<a href="http://warp.rice.edu/trac/wiki/cores/radio_controller">radio_controller user guide</a> for more details.
156\param ba Base memory address of radio_controller pcore
157\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
158\return Returns non-zero value if an input parameter was invalid; else returns 0
159*/
160int radio_controller_TxEnable(u32 ba, u32 rfSel) {
161
162    u32 rfCtrlMask, oldVal, newVal;
163
164    if((rfSel & RC_ANY_RF)==0)
165        return RC_INVALID_RFSEL;
166
167    rfCtrlMask = 0;
168       
169    //Convert the user-supplied masks to the masks for the control registers
170    if(rfSel & RC_RFA) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFA;
171    if(rfSel & RC_RFB) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFB;
172    if(rfSel & RC_RFC) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFC;
173    if(rfSel & RC_RFD) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFD;
174
175    oldVal = Xil_In32(ba + RC_SLV_REG0_OFFSET);
176   
177    //Force RxEn=0, SHDN=1 for radios selected by rfsel
178    oldVal = (oldVal & (~(rfCtrlMask & RC_REG0_RXEN))) | (rfCtrlMask & RC_REG0_SHDN);
179   
180    newVal = oldVal | (rfCtrlMask & RC_REG0_TXEN);
181   
182    Xil_Out32(ba + RC_SLV_REG0_OFFSET, newVal);
183   
184//  radio_controller_setMode_standby(ba, rfCtrlMask);
185//  radio_controller_setMode_Tx(ba, rfCtrlMask);
186
187    return 0;
188}
189
190/**
191\brief Sets the selected RF interfaces to the Receive state. The corresponding MAX2829s and RF switches are
192set to the correct state for reception. The PAs in the selected RF interfaces are disabled.
193\param ba Base memory address of radio_controller pcore
194\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
195\return Returns non-zero value if an input parameter was invalid; else returns 0
196*/
197int radio_controller_RxEnable(u32 ba, u32 rfSel) {
198
199    u32 rfCtrlMask, oldVal, newVal;;
200
201    if((rfSel & RC_ANY_RF)==0)
202        return RC_INVALID_RFSEL;
203       
204    rfCtrlMask = 0;
205       
206    //Convert the user-supplied masks to the masks for the control registers
207    if(rfSel & RC_RFA) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFA;
208    if(rfSel & RC_RFB) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFB;
209    if(rfSel & RC_RFC) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFC;
210    if(rfSel & RC_RFD) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFD;
211
212    oldVal = Xil_In32(ba + RC_SLV_REG0_OFFSET);
213   
214    //Force TxEn=0, SHDN=1 for radios selected by rfsel
215    oldVal = (oldVal & (~(rfCtrlMask & RC_REG0_TXEN))) | (rfCtrlMask & RC_REG0_SHDN);
216   
217    newVal = oldVal | (rfCtrlMask & RC_REG0_RXEN);
218   
219    Xil_Out32(ba + RC_SLV_REG0_OFFSET, newVal);
220
221//  radio_controller_setMode_standby(ba, rfCtrlMask);
222//  radio_controller_setMode_Rx(ba, rfCtrlMask);
223
224    return 0;
225}
226
227/**
228\brief Sets the selected RF interfaces to the Standby state (Tx and Rx disabled). The corresponding MAX2829s and PAs are
229set to the correct state for standby.
230\param ba Base memory address of radio_controller pcore
231\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
232\return Returns non-zero value if an input parameter was invalid; else returns 0
233*/
234int radio_controller_TxRxDisable(u32 ba, u32 rfSel) {
235
236    u32 rfCtrlMask = 0;
237
238    if((rfSel & RC_ANY_RF)==0)
239        return RC_INVALID_RFSEL;
240       
241    //Convert the user-supplied masks to the masks for the control registers
242    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
243    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
244    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
245    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
246
247    radio_controller_setMode_standby(ba, rfCtrlMask);
248
249    return 0;
250}
251
252/**
253\brief Sets the selected RF interfaces to the Standby state (Tx and Rx disabled). The corresponding MAX2829s and PAs are
254set to the correct state for standby.
255\param ba Base memory address of radio_controller pcore
256\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
257\param bandSel Selects the 2.4GHz or 5GHz band; must be RC_24GHZ or RC_5GHZ
258\param chanNum New center frequency channel number, in [1,14] for 2.4GHz or [1,23] for 5GHz. The channel numbers
259and corresponding center frequencies are listed in the table below.
260\return Returns non-zero value if an input parameter was invalid; else returns 0
261
2622.4GHz <br> Chan | Freq <br> (MHz) | | 5GHz <br> Chan | Freq <br> (MHz)
263--- | ----- | - | --- | -----
2641 | 2412 |  | 1 | 5180
2652 | 2417 |  | 2 | 5190
2663 | 2422 |  | 3 | 5200
2674 | 2427 |  | 4 | 5220
2685 | 2432 |  | 5 | 5230
2696 | 2437 |  | 6 | 5240
2707 | 2442 |  | 7 | 5260
2718 | 2447 |  | 8 | 5270
2729 | 2452 |  | 9 | 5280
27310 | 2457 |  | 10 | 5300
27411 | 2462 |  | 11 | 5310
27512 | 2467 |  | 12 | 5320
27613 | 2472 |  | 13 | 5500
27714 | 2484 |  | 14 | 5510
278- | - | | 15 | 5520
279- | - | | 16 | 5540
280- | - | | 17 | 5550
281- | - | | 18 | 5560
282- | - | | 19 | 5580
283- | - | | 20 | 5590
284- | - | | 21 | 5600
285- | - | | 22 | 5620
286- | - | | 23 | 5630
287- | - | | 24 | 5640
288- | - | | 25 | 5660
289- | - | | 26 | 5670
290- | - | | 27 | 5680
291- | - | | 28 | 5700
292- | - | | 29 | 5710
293- | - | | 30 | 5720
294- | - | | 31 | 5745
295- | - | | 32 | 5755
296- | - | | 33 | 5765
297- | - | | 34 | 5785
298- | - | | 35 | 5795
299- | - | | 36 | 5805
300- | - | | 37 | 5825
301- | - | | 38 | 5860
302- | - | | 39 | 5870
303- | - | | 40 | 5875
304- | - | | 41 | 5880
305- | - | | 42 | 5885
306- | - | | 43 | 5890
307- | - | | 44 | 5865
308*/
309int radio_controller_setCenterFrequency(u32 ba, u32 rfSel, u8 bandSel, u8 chanNum) {
310
311    if((bandSel == RC_24GHZ) && (chanNum >= 1) && (chanNum <= 14) && (rfSel & RC_ANY_RF)){ //14 valid 2.4GHz channels
312        //MAX2829 tuning process for 2.4GHz channels:
313        // -Set reg5[0] to 0 (selects 2.4GHz)
314        // -Set reg3, reg4 with PLL tuning params
315
316        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x1, 0x0);
317
318        //Write the PLL parameters
319        radio_controller_SPI_write(ba, rfSel, 3, rc_tuningParams_24GHz_reg3[chanNum-1]);
320        radio_controller_SPI_write(ba, rfSel, 4, rc_tuningParams_24GHz_reg4[chanNum-1]);
321
322        return(rc_tuningParams_24GHz_freqs[chanNum-1]);
323    }
324
325    if((bandSel == RC_5GHZ) && (chanNum >= 1) && (chanNum <= 44) && (rfSel & RC_ANY_RF)) {
326        //MAX2829 tuning process for 5GHz channels:
327        //(Assumes default config of 5GHz sub-band tuning via FSM; see MAX2829 datasheet for details)
328        // -Set:
329        //   -reg5[0] to 1 (selects 5GHz)
330        //   -reg5[6] based on selected freq (0:4.9-5.35GHz, 1:5.47-5.875GHz)
331        // -Set reg3, reg4 with PLL tuning params
332
333        if(chanNum <= 12)
334            radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x41, 0x01);
335        else
336            radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x41, 0x41);
337
338        //Reset the band select FSM
339        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x80, 0x00);
340       
341        //Write the PLL parameters
342        radio_controller_SPI_write(ba, rfSel, 3, rc_tuningParams_5GHz_reg3[chanNum-1]);
343        radio_controller_SPI_write(ba, rfSel, 4, rc_tuningParams_5GHz_reg4[chanNum-1]);
344
345        //Start the band select FSM
346        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x80, 0x80);
347       
348        return(rc_tuningParams_5GHz_freqs[chanNum-1]);
349    }
350   
351    //Some input param was invalid if we get here, so return an invalid frequency
352    return RC_INVALID_PARAM;
353}
354
355/**
356\brief Reads the radio controller "mirror" register corresponding to the MAX2829 register at regAddr
357\param ba Base memory address of radio_controller pcore
358\param rfSel Selects RF interface to read (must be one of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
359\param regAddr Register address to read, in [0x0,0xC]
360\return Returns 255 if input parameters are invalid; otherwise returns 14-bit register value
361*/
362u16 radio_controller_SPI_read(u32 ba, u32 rfSel, u8 regAddr) {
363    if(((rfSel & RC_ANY_RF)==0) || (regAddr>0xC))
364        return 255; //impossible value for 14-bit registers; use for error checking
365
366    //Use Xil_In32 to grab 16LSB of each register (Xil_In16 reads 16MSB of 32-bit register when address is aligned to 4 bytes)
367    if(rfSel & RC_RFA)
368        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFA_BASEADDR + 4*regAddr));
369
370    if(rfSel & RC_RFB)
371        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFB_BASEADDR + 4*regAddr));
372
373    if(rfSel & RC_RFC)
374        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFC_BASEADDR + 4*regAddr));
375
376    if(rfSel & RC_RFD)
377        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFD_BASEADDR + 4*regAddr));
378
379    //Can't get here, but return error anyway so compiler doesn't complain
380    return 254;
381}
382
383/**
384\brief Sets specific bits in a single register in selected MAX2829s
385\param ba Base memory address of radio_controller pcore
386\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
387\param regAddr Register address to write, in [0x0,0xC]
388\param regDataMask 14-bit mask of bits to affect (1 in mask selects bit for writing)
389\param regData 14-bit value to set; only bits with 1 in regDataMask are used
390\return Returns non-zero if input parameters are invalid; otherwise returns 0
391*/
392int radio_controller_SPI_setRegBits(u32 ba, u32 rfSel, u8 regAddr, u16 regDataMask, u16 regData) {
393    u16 curRegData;
394    u16 newRegData;
395   
396    if(((rfSel & RC_ANY_RF)==0) || (regAddr>13))
397        return RC_INVALID_RFSEL;
398
399    if(rfSel & RC_RFA) {
400        curRegData = radio_controller_SPI_read(ba, RC_RFA, regAddr);
401        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
402        radio_controller_SPI_write(ba, RC_RFA, regAddr, newRegData);
403    }
404    if(rfSel & RC_RFB) {
405        curRegData = radio_controller_SPI_read(ba, RC_RFB, regAddr);
406        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
407        radio_controller_SPI_write(ba, RC_RFB, regAddr, newRegData);
408    }
409    if(rfSel & RC_RFC) {
410        curRegData = radio_controller_SPI_read(ba, RC_RFC, regAddr);
411        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
412        radio_controller_SPI_write(ba, RC_RFC, regAddr, newRegData);
413    }
414    if(rfSel & RC_RFD) {
415        curRegData = radio_controller_SPI_read(ba, RC_RFD, regAddr);
416        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
417        radio_controller_SPI_write(ba, RC_RFD, regAddr, newRegData);
418    }
419
420    return 0;   
421}
422
423/**
424\brief Sets state of RXHP pin on selected MAX2829s. This function only affects state if the RXHP control
425source is set to software on the selected RF interfaces.
426\param ba Base memory address of radio_controller pcore
427\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
428\param mode RXHP is asserted if mode=RC_RXHP_ON, else RXHP is deasserted
429\return Returns non-zero if input parameters are invalid; otherwise returns 0
430*/
431int radio_controller_setRxHP(u32 ba, u32 rfSel, u8 mode) {
432    //Sanity check inputs
433    if((rfSel & RC_ANY_RF) == 0)
434        return RC_INVALID_RFSEL;
435
436    if(mode > 1)
437        return RC_INVALID_PARAM;
438
439    u32 rfCtrlMask = 0;
440   
441    //Convert the user-supplied masks to the masks for the control registers
442    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
443    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
444    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
445    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
446
447    u32 curRegVal, newRegVal;
448
449    curRegVal = Xil_In32(ba+RC_SLV_REG0_OFFSET);
450   
451    if(mode == RC_RXHP_ON) {
452        //Assert RxHP bits in reg0; drives 1 to corresponding RxHP pin on MAX2829
453        newRegVal = curRegVal | (RC_REG0_RXHP & rfCtrlMask);
454    } else {
455        newRegVal = curRegVal & (~(RC_REG0_RXHP & rfCtrlMask));
456    }
457   
458    Xil_Out32(ba+RC_SLV_REG0_OFFSET, newRegVal);
459
460    return 0;
461}
462
463/**
464\brief Selects between register or hardware control for the various radio control signals on the selected RF interfaces.
465\param ba Base memory address of radio_controller pcore
466\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
467\param ctrlSrcMask Specifies which control signals should have new control source; OR'd combination of [RC_REG0_TXEN_CTRLSRC, RC_REG0_RXEN_CTRLSRC, RC_REG0_RXHP_CTRLSRC, RC_REG0_SHDN_CTRLSRC]
468\param ctrlSrc Selects register (from C code) or hardware (usr_ ports) control; must be RC_CTRLSRC_REG or RC_CTRLSRC_HW
469\return Returns non-zero if input parameters are invalid; otherwise returns 0
470*/
471int radio_controller_setCtrlSource(u32 ba, u32 rfSel, u32 ctrlSrcMask, u8 ctrlSrc) {
472
473    //Sanity check inputs
474    if((rfSel & RC_ANY_RF) == 0)
475        return RC_INVALID_RFSEL;
476
477    if((ctrlSrcMask & RC_REG0_ALL_CTRLSRC) == 0)
478        return RC_INVALID_PARAM;
479
480    u32 rfCtrlMask = 0;
481   
482    //Convert the user-supplied masks to the masks for the control registers
483    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
484    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
485    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
486    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
487
488    u32 curRegVal, newRegVal;
489
490    curRegVal = Xil_In32(ba+RC_SLV_REG0_OFFSET);
491   
492    if(ctrlSrc == RC_CTRLSRC_HW) {
493        //Hardware control via usr_* ports enabled by 1 in reg0 ctrlSrc bits
494        newRegVal = curRegVal | (ctrlSrcMask & rfCtrlMask & RC_REG0_ALL_CTRLSRC);
495    } else {
496        //Software control via writes to reg0 (RC_REG0_TXEN, RC_REG0_RXEN, etc.)
497        newRegVal = curRegVal & (~(ctrlSrcMask & rfCtrlMask & RC_REG0_ALL_CTRLSRC));
498    }
499   
500    Xil_Out32(ba+RC_SLV_REG0_OFFSET, newRegVal);
501
502    return 0;
503}
504
505/**
506\brief Sets the final Tx VGA gain set by the Tx sequencing state machine for the selected RF interfaces
507\param ba Base memory address of radio_controller pcore
508\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
509\param gainTarget Tx VGA gain setting, in [0,63]
510\return Returns non-zero if input parameters are invalid; otherwise returns 0
511*/
512int radio_controller_setTxGainTarget(u32 ba, u32 rfSel, u8 gainTarget) {
513    //Sanity check inputs
514    if(((rfSel & RC_ANY_RF)==0))
515        return RC_INVALID_RFSEL;
516
517    u32 regVal;
518
519    regVal = Xil_In32(ba+RC_SLV_REG2_OFFSET);
520   
521    if(rfSel & RC_RFA)
522        regVal = (regVal & ~(0x0000003F)) | ((gainTarget<< 0) & 0x0000003F);
523    if(rfSel & RC_RFB)
524        regVal = (regVal & ~(0x00003F00)) | ((gainTarget<< 8) & 0x00003F00);
525    if(rfSel & RC_RFC)
526        regVal = (regVal & ~(0x003F0000)) | ((gainTarget<<16) & 0x003F0000);
527    if(rfSel & RC_RFD)
528        regVal = (regVal & ~(0x3F000000)) | ((gainTarget<<24) & 0x3F000000);
529   
530    Xil_Out32(ba+RC_SLV_REG2_OFFSET, regVal);
531
532    return 0;
533}
534
535/**
536\brief Sets the control source for Tx gains in the selected RF interfaces
537\param ba Base memory address of radio_controller pcore
538\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
539\param gainSrc must be one of [RC_GAINSRC_SPI, RC_GAINSRC_REG, RC_GAINSRC_HW], for SPI control, register control or hardware (usr_RFx_TxGain port) control
540\return Returns non-zero if input parameters are invalid; otherwise returns 0
541*/
542int radio_controller_setTxGainSource(u32 ba, u32 rfSel, u8 gainSrc) {
543
544    //Sanity check inputs
545    if(((rfSel & RC_ANY_RF)==0))
546        return RC_INVALID_RFSEL;
547
548    u32 rfCtrlMask = 0;
549    u32 curRegVal, newRegVal;
550   
551    //Convert the user-supplied masks to the masks for the control registers
552    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
553    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
554    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
555    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
556
557    if(gainSrc == RC_GAINSRC_SPI) {
558        //Configure MAX2829 for Tx gain control via SPI
559        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_TXGAINS_SPI_CTRL_EN, 1);
560        return 0;
561    }
562    else if(gainSrc == RC_GAINSRC_HW) {
563        //Disable SPI Tx gain control in MAX2829
564        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_TXGAINS_SPI_CTRL_EN, 0);
565       
566        //Configure radio controller for Tx gain target from usr_ ports in logic
567        curRegVal = Xil_In32(ba+RC_SLV_REG2_OFFSET);
568        newRegVal = (curRegVal | (rfCtrlMask & RC_REG2_TXGAIN_CTRLSRC));
569        Xil_Out32(ba+RC_SLV_REG2_OFFSET, newRegVal);
570        return 0;
571    }
572    else if(gainSrc == RC_GAINSRC_REG) {
573        //Disable SPI Tx gain control in MAX2829
574        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_TXGAINS_SPI_CTRL_EN, 0);
575   
576        //Configure radio controller for Tx gain target from registers
577        curRegVal = Xil_In32(ba+RC_SLV_REG2_OFFSET);
578        newRegVal = (curRegVal & ~(rfCtrlMask & RC_REG2_TXGAIN_CTRLSRC));
579        Xil_Out32(ba+RC_SLV_REG2_OFFSET, newRegVal);
580        return 0;
581    }
582       
583    //gainSrc must have been invalid if we get here
584    return RC_INVALID_PARAM;
585}
586
587/**
588\brief Sets the control source for Rx gains in the selected RF interfaces. Note that when hardware control is selected, the corresponding
589RXHP should also be set for hardware control using radio_controller_setCtrlSource().
590\param ba Base memory address of radio_controller pcore
591\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
592\param gainSrc must be one of [RC_GAINSRC_SPI, RC_GAINSRC_REG, RC_GAINSRC_HW], for SPI control, register control or hardware (usr_RFx_TxGain port) control
593\return Returns non-zero if input parameters are invalid; otherwise returns 0
594*/
595int radio_controller_setRxGainSource(u32 ba, u32 rfSel, u8 gainSrc) {
596    //Sanity check inputs
597    if(((rfSel & RC_ANY_RF)==0))
598        return RC_INVALID_RFSEL;
599
600    u32 rfCtrlMask = 0;
601    u32 curRegVal, newRegVal;
602   
603    //Convert the user-supplied masks to the masks for the control registers
604    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
605    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
606    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
607    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
608
609    if(gainSrc == RC_GAINSRC_SPI) {
610        //Configure MAX2829 for Tx gain control via SPI
611        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_RXGAINS_SPI_CTRL_EN, 1);
612        return 0;
613    }
614    else if(gainSrc == RC_GAINSRC_REG) {
615        //Disable SPI Rx gain control in MAX2829
616        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_RXGAINS_SPI_CTRL_EN, 0);
617       
618        //Configure radio controller for Rx gains from registers
619        curRegVal = Xil_In32(ba+RC_SLV_REG3_OFFSET);
620        newRegVal = (curRegVal & ~(rfCtrlMask & RC_REG3_RXGAIN_CTRLSRC));
621        Xil_Out32(ba+RC_SLV_REG3_OFFSET, newRegVal);
622        return 0;
623    }
624    else if(gainSrc == RC_GAINSRC_HW) {
625        //Disable SPI Rx gain control in MAX2829
626        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_RXGAINS_SPI_CTRL_EN, 0);
627       
628        //Configure radio controller for Tx gains from usr_ ports in logic
629        curRegVal = Xil_In32(ba+RC_SLV_REG3_OFFSET);
630        newRegVal = (curRegVal | (rfCtrlMask & RC_REG3_RXGAIN_CTRLSRC));
631        Xil_Out32(ba+RC_SLV_REG3_OFFSET, newRegVal);
632        return 0;
633    }
634       
635    //gainSrc must have been invalid if we get here
636    return RC_INVALID_PARAM;
637
638}
639
640/**
641\brief Sets a MAX2829 parameter via a SPI register write.
642\param ba Base memory address of radio_controller pcore
643\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
644\param paramID Parameter ID to update. Must be valid RC_PARAMID_* (see table below)
645\param paramVal Parameter value to set. Valid values depend on the selected parameter (see table below)
646\return Returns non-zero if input parameters are invalid; otherwise returns 0
647
648Parameter ID | Description | Parameter Values
649------------ | ----------- | ----------------
650RC_PARAMID_RXGAIN_RF | Rx RF gain value | 1: 0dB<br>2: 15dB<br>3: 30dB
651RC_PARAMID_RXGAIN_BB | Rx baseband gain value | [0,31]: approx [0,63]dB
652RC_PARAMID_TXGAIN_RF | Tx RF gain value | [0,63]: approx [0,31]dB
653RC_PARAMID_TXGAIN_BB | Tx baseband gain value | 0: 0<br>1: -1.5dB<br>2: -3dB<br>3: -5dB
654RC_PARAMID_TXLPF_BW | Tx low pass filter corner frequency<br> (Tx bandwidth is 2x corner frequency) | 1: 12MHz<br>2: 18MHz<br>3: 24MHz
655RC_PARAMID_RXLPF_BW | Rx low pass filter corner frequency<br> (Rx bandwidth is 2x corner frequency) | 0: 7.5MHz<br>1: 9.5MHz<br>2: 14MHz<br>3: 18MHz
656RC_PARAMID_RXLPF_BW_FINE | Rx low pass filter corner fine adjustment | 0: 90%<br>1: 95%<br>2: 100%<br>3: 105%<br>4: 110%
657RC_PARAMID_RXHPF_HIGH_CUTOFF_EN | Set corner frequency for Rx high pass filter when RXHP=0| 0: Low corner (100Hz)<br>1: High corner (30kHz)
658RC_PARAMID_RSSI_HIGH_BW_EN | En/disable high bandwidth RSSI signal | 0: Disable high bandwidth RSSI<br>1: Enable high bandwidth RSSI
659RC_PARAMID_TXLINEARITY_PADRIVER | Linearity of Tx PA driver circuit | [0,3]: [min,max] linearity
660RC_PARAMID_TXLINEARITY_VGA | Linearity of Tx VGA circuit | [0,3]: [min,max] linearity
661RC_PARAMID_TXLINEARITY_UPCONV | Linearity of Tx upconverter circuit | [0,3]: [min,max] linearity
662RC_PARAMID_TXGAINS_SPI_CTRL_EN |  En/disable SPI control of Tx gains | 0: Disable SPI control<br>1: Enable SPI control
663RC_PARAMID_RXGAINS_SPI_CTRL_EN |  En/disable SPI control of Rx gains | 0: Disable SPI control<br>1: Enable SPI control
664
665*/
666int radio_controller_setRadioParam(u32 ba, u32 rfSel, u32 paramID, u32 paramVal) {
667    u16 curRegData;
668    u16 newRegData;
669
670    u16 x, y;
671
672    //Sanity check inputs
673    if(((rfSel & RC_ANY_RF)==0))
674        return RC_INVALID_RFSEL;
675       
676       
677    switch(paramID) {
678#ifdef RC_INCLUDED_PARAMS_GAIN_CTRL
679        case RC_PARAMID_TXGAINS_SPI_CTRL_EN:
680            //reg9[10]: 0=B port controls Tx VGA gain, 1=SPI regC[5:0] controls Tx VGA gain
681            if(paramVal > 1) return RC_INVALID_PARAM;
682            x = paramVal ? 0x0400 : 0x0000;
683            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0400, x);
684            break;
685        case RC_PARAMID_RXGAINS_SPI_CTRL_EN:
686            //reg8[12]: 0=B port controls Rx gains, 1=SPI regB[6:0] controls Rx gains
687            if(paramVal > 1) return RC_INVALID_PARAM;
688            x = paramVal ? 0x1000 : 0x0000;
689            return radio_controller_SPI_setRegBits(ba, rfSel, 0x8, 0x1000, x);
690            break;
691        case RC_PARAMID_RXGAIN_RF:
692            //regB[6:5] sets LNA gain (but only if SPI control for Rx gains is enabled)
693            if(paramVal > 3) return RC_INVALID_PARAM;
694            x = (paramVal & 0x3)<<5;
695            return radio_controller_SPI_setRegBits(ba, rfSel, 0xB, 0x0060, x);
696        case RC_PARAMID_RXGAIN_BB:
697            //regB[4:0] sets Rx VGA gain (but only if SPI control for Rx gains is enabled)
698            if(paramVal > 31) return RC_INVALID_PARAM;
699            x = (paramVal & 0x1F);
700            return radio_controller_SPI_setRegBits(ba, rfSel, 0xB, 0x001F, x);
701            break;
702        case RC_PARAMID_TXGAIN_RF:
703            //regC[5:0] sets Tx RF VGA gain (but only if SPI control for Tx gains is enabled)
704            if(paramVal > 63) return RC_INVALID_PARAM;
705            x = (paramVal & 0x3F);
706            return radio_controller_SPI_setRegBits(ba, rfSel, 0xC, 0x003F, x);
707            break;
708        case RC_PARAMID_TXGAIN_BB:
709            //reg9[1:0] sets Tx BB gain (Tx BB gain always set via SPI)
710            if(paramVal > 3) return RC_INVALID_PARAM;
711            x = (paramVal & 0x3);
712            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0003, x);
713            break;
714#endif //RC_INCLUDED_PARAMS_GAIN_CTRL
715
716#ifdef RC_INCLUDED_PARAMS_FILTS
717        case RC_PARAMID_TXLPF_BW:
718            //reg7[6:5]: 00=undefined, 01=12MHz, 10=18MHz, 11=24MHz
719            if(paramVal == 0 || paramVal > 3) return RC_INVALID_PARAM;
720            x = (paramVal&0x3)<<5;
721            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0060, x);
722            break;
723        case RC_PARAMID_RXLPF_BW:
724            //reg7[4:3]: 00=7.5MHz, 01=9.5MHz, 10=14MHz, 11=18MHz
725            if(paramVal > 3) return RC_INVALID_PARAM;
726            x = (paramVal&0x3)<<3;
727            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0018, x);
728            break;
729        case RC_PARAMID_RXLPF_BW_FINE:
730            //reg7[2:0]: 000=90%, 001=95%, 010=100%, 011=105%, 100=110%
731            if(paramVal > 4) return RC_INVALID_PARAM;
732            x = (paramVal&0x7);
733            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0007, x);
734            break;
735        case RC_PARAMID_RXHPF_HIGH_CUTOFF_EN:
736            //reg8[2]: HPF corner freq when RxHP=0; 0=100Hz, 1=30kHz
737            if(paramVal > 1) return RC_INVALID_PARAM;
738            x = paramVal ? 0x0004 : 0x0000;
739            return radio_controller_SPI_setRegBits(ba, rfSel, 0x8, 0x0004, x);
740            break;
741#endif //RC_INCLUDED_PARAMS_FILTS
742
743#ifdef RC_INCLUDED_PARAMS_MISC
744        case RC_PARAMID_RSSI_HIGH_BW_EN:
745            //reg7[11]: 0=2MHz RSSI BW, 1=6MHZ RSSI BW
746            if(paramVal > 1) return RC_INVALID_PARAM;
747            x = paramVal ? 0x0800 : 0x0000;
748            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0800, x);
749            break;
750        case RC_PARAMID_TXLINEARITY_PADRIVER:
751            //reg9[9:8]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
752            if(paramVal > 3) return RC_INVALID_PARAM;
753            x = (paramVal&0x3)<<8;
754            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0300, x);
755            break;
756        case RC_PARAMID_TXLINEARITY_VGA:
757            //reg9[7:6]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
758            if(paramVal > 3) return RC_INVALID_PARAM;
759            x = (paramVal&0x3)<<6;
760            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x00C0, x);
761            break;
762        case RC_PARAMID_TXLINEARITY_UPCONV:
763            //reg9[3:2]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
764            if(paramVal > 3) return RC_INVALID_PARAM;
765            x = (paramVal&0x3)<<2;
766            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x000C, x);
767            break;
768#endif //RC_INCLUDED_PARAMS_MISC
769        default:
770            //Either no paramters were #ifdef'd in, or user supplied invalid paramID
771            return RC_INVALID_PARAMID;
772            break;
773    }
774
775    return 0;
776}
777
778/**
779\brief Reads the TxDCO calibration values from the EEPROM and writes the values to the DACs of the selected RF interface. This function
780requires the w3_iic_eeprom and w3_ad_controller cores.
781\param ad_ba Base memory address of w3_ad_controller core
782\param iic_ba Base memory address of w3_iic_eeprom core
783\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
784\return Returns non-zero if w3_ad_controller or w3_iic_eeprom core is not found; otherwise returns 0
785*/
786int radio_controller_apply_TxDCO_calibration(u32 ad_ba, u32 iic_ba, u32 rfSel) {
787#if defined XPAR_W3_IIC_EEPROM_NUM_INSTANCES && defined XPAR_W3_AD_CONTROLLER_NUM_INSTANCES
788    u16 rI, rQ;
789    u32 ad_sel = 0;
790   
791    if(rfSel & RC_RFA)
792        ad_sel |= RFA_AD_CS;
793    if(rfSel & RC_RFB)
794        ad_sel |= RFB_AD_CS;
795    if(rfSel & RC_RFC)
796        ad_sel |= RFC_AD_CS;
797    if(rfSel & RC_RFD)
798        ad_sel |= RFD_AD_CS;
799   
800    //For each radio interface specified by rfSel:
801    // -Read the I/Q TxDCO calibration values from the EEPROM (two u16 values)
802    // -Apply the TxDCO calibration values via the ad_controller driver
803    //The RC_EEPROM_TXDCO_ADDR_RFx_x macros are defined in radio_controller.h
804    //The on-board RF interfaces use the on-board EEPROM
805    //FMC RF interfaces use the EEPROM on the FMC module
806    //On-board RFA/RFB use the same EEPROM byte addresses as FMC RFC/RFD, respectively
807    //User code must supply the correct IIC controller base address when calling this function
808    if(rfSel & (RC_RFA | RC_RFC)) {
809        rI = iic_eeprom_readByte(iic_ba, RC_EEPROM_TXDCO_ADDR_RFA_I) + (iic_eeprom_readByte(iic_ba, RC_EEPROM_TXDCO_ADDR_RFA_I+1)<<8);
810        rQ = iic_eeprom_readByte(iic_ba, RC_EEPROM_TXDCO_ADDR_RFA_Q) + (iic_eeprom_readByte(iic_ba, RC_EEPROM_TXDCO_ADDR_RFA_Q+1)<<8);
811   
812        ad_set_TxDCO(ad_ba, (ad_sel & (RFA_AD_CS | RFC_AD_CS)), AD_CHAN_I, rI);
813        ad_set_TxDCO(ad_ba, (ad_sel & (RFA_AD_CS | RFC_AD_CS)), AD_CHAN_Q, rQ);
814    }
815    if(rfSel & (RC_RFB | RC_RFD)) {
816        rI = iic_eeprom_readByte(iic_ba, RC_EEPROM_TXDCO_ADDR_RFB_I) + (iic_eeprom_readByte(iic_ba, RC_EEPROM_TXDCO_ADDR_RFB_I+1)<<8);
817        rQ = iic_eeprom_readByte(iic_ba, RC_EEPROM_TXDCO_ADDR_RFB_Q) + (iic_eeprom_readByte(iic_ba, RC_EEPROM_TXDCO_ADDR_RFB_Q+1)<<8);
818   
819        ad_set_TxDCO(ad_ba, (ad_sel & (RFB_AD_CS | RFD_AD_CS)), AD_CHAN_I, rI);
820        ad_set_TxDCO(ad_ba, (ad_sel & (RFB_AD_CS | RFD_AD_CS)), AD_CHAN_Q, rQ);
821    }
822   
823    return 0;
824#else
825    print("w3_iic_eeprom or w3_ad_controller pcores are missing! Cannot apply TxDCO correction\n");
826    return -1;
827#endif
828}
829
830/**
831\brief Simple pseudo-usleep implementation (since MicroBlaze lacks internal timer for native usleep implementation).
832The actual sleep time is not guaranteed to be d microseconds.
833\param d Number of "microseconds" to sleep (proportional to sleep time; actual sleep time will depend on processor and instruction memory clocks)
834*/
835void rc_usleep(int d) {
836    volatile int i;
837    for(i=0; i<d*4; i++) { /* do nothing */}
838    return;
839}
840
841/** @}*/ //END group user_functions
Note: See TracBrowser for help on using the repository browser.