source: PlatformSupport/CustomPeripherals/pcores/radio_controller_axi_v3_00_d/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: 33.4 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[30] = { 5180,   5200,   5220,   5240,   5260,   5280,   5300,   5320,   5500,   5520,   5540,   5560,   5580,   5600,   5620,   5640,   5660,   5680,   5700,   5745,   5765,   5785,   5805,   5860,   5865,   5875,   5885,   5890,   5870,   5880};
36static u16 rc_tuningParams_5GHz_reg3[30] = {0x30CF, 0x0CCC, 0x00D0, 0x10D1, 0x20D2, 0x30D3, 0x00D4, 0x00D4, 0x00DC, 0x00DC, 0x10DD, 0x20DE, 0x30DF, 0x00E0, 0x00E0, 0x10E1, 0x20E2, 0x30E3, 0x00E4, 0x00E5, 0x10E6, 0x20E7, 0x30E8, 0x20EA, 0x20EA, 0x00EB, 0x20EB, 0x10EB, 0x00EA, 0x30EB}; 
37static u16 rc_tuningParams_5GHz_reg4[30] = {0x0CCC, 0x0000, 0x3333, 0x2666, 0x1999, 0x0CCC, 0x0000, 0x3333, 0x0000, 0x3333, 0x2666, 0x1999, 0x0CCC, 0x0000, 0x3333, 0x2666, 0x1999, 0x0CCC, 0x0000, 0x3333, 0x2666, 0x1999, 0x0CCC, 0x1999, 0x2666, 0x0000, 0x1999, 0x2666, 0x3333, 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- | - | | 24 | 5860
287- | - | | 25 | 5865
288- | - | | 26 | 5875
289- | - | | 27 | 5885
290- | - | | 28 | 5890
291- | - | | 29 | 5870
292- | - | | 30 | 5880
293
294*/
295int radio_controller_setCenterFrequency(u32 ba, u32 rfSel, u8 bandSel, u8 chanNum) {
296
297    if((bandSel == RC_24GHZ) && (chanNum >= 1) && (chanNum <= 14) && (rfSel & RC_ANY_RF)){ //14 valid 2.4GHz channels
298        //MAX2829 tuning process for 2.4GHz channels:
299        // -Set reg5[0] to 0 (selects 2.4GHz)
300        // -Set reg3, reg4 with PLL tuning params
301
302        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x1, 0x0);
303
304        //Write the PLL parameters
305        radio_controller_SPI_write(ba, rfSel, 3, rc_tuningParams_24GHz_reg3[chanNum-1]);
306        radio_controller_SPI_write(ba, rfSel, 4, rc_tuningParams_24GHz_reg4[chanNum-1]);
307
308        return(rc_tuningParams_24GHz_freqs[chanNum-1]);
309    }
310
311    if((bandSel == RC_5GHZ) && (chanNum >= 1) && (chanNum <= 30) && (rfSel & RC_ANY_RF)) { //23 valid 5GHz channels
312        //MAX2829 tuning process for 5GHz channels:
313        //(Assumes default config of 5GHz sub-band tuning via FSM; see MAX2829 datasheet for details)
314        // -Set:
315        //   -reg5[0] to 1 (selects 5GHz)
316        //   -reg5[6] based on selected freq (0:4.9-5.35GHz, 1:5.47-5.875GHz)
317        // -Set reg3, reg4 with PLL tuning params
318
319        if(chanNum<=8)
320            radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x41, 0x01);
321        else
322            radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x41, 0x41);
323
324        //Reset the band select FSM
325        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x80, 0x00);
326       
327        //Write the PLL parameters
328        radio_controller_SPI_write(ba, rfSel, 3, rc_tuningParams_5GHz_reg3[chanNum-1]);
329        radio_controller_SPI_write(ba, rfSel, 4, rc_tuningParams_5GHz_reg4[chanNum-1]);
330
331        //Start the band select FSM
332        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x80, 0x80);
333       
334        return(rc_tuningParams_5GHz_freqs[chanNum-1]);
335    }
336   
337    //Some input param was invalid if we get here, so return an invalid frequency
338    return RC_INVALID_PARAM;
339}
340
341/**
342\brief Reads the radio controller "mirror" register corresponding to the MAX2829 register at regAddr
343\param ba Base memory address of radio_controller pcore
344\param rfSel Selects RF interface to read (must be one of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
345\param regAddr Register address to read, in [0x0,0xC]
346\return Returns 255 if input parameters are invalid; otherwise returns 14-bit register value
347*/
348u16 radio_controller_SPI_read(u32 ba, u32 rfSel, u8 regAddr) {
349    if(((rfSel & RC_ANY_RF)==0) || (regAddr>0xC))
350        return 255; //impossible value for 14-bit registers; use for error checking
351
352    //Use Xil_In32 to grab 16LSB of each register (Xil_In16 reads 16MSB of 32-bit register when address is aligned to 4 bytes)
353    if(rfSel & RC_RFA)
354        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFA_BASEADDR + 4*regAddr));
355
356    if(rfSel & RC_RFB)
357        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFB_BASEADDR + 4*regAddr));
358
359    if(rfSel & RC_RFC)
360        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFC_BASEADDR + 4*regAddr));
361
362    if(rfSel & RC_RFD)
363        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFD_BASEADDR + 4*regAddr));
364
365    //Can't get here, but return error anyway so compiler doesn't complain
366    return 254;
367}
368
369/**
370\brief Sets specific bits in a single register in selected MAX2829s
371\param ba Base memory address of radio_controller pcore
372\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
373\param regAddr Register address to write, in [0x0,0xC]
374\param regDataMask 14-bit mask of bits to affect (1 in mask selects bit for writing)
375\param regData 14-bit value to set; only bits with 1 in regDataMask are used
376\return Returns non-zero if input parameters are invalid; otherwise returns 0
377*/
378int radio_controller_SPI_setRegBits(u32 ba, u32 rfSel, u8 regAddr, u16 regDataMask, u16 regData) {
379    u16 curRegData;
380    u16 newRegData;
381   
382    if(((rfSel & RC_ANY_RF)==0) || (regAddr>13))
383        return RC_INVALID_RFSEL;
384
385    if(rfSel & RC_RFA) {
386        curRegData = radio_controller_SPI_read(ba, RC_RFA, regAddr);
387        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
388        radio_controller_SPI_write(ba, RC_RFA, regAddr, newRegData);
389    }
390    if(rfSel & RC_RFB) {
391        curRegData = radio_controller_SPI_read(ba, RC_RFB, regAddr);
392        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
393        radio_controller_SPI_write(ba, RC_RFB, regAddr, newRegData);
394    }
395    if(rfSel & RC_RFC) {
396        curRegData = radio_controller_SPI_read(ba, RC_RFC, regAddr);
397        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
398        radio_controller_SPI_write(ba, RC_RFC, regAddr, newRegData);
399    }
400    if(rfSel & RC_RFD) {
401        curRegData = radio_controller_SPI_read(ba, RC_RFD, regAddr);
402        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
403        radio_controller_SPI_write(ba, RC_RFD, regAddr, newRegData);
404    }
405
406    return 0;   
407}
408
409/**
410\brief Sets state of RXHP pin on selected MAX2829s. This function only affects state if the RXHP control
411source is set to software on the selected RF interfaces.
412\param ba Base memory address of radio_controller pcore
413\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
414\param mode RXHP is asserted if mode=RC_RXHP_ON, else RXHP is deasserted
415\return Returns non-zero if input parameters are invalid; otherwise returns 0
416*/
417int radio_controller_setRxHP(u32 ba, u32 rfSel, u8 mode) {
418    //Sanity check inputs
419    if((rfSel & RC_ANY_RF) == 0)
420        return RC_INVALID_RFSEL;
421
422    if(mode > 1)
423        return RC_INVALID_PARAM;
424
425    u32 rfCtrlMask = 0;
426   
427    //Convert the user-supplied masks to the masks for the control registers
428    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
429    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
430    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
431    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
432
433    u32 curRegVal, newRegVal;
434
435    curRegVal = Xil_In32(ba+RC_SLV_REG0_OFFSET);
436   
437    if(mode == RC_RXHP_ON) {
438        //Assert RxHP bits in reg0; drives 1 to corresponding RxHP pin on MAX2829
439        newRegVal = curRegVal | (RC_REG0_RXHP & rfCtrlMask);
440    } else {
441        newRegVal = curRegVal & (~(RC_REG0_RXHP & rfCtrlMask));
442    }
443   
444    Xil_Out32(ba+RC_SLV_REG0_OFFSET, newRegVal);
445
446    return 0;
447}
448
449/**
450\brief Selects between register or hardware control for the various radio control signals on the selected RF interfaces.
451\param ba Base memory address of radio_controller pcore
452\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
453\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]
454\param ctrlSrc Selects register (from C code) or hardware (usr_ ports) control; must be RC_CTRLSRC_REG or RC_CTRLSRC_HW
455\return Returns non-zero if input parameters are invalid; otherwise returns 0
456*/
457int radio_controller_setCtrlSource(u32 ba, u32 rfSel, u32 ctrlSrcMask, u8 ctrlSrc) {
458
459    //Sanity check inputs
460    if((rfSel & RC_ANY_RF) == 0)
461        return RC_INVALID_RFSEL;
462
463    if((ctrlSrcMask & RC_REG0_ALL_CTRLSRC) == 0)
464        return RC_INVALID_PARAM;
465
466    u32 rfCtrlMask = 0;
467   
468    //Convert the user-supplied masks to the masks for the control registers
469    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
470    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
471    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
472    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
473
474    u32 curRegVal, newRegVal;
475
476    curRegVal = Xil_In32(ba+RC_SLV_REG0_OFFSET);
477   
478    if(ctrlSrc == RC_CTRLSRC_HW) {
479        //Hardware control via usr_* ports enabled by 1 in reg0 ctrlSrc bits
480        newRegVal = curRegVal | (ctrlSrcMask & rfCtrlMask & RC_REG0_ALL_CTRLSRC);
481    } else {
482        //Software control via writes to reg0 (RC_REG0_TXEN, RC_REG0_RXEN, etc.)
483        newRegVal = curRegVal & (~(ctrlSrcMask & rfCtrlMask & RC_REG0_ALL_CTRLSRC));
484    }
485   
486    Xil_Out32(ba+RC_SLV_REG0_OFFSET, newRegVal);
487
488    return 0;
489}
490
491/**
492\brief Sets the final Tx VGA gain set by the Tx sequencing state machine for the selected RF interfaces
493\param ba Base memory address of radio_controller pcore
494\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
495\param gainTarget Tx VGA gain setting, in [0,63]
496\return Returns non-zero if input parameters are invalid; otherwise returns 0
497*/
498int radio_controller_setTxGainTarget(u32 ba, u32 rfSel, u8 gainTarget) {
499    //Sanity check inputs
500    if(((rfSel & RC_ANY_RF)==0))
501        return RC_INVALID_RFSEL;
502
503    u32 regVal;
504
505    regVal = Xil_In32(ba+RC_SLV_REG2_OFFSET);
506   
507    if(rfSel & RC_RFA)
508        regVal = (regVal & ~(0x0000003F)) | ((gainTarget<< 0) & 0x0000003F);
509    if(rfSel & RC_RFB)
510        regVal = (regVal & ~(0x00003F00)) | ((gainTarget<< 8) & 0x00003F00);
511    if(rfSel & RC_RFC)
512        regVal = (regVal & ~(0x003F0000)) | ((gainTarget<<16) & 0x003F0000);
513    if(rfSel & RC_RFD)
514        regVal = (regVal & ~(0x3F000000)) | ((gainTarget<<24) & 0x3F000000);
515   
516    Xil_Out32(ba+RC_SLV_REG2_OFFSET, regVal);
517
518    return 0;
519}
520
521/**
522\brief Sets the control source for Tx gains in the selected RF interfaces
523\param ba Base memory address of radio_controller pcore
524\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
525\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
526\return Returns non-zero if input parameters are invalid; otherwise returns 0
527*/
528int radio_controller_setTxGainSource(u32 ba, u32 rfSel, u8 gainSrc) {
529
530    //Sanity check inputs
531    if(((rfSel & RC_ANY_RF)==0))
532        return RC_INVALID_RFSEL;
533
534    u32 rfCtrlMask = 0;
535    u32 curRegVal, newRegVal;
536   
537    //Convert the user-supplied masks to the masks for the control registers
538    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
539    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
540    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
541    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
542
543    if(gainSrc == RC_GAINSRC_SPI) {
544        //Configure MAX2829 for Tx gain control via SPI
545        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_TXGAINS_SPI_CTRL_EN, 1);
546        return 0;
547    }
548    else if(gainSrc == RC_GAINSRC_HW) {
549        //Disable SPI Tx gain control in MAX2829
550        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_TXGAINS_SPI_CTRL_EN, 0);
551       
552        //Configure radio controller for Tx gain target from usr_ ports in logic
553        curRegVal = Xil_In32(ba+RC_SLV_REG2_OFFSET);
554        newRegVal = (curRegVal | (rfCtrlMask & RC_REG2_TXGAIN_CTRLSRC));
555        Xil_Out32(ba+RC_SLV_REG2_OFFSET, newRegVal);
556        return 0;
557    }
558    else if(gainSrc == RC_GAINSRC_REG) {
559        //Disable SPI Tx gain control in MAX2829
560        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_TXGAINS_SPI_CTRL_EN, 0);
561   
562        //Configure radio controller for Tx gain target from registers
563        curRegVal = Xil_In32(ba+RC_SLV_REG2_OFFSET);
564        newRegVal = (curRegVal & ~(rfCtrlMask & RC_REG2_TXGAIN_CTRLSRC));
565        Xil_Out32(ba+RC_SLV_REG2_OFFSET, newRegVal);
566        return 0;
567    }
568       
569    //gainSrc must have been invalid if we get here
570    return RC_INVALID_PARAM;
571}
572
573/**
574\brief Sets the control source for Rx gains in the selected RF interfaces. Note that when hardware control is selected, the corresponding
575RXHP should also be set for hardware control using radio_controller_setCtrlSource().
576\param ba Base memory address of radio_controller pcore
577\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
578\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
579\return Returns non-zero if input parameters are invalid; otherwise returns 0
580*/
581int radio_controller_setRxGainSource(u32 ba, u32 rfSel, u8 gainSrc) {
582    //Sanity check inputs
583    if(((rfSel & RC_ANY_RF)==0))
584        return RC_INVALID_RFSEL;
585
586    u32 rfCtrlMask = 0;
587    u32 curRegVal, newRegVal;
588   
589    //Convert the user-supplied masks to the masks for the control registers
590    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
591    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
592    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
593    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
594
595    if(gainSrc == RC_GAINSRC_SPI) {
596        //Configure MAX2829 for Tx gain control via SPI
597        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_RXGAINS_SPI_CTRL_EN, 1);
598        return 0;
599    }
600    else if(gainSrc == RC_GAINSRC_REG) {
601        //Disable SPI Rx gain control in MAX2829
602        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_RXGAINS_SPI_CTRL_EN, 0);
603       
604        //Configure radio controller for Rx gains from registers
605        curRegVal = Xil_In32(ba+RC_SLV_REG3_OFFSET);
606        newRegVal = (curRegVal & ~(rfCtrlMask & RC_REG3_RXGAIN_CTRLSRC));
607        Xil_Out32(ba+RC_SLV_REG3_OFFSET, newRegVal);
608        return 0;
609    }
610    else if(gainSrc == RC_GAINSRC_HW) {
611        //Disable SPI Rx gain control in MAX2829
612        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_RXGAINS_SPI_CTRL_EN, 0);
613       
614        //Configure radio controller for Tx gains from usr_ ports in logic
615        curRegVal = Xil_In32(ba+RC_SLV_REG3_OFFSET);
616        newRegVal = (curRegVal | (rfCtrlMask & RC_REG3_RXGAIN_CTRLSRC));
617        Xil_Out32(ba+RC_SLV_REG3_OFFSET, newRegVal);
618        return 0;
619    }
620       
621    //gainSrc must have been invalid if we get here
622    return RC_INVALID_PARAM;
623
624}
625
626/**
627\brief Sets a MAX2829 parameter via a SPI register write.
628\param ba Base memory address of radio_controller pcore
629\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
630\param paramID Parameter ID to update. Must be valid RC_PARAMID_* (see table below)
631\param paramVal Parameter value to set. Valid values depend on the selected parameter (see table below)
632\return Returns non-zero if input parameters are invalid; otherwise returns 0
633
634Parameter ID | Description | Parameter Values
635------------ | ----------- | ----------------
636RC_PARAMID_RXGAIN_RF | Rx RF gain value | 1: 0dB<br>2: 15dB<br>3: 30dB
637RC_PARAMID_RXGAIN_BB | Rx baseband gain value | [0,31]: approx [0,63]dB
638RC_PARAMID_TXGAIN_RF | Tx RF gain value | [0,63]: approx [0,31]dB
639RC_PARAMID_TXGAIN_BB | Tx baseband gain value | 0: 0<br>1: -1.5dB<br>2: -3dB<br>3: -5dB
640RC_PARAMID_TXLPF_BW | Tx low pass filter corner frequency<br> (Tx bandwidth is 2x corner frequency) | 1: 12MHz<br>2: 18MHz<br>3: 24MHz
641RC_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
642RC_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%
643RC_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)
644RC_PARAMID_RSSI_HIGH_BW_EN | En/disable high bandwidth RSSI signal | 0: Disable high bandwidth RSSI<br>1: Enable high bandwidth RSSI
645RC_PARAMID_TXLINEARITY_PADRIVER | Linearity of Tx PA driver circuit | [0,3]: [min,max] linearity
646RC_PARAMID_TXLINEARITY_VGA | Linearity of Tx VGA circuit | [0,3]: [min,max] linearity
647RC_PARAMID_TXLINEARITY_UPCONV | Linearity of Tx upconverter circuit | [0,3]: [min,max] linearity
648RC_PARAMID_TXGAINS_SPI_CTRL_EN |  En/disable SPI control of Tx gains | 0: Disable SPI control<br>1: Enable SPI control
649RC_PARAMID_RXGAINS_SPI_CTRL_EN |  En/disable SPI control of Rx gains | 0: Disable SPI control<br>1: Enable SPI control
650
651*/
652int radio_controller_setRadioParam(u32 ba, u32 rfSel, u32 paramID, u32 paramVal) {
653    u16 curRegData;
654    u16 newRegData;
655
656    u16 x, y;
657
658    //Sanity check inputs
659    if(((rfSel & RC_ANY_RF)==0))
660        return RC_INVALID_RFSEL;
661       
662       
663    switch(paramID) {
664#ifdef RC_INCLUDED_PARAMS_GAIN_CTRL
665        case RC_PARAMID_TXGAINS_SPI_CTRL_EN:
666            //reg9[10]: 0=B port controls Tx VGA gain, 1=SPI regC[5:0] controls Tx VGA gain
667            if(paramVal > 1) return RC_INVALID_PARAM;
668            x = paramVal ? 0x0400 : 0x0000;
669            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0400, x);
670            break;
671        case RC_PARAMID_RXGAINS_SPI_CTRL_EN:
672            //reg8[12]: 0=B port controls Rx gains, 1=SPI regB[6:0] controls Rx gains
673            if(paramVal > 1) return RC_INVALID_PARAM;
674            x = paramVal ? 0x1000 : 0x0000;
675            return radio_controller_SPI_setRegBits(ba, rfSel, 0x8, 0x1000, x);
676            break;
677        case RC_PARAMID_RXGAIN_RF:
678            //regB[6:5] sets LNA gain (but only if SPI control for Rx gains is enabled)
679            if(paramVal > 3) return RC_INVALID_PARAM;
680            x = (paramVal & 0x3)<<5;
681            return radio_controller_SPI_setRegBits(ba, rfSel, 0xB, 0x0060, x);
682        case RC_PARAMID_RXGAIN_BB:
683            //regB[4:0] sets Rx VGA gain (but only if SPI control for Rx gains is enabled)
684            if(paramVal > 31) return RC_INVALID_PARAM;
685            x = (paramVal & 0x1F);
686            return radio_controller_SPI_setRegBits(ba, rfSel, 0xB, 0x001F, x);
687            break;
688        case RC_PARAMID_TXGAIN_RF:
689            //regC[5:0] sets Tx RF VGA gain (but only if SPI control for Tx gains is enabled)
690            if(paramVal > 63) return RC_INVALID_PARAM;
691            x = (paramVal & 0x3F);
692            return radio_controller_SPI_setRegBits(ba, rfSel, 0xC, 0x003F, x);
693            break;
694        case RC_PARAMID_TXGAIN_BB:
695            //reg9[1:0] sets Tx BB gain (Tx BB gain always set via SPI)
696            if(paramVal > 3) return RC_INVALID_PARAM;
697            x = (paramVal & 0x3);
698            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0003, x);
699            break;
700#endif //RC_INCLUDED_PARAMS_GAIN_CTRL
701
702#ifdef RC_INCLUDED_PARAMS_FILTS
703        case RC_PARAMID_TXLPF_BW:
704            //reg7[6:5]: 00=undefined, 01=12MHz, 10=18MHz, 11=24MHz
705            if(paramVal == 0 || paramVal > 3) return RC_INVALID_PARAM;
706            x = (paramVal&0x3)<<5;
707            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0060, x);
708            break;
709        case RC_PARAMID_RXLPF_BW:
710            //reg7[4:3]: 00=7.5MHz, 01=9.5MHz, 10=14MHz, 11=18MHz
711            if(paramVal > 3) return RC_INVALID_PARAM;
712            x = (paramVal&0x3)<<3;
713            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0018, x);
714            break;
715        case RC_PARAMID_RXLPF_BW_FINE:
716            //reg7[2:0]: 000=90%, 001=95%, 010=100%, 011=105%, 100=110%
717            if(paramVal > 4) return RC_INVALID_PARAM;
718            x = (paramVal&0x7);
719            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0007, x);
720            break;
721        case RC_PARAMID_RXHPF_HIGH_CUTOFF_EN:
722            //reg8[2]: HPF corner freq when RxHP=0; 0=100Hz, 1=30kHz
723            if(paramVal > 1) return RC_INVALID_PARAM;
724            x = paramVal ? 0x0004 : 0x0000;
725            return radio_controller_SPI_setRegBits(ba, rfSel, 0x8, 0x0004, x);
726            break;
727#endif //RC_INCLUDED_PARAMS_FILTS
728
729#ifdef RC_INCLUDED_PARAMS_MISC
730        case RC_PARAMID_RSSI_HIGH_BW_EN:
731            //reg7[11]: 0=2MHz RSSI BW, 1=6MHZ RSSI BW
732            if(paramVal > 1) return RC_INVALID_PARAM;
733            x = paramVal ? 0x0800 : 0x0000;
734            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0800, x);
735            break;
736        case RC_PARAMID_TXLINEARITY_PADRIVER:
737            //reg9[9:8]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
738            if(paramVal > 3) return RC_INVALID_PARAM;
739            x = (paramVal&0x3)<<8;
740            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0300, x);
741            break;
742        case RC_PARAMID_TXLINEARITY_VGA:
743            //reg9[7:6]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
744            if(paramVal > 3) return RC_INVALID_PARAM;
745            x = (paramVal&0x3)<<6;
746            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x00C0, x);
747            break;
748        case RC_PARAMID_TXLINEARITY_UPCONV:
749            //reg9[3:2]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
750            if(paramVal > 3) return RC_INVALID_PARAM;
751            x = (paramVal&0x3)<<2;
752            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x000C, x);
753            break;
754#endif //RC_INCLUDED_PARAMS_MISC
755        default:
756            //Either no paramters were #ifdef'd in, or user supplied invalid paramID
757            return RC_INVALID_PARAMID;
758            break;
759    }
760
761    return 0;
762}
763
764/**
765\brief Reads the TxDCO calibration values from the EEPROM and writes the values to the DACs of the selected RF interface. This function
766requires the w3_iic_eeprom and w3_ad_controller cores.
767\param ad_ba Base memory address of w3_ad_controller core
768\param iic_ba Base memory address of w3_iic_eeprom core
769\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
770\return Returns non-zero if w3_ad_controller or w3_iic_eeprom core is not found; otherwise returns 0
771*/
772int radio_controller_apply_TxDCO_calibration(u32 ad_ba, u32 iic_ba, u32 rfSel) {
773#if defined XPAR_W3_IIC_EEPROM_NUM_INSTANCES && defined XPAR_W3_AD_CONTROLLER_NUM_INSTANCES
774    u16 rI, rQ;
775    u32 ad_sel = 0;
776   
777    if(rfSel & RC_RFA)
778        ad_sel |= RFA_AD_CS;
779    if(rfSel & RC_RFB)
780        ad_sel |= RFB_AD_CS;
781    if(rfSel & RC_RFC)
782        ad_sel |= RFC_AD_CS;
783    if(rfSel & RC_RFD)
784        ad_sel |= RFD_AD_CS;
785   
786    //For each radio interface specified by rfSel:
787    // -Read the I/Q TxDCO calibration values from the EEPROM (two u16 values)
788    // -Apply the TxDCO calibration values via the ad_controller driver
789    //The RC_EEPROM_TXDCO_ADDR_RFx_x macros are defined in radio_controller.h
790    //The on-board RF interfaces use the on-board EEPROM
791    //FMC RF interfaces use the EEPROM on the FMC module
792    //On-board RFA/RFB use the same EEPROM byte addresses as FMC RFC/RFD, respectively
793    //User code must supply the correct IIC controller base address when calling this function
794    if(rfSel & (RC_RFA | RC_RFC)) {
795        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);
796        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);
797   
798        ad_set_TxDCO(ad_ba, (ad_sel & (RFA_AD_CS | RFC_AD_CS)), AD_CHAN_I, rI);
799        ad_set_TxDCO(ad_ba, (ad_sel & (RFA_AD_CS | RFC_AD_CS)), AD_CHAN_Q, rQ);
800    }
801    if(rfSel & (RC_RFB | RC_RFD)) {
802        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);
803        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);
804   
805        ad_set_TxDCO(ad_ba, (ad_sel & (RFB_AD_CS | RFD_AD_CS)), AD_CHAN_I, rI);
806        ad_set_TxDCO(ad_ba, (ad_sel & (RFB_AD_CS | RFD_AD_CS)), AD_CHAN_Q, rQ);
807    }
808   
809    return 0;
810#else
811    print("w3_iic_eeprom or w3_ad_controller pcores are missing! Cannot apply TxDCO correction\n");
812    return -1;
813#endif
814}
815
816
817/**
818\brief Simple pseudo-usleep implementation (since MicroBlaze lacks internal timer for native usleep implementation).
819The actual sleep time is not guaranteed to be d microseconds.
820\param d Number of "microseconds" to sleep (proportional to sleep time; actual sleep time will depend on processor and instruction memory clocks)
821*/
822void rc_usleep(int d) {
823    volatile int i;
824    for(i=0; i<d*4; i++) { /* do nothing */}
825    return;
826}
827
828/** @}*/ //END group user_functions
Note: See TracBrowser for help on using the repository browser.