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

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

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

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