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

Last change on this file was 4519, checked in by murphpo, 9 years ago

fixed register bit mask for RC_PARAMID_RXHPF_HIGH_CUTOFF_EN

File size: 35.2 KB
Line 
1/*****************************************************************
2* File: radio_controller.c
3* Copyright (c) 2013 Mango Communications, all rights reseved
4* Released under the WARP License
5* See http://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 and digital I/O
12for controlling the MAX2829 and AD9777 ICs on the WARP Radio Board v1.4
13
14@version 2.00.a
15@author Patrick Murphy
16@copyright (c) 2013 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#include "radio_controller.h"
24#include "xparameters.h"
25
26#if defined XPAR_EEPROM_ONEWIRE_NUM_INSTANCES
27#include "EEPROM.h"
28#endif
29
30static u16 rc_tuningParams_24GHz_freqs[14] = { 2412,   2417,   2422,   2427,   2432,   2437,   2442,   2447,   2452,   2457,   2462,   2467,   2472,   2484};
31static u16 rc_tuningParams_24GHz_reg3[14] = {0x00A0, 0x20A1, 0x30A1, 0x00A1, 0x20A2, 0x30A2, 0x00A2, 0x20A3, 0x30A3, 0x00A3, 0x20A4, 0x30A4, 0x00A4, 0x10A5};
32static u16 rc_tuningParams_24GHz_reg4[14] = {0x3333, 0x0888, 0x1DDD, 0x3333, 0x0888, 0x1DDD, 0x3333, 0x0888, 0x1DDD, 0x3333, 0x0888, 0x1DDD, 0x3333, 0x2666};
33
34static 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};
35static 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}; 
36static 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};
37
38/**
39\defgroup user_functions Functions
40\brief Functions to call from user code
41\addtogroup user_functions
42
43Example:
44\code{.c}
45//Assumes user code sets RC_BASEADDR to base address of radio_controller core, as set in xparameters.h
46
47//Initialize the radio controller logic
48radio_controller_init(RC_CONTROLLER, 1, 1);
49
50\endcode
51
52@{
53*/
54
55/**
56\brief Initializes the radio controller core and the selected MAX2829 transceivers. The selected transceivers
57are reset, configured with sane defaults and set to the Standby state. User code should call this function once
58at boot for all RF interfaces.
59\param ba Base memory address of radio_controller pcore
60\param rfSel Selects RF interface to initialize (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
61\param clkDiv_SPI Clock divider for SPI serial clock (set to 3 for 160MHz bus)
62\param clkDiv_TxDelays Clock divider for Tx sequencing state machine (set to 1 for normal operation)
63\return Returns -1 if any MAX2829 indicates no PLL lock after init; otherwise returns 0
64*/
65int radio_controller_init(u32 ba, u32 rfSel, u8 clkDiv_SPI, u8 clkDiv_TxDelays) {
66
67    //Sanity check arguments
68    if(((rfSel & RC_ANY_RF)==0) || (clkDiv_SPI>7) || (clkDiv_TxDelays>3))
69        return RC_INVALID_PARAM;
70
71    //Radio controller init procedure:
72    // -Set clock dividers for DAC & MAX2829 SPI and TxTiming state machines
73    // -Reset AD7777 DAC, then configure for single ref resistor mode
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    //Set sane defaults for ADC and DAC control lines
87    // RSSI: CLAMP, SLEEP, HIZ all off
88    // Rx ADC: DCS on (recommended for Fs>40MHz), DFS on (for 2's complement)
89    Xil_Out32(ba+RC_SLV_REG8_OFFSET, (RC_REG8_MASK_RXADC_DFS | RC_REG8_MASK_RXADC_DCS));
90   
91    //Initialize the AD9777 DACs
92
93    // Max SPI_CLK is 15MHz; be conservative here (negligible overhead for 1 register write)
94    radio_controller_setClkDiv_DAC_SPI(ba, 3);
95   
96    //Toggle DAC resets
97    Xil_Out32(ba+RC_SLV_REG8_OFFSET, Xil_In32(ba+RC_SLV_REG8_OFFSET) | RC_REG8_MASK_DAC_RESET);
98    Xil_Out32(ba+RC_SLV_REG8_OFFSET, Xil_In32(ba+RC_SLV_REG8_OFFSET) & (~RC_REG8_MASK_DAC_RESET));
99
100    //Set 1R mode (reg[0] = 0x4)
101    radio_controller_DAC_SPI_write(ba, RC_REG6_DACSEL_ALL, 0x0, 0x4);
102   
103    //Initialize MAX2829 transceivers
104    radio_controller_setClkDiv_SPI(ba, clkDiv_SPI);
105    radio_controller_setClkDiv_TxDelays(ba, clkDiv_TxDelays);
106
107    //Convert the user-supplied masks to the masks for the control registers
108    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
109    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
110    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
111    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
112
113    radio_controller_setMode_shutdown(ba, rfCtrlMask);
114    radio_controller_setMode_reset(ba, rfCtrlMask);
115    usleep(1000);
116    radio_controller_setMode_shutdown(ba, rfCtrlMask);
117    usleep(1000);
118   
119    //MAX2829 reg2:
120    // -MIMO mode (reg2[13]=1)
121    // -Other bits set to defaults
122    radio_controller_SPI_write(ba, rfSel, 2, 0x3007);
123   
124    //MAX2829 reg5:
125    // -20MHz reference clock (reg5[3:1]=[0 0 1] (was -40MHz reference clock (reg5[3:1]=[0 1 0]))
126    // -MIMO mode (reg5[13]=1)
127    // -Other bits set to defaults
128    radio_controller_SPI_write(ba, rfSel, 5, 0x3822);
129
130    //MAX2829 reg8:
131    // -RSSI output in [0.5,2.5]v (reg8[11]=1)
132    // -RSSI output always on in Rx mode (reg8[10]=1)
133    // -Other bits set to defaults
134    radio_controller_SPI_write(ba, rfSel, 8, 0x0C25);
135   
136    //MAX2829 reg9:
137    // -Max linearity for Tx PA driver (reg9[9:8]=[1 1]
138    // -Max linearity for Tx VGA (reg9[7:6]=[1 1])
139    // -Max linearity for upconverter (reg9[3:2]=[1 1])
140    // -Tx baseband gain set to (max-3dB) (reg9[1:0]=[1 0])
141    radio_controller_SPI_write(ba, rfSel, 9, 0x03CD);
142
143
144    //Finally bring the MAX2829 out of shutdown
145    // The PLL should lock (LD -> 1) shortly after this call
146    radio_controller_setMode_standby(ba, rfCtrlMask);
147
148    pll_lock_status = 0;
149   
150    while(pll_lock_status != (RC_REG11_LD & rfCtrlMask)) {
151        usleep(10000);
152        pll_lock_status = Xil_In32(ba + RC_SLV_REG11_OFFSET) & RC_REG11_LD & rfCtrlMask;
153        pll_lock_wait_tries++;
154        if(pll_lock_wait_tries > 1000) {
155            xil_printf("Radios didn't lock! RC stat reg: 0x%08x\n", Xil_In32(ba + RC_SLV_REG11_OFFSET));
156            return -1;
157        }
158    }
159//  xil_printf("Radios locked after %d tries\n", pll_lock_wait_tries);
160
161
162    //Set sane defaults
163    radio_controller_setTxDelays(ba, 150, 0, 0, 250);
164    radio_controller_setTxGainTiming(ba, 0xF, 3);
165
166    return 0;
167}
168
169/**
170\brief Sets the selected RF interfaces to the Transmit state. The corresponding MAX2829s, PAs and RF switches are all
171set to the correct state for transmission. This call initiates the Tx sequencing state machine. Refer to the
172<a href="http://warp.rice.edu/trac/wiki/cores/radio_controller">radio_controller user guide</a> for more details.
173\param ba Base memory address of radio_controller pcore
174\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
175\return Returns non-zero value if an input parameter was invalid; else returns 0
176*/
177int radio_controller_TxEnable(u32 ba, u32 rfSel) {
178
179    u32 rfCtrlMask, oldVal, newVal;
180
181    if((rfSel & RC_ANY_RF)==0)
182        return RC_INVALID_RFSEL;
183
184    rfCtrlMask = 0;
185       
186    //Convert the user-supplied masks to the masks for the control registers
187    if(rfSel & RC_RFA) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFA;
188    if(rfSel & RC_RFB) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFB;
189    if(rfSel & RC_RFC) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFC;
190    if(rfSel & RC_RFD) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFD;
191
192    oldVal = Xil_In32(ba + RC_SLV_REG0_OFFSET);
193   
194    //Force RxEn=0, SHDN=1 for radios selected by rfsel
195    oldVal = (oldVal & (~(rfCtrlMask & RC_REG0_RXEN))) | (rfCtrlMask & RC_REG0_SHDN);
196   
197    newVal = oldVal | (rfCtrlMask & RC_REG0_TXEN);
198   
199    Xil_Out32(ba + RC_SLV_REG0_OFFSET, newVal);
200   
201//  radio_controller_setMode_standby(ba, rfCtrlMask);
202//  radio_controller_setMode_Tx(ba, rfCtrlMask);
203
204    return 0;
205}
206
207/**
208\brief Sets the selected RF interfaces to the Receive state. The corresponding MAX2829s and RF switches are
209set to the correct state for reception. The PAs in the selected RF interfaces are disabled.
210\param ba Base memory address of radio_controller pcore
211\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
212\return Returns non-zero value if an input parameter was invalid; else returns 0
213*/
214int radio_controller_RxEnable(u32 ba, u32 rfSel) {
215
216    u32 rfCtrlMask, oldVal, newVal;;
217
218    if((rfSel & RC_ANY_RF)==0)
219        return RC_INVALID_RFSEL;
220       
221    rfCtrlMask = 0;
222       
223    //Convert the user-supplied masks to the masks for the control registers
224    if(rfSel & RC_RFA) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFA;
225    if(rfSel & RC_RFB) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFB;
226    if(rfSel & RC_RFC) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFC;
227    if(rfSel & RC_RFD) rfCtrlMask = rfCtrlMask | RC_CTRLREGMASK_RFD;
228
229    oldVal = Xil_In32(ba + RC_SLV_REG0_OFFSET);
230   
231    //Force TxEn=0, SHDN=1 for radios selected by rfsel
232    oldVal = (oldVal & (~(rfCtrlMask & RC_REG0_TXEN))) | (rfCtrlMask & RC_REG0_SHDN);
233   
234    newVal = oldVal | (rfCtrlMask & RC_REG0_RXEN);
235   
236    Xil_Out32(ba + RC_SLV_REG0_OFFSET, newVal);
237
238//  radio_controller_setMode_standby(ba, rfCtrlMask);
239//  radio_controller_setMode_Rx(ba, rfCtrlMask);
240
241    return 0;
242}
243
244/**
245\brief Sets the selected RF interfaces to the Standby state (Tx and Rx disabled). The corresponding MAX2829s and PAs are
246set to the correct state for standby.
247\param ba Base memory address of radio_controller pcore
248\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
249\return Returns non-zero value if an input parameter was invalid; else returns 0
250*/
251int radio_controller_TxRxDisable(u32 ba, u32 rfSel) {
252
253    u32 rfCtrlMask = 0;
254
255    if((rfSel & RC_ANY_RF)==0)
256        return RC_INVALID_RFSEL;
257       
258    //Convert the user-supplied masks to the masks for the control registers
259    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
260    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
261    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
262    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
263
264    radio_controller_setMode_standby(ba, rfCtrlMask);
265
266    return 0;
267}
268
269/**
270\brief Sets the selected RF interfaces to the Standby state (Tx and Rx disabled). The corresponding MAX2829s and PAs are
271set to the correct state for standby.
272\param ba Base memory address of radio_controller pcore
273\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
274\param bandSel Selects the 2.4GHz or 5GHz band; must be RC_24GHZ or RC_5GHZ
275\param chanNum New center frequency channel number, in [1,14] for 2.4GHz or [1,23] for 5GHz. The channel numbers
276and corresponding center frequencies are listed in the table below.
277\return Returns non-zero value if an input parameter was invalid; else returns 0
278
2792.4GHz <br> Chan | Freq <br> (MHz) | | 5GHz <br> Chan | Freq <br> (MHz)
280--- | ----- | - | --- | -----
2811 | 2412 |  | 1 | 5180
2822 | 2417 |  | 2 | 5200
2833 | 2422 |  | 3 | 5220
2844 | 2427 |  | 4 | 5240
2855 | 2432 |  | 5 | 5260
2866 | 2437 |  | 6 | 5280
2877 | 2442 |  | 7 | 5300
2888 | 2447 |  | 8 | 5320
2899 | 2452 |  | 9 | 5500
29010 | 2457 |  | 10 | 5520
29111 | 2462 |  | 11 | 5540
29212 | 2467 |  | 12 | 5560
29313 | 2472 |  | 13 | 5580
29414 | 2484 |  | 14 | 5600
295- | - | | 15 | 5620
296- | - | | 16 | 5640
297- | - | | 17 | 5660
298- | - | | 18 | 5680
299- | - | | 19 | 5700
300- | - | | 20 | 5745
301- | - | | 21 | 5765
302- | - | | 22 | 5785
303- | - | | 23 | 5805
304*/
305int radio_controller_setCenterFrequency(u32 ba, u32 rfSel, u8 bandSel, u8 chanNum) {
306
307    if((bandSel == RC_24GHZ) && (chanNum >= 1) && (chanNum <= 14) && (rfSel & RC_ANY_RF)){ //14 valid 2.4GHz channels
308        //MAX2829 tuning process for 2.4GHz channels:
309        // -Set reg5[0] to 0 (selects 2.4GHz)
310        // -Set reg3, reg4 with PLL tuning params
311
312        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x1, 0x0);
313
314        //Write the PLL parameters
315        radio_controller_SPI_write(ba, rfSel, 3, rc_tuningParams_24GHz_reg3[chanNum-1]);
316        radio_controller_SPI_write(ba, rfSel, 4, rc_tuningParams_24GHz_reg4[chanNum-1]);
317
318        return(rc_tuningParams_24GHz_freqs[chanNum-1]);
319    }
320
321    if((bandSel == RC_5GHZ) && (chanNum >= 1) && (chanNum <= 23) && (rfSel & RC_ANY_RF)) { //23 valid 5GHz channels
322        //MAX2829 tuning process for 5GHz channels:
323        //(Assumes default config of 5GHz sub-band tuning via FSM; see MAX2829 datasheet for details)
324        // -Set:
325        //   -reg5[0] to 1 (selects 5GHz)
326        //   -reg5[6] based on selected freq (0:4.9-5.35GHz, 1:5.47-5.875GHz)
327        // -Set reg3, reg4 with PLL tuning params
328
329        if(chanNum<=8)
330            radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x41, 0x01);
331        else
332            radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x41, 0x41);
333
334        //Reset the band select FSM
335        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x80, 0x00);
336       
337        //Write the PLL parameters
338        radio_controller_SPI_write(ba, rfSel, 3, rc_tuningParams_5GHz_reg3[chanNum-1]);
339        radio_controller_SPI_write(ba, rfSel, 4, rc_tuningParams_5GHz_reg4[chanNum-1]);
340
341        //Start the band select FSM
342        radio_controller_SPI_setRegBits(ba, rfSel, 5, 0x80, 0x80);
343
344        return(rc_tuningParams_5GHz_freqs[chanNum-1]);
345    }
346   
347    //Some input param was invalid if we get here, so return an invalid frequency
348    return RC_INVALID_PARAM;
349}
350
351/**
352\brief Reads the radio controller "mirror" register corresponding to the MAX2829 register at regAddr
353\param ba Base memory address of radio_controller pcore
354\param rfSel Selects RF interface to read (must be one of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
355\param regAddr Register address to read, in [0x0,0xC]
356\return Returns 255 if input parameters are invalid; otherwise returns 14-bit register value
357*/
358u16 radio_controller_SPI_read(u32 ba, u32 rfSel, u8 regAddr) {
359    if(((rfSel & RC_ANY_RF)==0) || (regAddr>0xC))
360        return 255; //impossible value for 14-bit registers; use for error checking
361
362    //Use Xil_In32 to grab 16LSB of each register (Xil_In16 reads 16MSB of 32-bit register when address is aligned to 4 bytes)
363    if(rfSel & RC_RFA)
364        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFA_BASEADDR + 4*regAddr));
365
366    if(rfSel & RC_RFB)
367        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFB_BASEADDR + 4*regAddr));
368
369    if(rfSel & RC_RFC)
370        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFC_BASEADDR + 4*regAddr));
371
372    if(rfSel & RC_RFD)
373        return (u16)(0xFFFF & Xil_In32(ba + RC_SPI_MIRRORREGS_RFD_BASEADDR + 4*regAddr));
374
375    //Can't get here, but return error anyway so compiler doesn't complain
376    return 254;
377}
378
379/**
380\brief Sets specific bits in a single register in selected MAX2829s
381\param ba Base memory address of radio_controller pcore
382\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
383\param regAddr Register address to write, in [0x0,0xC]
384\param regDataMask 14-bit mask of bits to affect (1 in mask selects bit for writing)
385\param regData 14-bit value to set; only bits with 1 in regDataMask are used
386\return Returns non-zero if input parameters are invalid; otherwise returns 0
387*/
388int radio_controller_SPI_setRegBits(u32 ba, u32 rfSel, u8 regAddr, u16 regDataMask, u16 regData) {
389    u16 curRegData;
390    u16 newRegData;
391   
392    if(((rfSel & RC_ANY_RF)==0) || (regAddr>13))
393        return RC_INVALID_RFSEL;
394
395    if(rfSel & RC_RFA) {
396        curRegData = radio_controller_SPI_read(ba, RC_RFA, regAddr);
397        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
398        radio_controller_SPI_write(ba, RC_RFA, regAddr, newRegData);
399    }
400    if(rfSel & RC_RFB) {
401        curRegData = radio_controller_SPI_read(ba, RC_RFB, regAddr);
402        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
403        radio_controller_SPI_write(ba, RC_RFB, regAddr, newRegData);
404    }
405    if(rfSel & RC_RFC) {
406        curRegData = radio_controller_SPI_read(ba, RC_RFC, regAddr);
407        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
408        radio_controller_SPI_write(ba, RC_RFC, regAddr, newRegData);
409    }
410    if(rfSel & RC_RFD) {
411        curRegData = radio_controller_SPI_read(ba, RC_RFD, regAddr);
412        newRegData = ((curRegData & ~regDataMask) | (regData & regDataMask));
413        radio_controller_SPI_write(ba, RC_RFD, regAddr, newRegData);
414    }
415
416    return 0;   
417}
418
419/**
420\brief Sets state of RXHP pin on selected MAX2829s. This function only affects state if the RXHP control
421source is set to software on the selected RF interfaces.
422\param ba Base memory address of radio_controller pcore
423\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
424\param mode RXHP is asserted if mode=RC_RXHP_ON, else RXHP is deasserted
425\return Returns non-zero if input parameters are invalid; otherwise returns 0
426*/
427int radio_controller_setRxHP(u32 ba, u32 rfSel, u8 mode) {
428    //Sanity check inputs
429    if((rfSel & RC_ANY_RF) == 0)
430        return RC_INVALID_RFSEL;
431
432    if(mode > 1)
433        return RC_INVALID_PARAM;
434
435    u32 rfCtrlMask = 0;
436   
437    //Convert the user-supplied masks to the masks for the control registers
438    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
439    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
440    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
441    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
442
443    u32 curRegVal, newRegVal;
444
445    curRegVal = Xil_In32(ba+RC_SLV_REG0_OFFSET);
446   
447    if(mode == RC_RXHP_ON) {
448        //Assert RxHP bits in reg0; drives 1 to corresponding RxHP pin on MAX2829
449        newRegVal = curRegVal | (RC_REG0_RXHP & rfCtrlMask);
450    } else {
451        newRegVal = curRegVal & (~(RC_REG0_RXHP & rfCtrlMask));
452    }
453   
454    Xil_Out32(ba+RC_SLV_REG0_OFFSET, newRegVal);
455
456    return 0;
457}
458
459/**
460\brief Selects between register or hardware control for the various radio control signals on the selected RF interfaces.
461\param ba Base memory address of radio_controller pcore
462\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
463\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]
464\param ctrlSrc Selects register (from C code) or hardware (usr_ ports) control; must be RC_CTRLSRC_REG or RC_CTRLSRC_HW
465\return Returns non-zero if input parameters are invalid; otherwise returns 0
466*/
467int radio_controller_setCtrlSource(u32 ba, u32 rfSel, u32 ctrlSrcMask, u8 ctrlSrc) {
468
469    //Sanity check inputs
470    if((rfSel & RC_ANY_RF) == 0)
471        return RC_INVALID_RFSEL;
472
473    if((ctrlSrcMask & RC_REG0_ALL_CTRLSRC) == 0)
474        return RC_INVALID_PARAM;
475
476    u32 rfCtrlMask = 0;
477   
478    //Convert the user-supplied masks to the masks for the control registers
479    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
480    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
481    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
482    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
483
484    u32 curRegVal, newRegVal;
485
486    curRegVal = Xil_In32(ba+RC_SLV_REG0_OFFSET);
487   
488    if(ctrlSrc == RC_CTRLSRC_HW) {
489        //Hardware control via usr_* ports enabled by 1 in reg0 ctrlSrc bits
490        newRegVal = curRegVal | (ctrlSrcMask & rfCtrlMask & RC_REG0_ALL_CTRLSRC);
491    } else {
492        //Software control via writes to reg0 (RC_REG0_TXEN, RC_REG0_RXEN, etc.)
493        newRegVal = curRegVal & (~(ctrlSrcMask & rfCtrlMask & RC_REG0_ALL_CTRLSRC));
494    }
495   
496    Xil_Out32(ba+RC_SLV_REG0_OFFSET, newRegVal);
497
498    return 0;
499}
500
501/**
502\brief Sets the final Tx VGA gain set by the Tx sequencing state machine for the selected RF interfaces
503\param ba Base memory address of radio_controller pcore
504\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
505\param gainTarget Tx VGA gain setting, in [0,63]
506\return Returns non-zero if input parameters are invalid; otherwise returns 0
507*/
508int radio_controller_setTxGainTarget(u32 ba, u32 rfSel, u8 gainTarget) {
509    //Sanity check inputs
510    if(((rfSel & RC_ANY_RF)==0))
511        return RC_INVALID_RFSEL;
512
513    u32 regVal;
514
515    regVal = Xil_In32(ba+RC_SLV_REG2_OFFSET);
516   
517    if(rfSel & RC_RFA)
518        regVal = (regVal & ~(0x0000003F)) | ((gainTarget<< 0) & 0x0000003F);
519    if(rfSel & RC_RFB)
520        regVal = (regVal & ~(0x00003F00)) | ((gainTarget<< 8) & 0x00003F00);
521    if(rfSel & RC_RFC)
522        regVal = (regVal & ~(0x003F0000)) | ((gainTarget<<16) & 0x003F0000);
523    if(rfSel & RC_RFD)
524        regVal = (regVal & ~(0x3F000000)) | ((gainTarget<<24) & 0x3F000000);
525   
526    Xil_Out32(ba+RC_SLV_REG2_OFFSET, regVal);
527
528    return 0;
529}
530
531/**
532\brief Sets the control source for Tx gains in the selected RF interfaces
533\param ba Base memory address of radio_controller pcore
534\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
535\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
536\return Returns non-zero if input parameters are invalid; otherwise returns 0
537*/
538int radio_controller_setTxGainSource(u32 ba, u32 rfSel, u8 gainSrc) {
539
540    //Sanity check inputs
541    if(((rfSel & RC_ANY_RF)==0))
542        return RC_INVALID_RFSEL;
543
544    u32 rfCtrlMask = 0;
545    u32 curRegVal, newRegVal;
546   
547    //Convert the user-supplied masks to the masks for the control registers
548    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
549    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
550    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
551    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
552
553    if(gainSrc == RC_GAINSRC_SPI) {
554        //Configure MAX2829 for Tx gain control via SPI
555        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_TXGAINS_SPI_CTRL_EN, 1);
556        return 0;
557    }
558    else if(gainSrc == RC_GAINSRC_HW) {
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 usr_ ports in logic
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    else if(gainSrc == RC_GAINSRC_REG) {
569        //Disable SPI Tx gain control in MAX2829
570        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_TXGAINS_SPI_CTRL_EN, 0);
571   
572        //Configure radio controller for Tx gain target from registers
573        curRegVal = Xil_In32(ba+RC_SLV_REG2_OFFSET);
574        newRegVal = (curRegVal & ~(rfCtrlMask & RC_REG2_TXGAIN_CTRLSRC));
575        Xil_Out32(ba+RC_SLV_REG2_OFFSET, newRegVal);
576        return 0;
577    }
578       
579    //gainSrc must have been invalid if we get here
580    return RC_INVALID_PARAM;
581}
582
583/**
584\brief Sets the control source for Rx gains in the selected RF interfaces. Note that when hardware control is selected, the corresponding
585RXHP should also be set for hardware control using radio_controller_setCtrlSource().
586\param ba Base memory address of radio_controller pcore
587\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
588\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
589\return Returns non-zero if input parameters are invalid; otherwise returns 0
590*/
591int radio_controller_setRxGainSource(u32 ba, u32 rfSel, u8 gainSrc) {
592    //Sanity check inputs
593    if(((rfSel & RC_ANY_RF)==0))
594        return RC_INVALID_RFSEL;
595
596    u32 rfCtrlMask = 0;
597    u32 curRegVal, newRegVal;
598   
599    //Convert the user-supplied masks to the masks for the control registers
600    if(rfSel & RC_RFA) rfCtrlMask |= RC_CTRLREGMASK_RFA;
601    if(rfSel & RC_RFB) rfCtrlMask |= RC_CTRLREGMASK_RFB;
602    if(rfSel & RC_RFC) rfCtrlMask |= RC_CTRLREGMASK_RFC;
603    if(rfSel & RC_RFD) rfCtrlMask |= RC_CTRLREGMASK_RFD;
604
605    if(gainSrc == RC_GAINSRC_SPI) {
606        //Configure MAX2829 for Tx gain control via SPI
607        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_RXGAINS_SPI_CTRL_EN, 1);
608        return 0;
609    }
610    else if(gainSrc == RC_GAINSRC_REG) {
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 Rx gains from registers
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    else if(gainSrc == RC_GAINSRC_HW) {
621        //Disable SPI Rx gain control in MAX2829
622        radio_controller_setRadioParam(ba, rfSel, RC_PARAMID_RXGAINS_SPI_CTRL_EN, 0);
623       
624        //Configure radio controller for Tx gains from usr_ ports in logic
625        curRegVal = Xil_In32(ba+RC_SLV_REG3_OFFSET);
626        newRegVal = (curRegVal | (rfCtrlMask & RC_REG3_RXGAIN_CTRLSRC));
627        Xil_Out32(ba+RC_SLV_REG3_OFFSET, newRegVal);
628        return 0;
629    }
630       
631    //gainSrc must have been invalid if we get here
632    return RC_INVALID_PARAM;
633
634}
635
636/**
637\brief Sets a MAX2829 parameter via a SPI register write.
638\param ba Base memory address of radio_controller pcore
639\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
640\param paramID Parameter ID to update. Must be valid RC_PARAMID_* (see table below)
641\param paramVal Parameter value to set. Valid values depend on the selected parameter (see table below)
642\return Returns non-zero if input parameters are invalid; otherwise returns 0
643
644Parameter ID | Description | Parameter Values
645------------ | ----------- | ----------------
646RC_PARAMID_RXGAIN_RF | Rx RF gain value | 1: 0dB<br>2: 15dB<br>3: 30dB
647RC_PARAMID_RXGAIN_BB | Rx baseband gain value | [0,31]: approx [0,63]dB
648RC_PARAMID_TXGAIN_RF | Tx RF gain value | [0,63]: approx [0,31]dB
649RC_PARAMID_TXGAIN_BB | Tx baseband gain value | 0: 0<br>1: -1.5dB<br>2: -3dB<br>3: -5dB
650RC_PARAMID_TXLPF_BW | Tx low pass filter corner frequency<br> (Tx bandwidth is 2x corner frequency) | 1: 12MHz<br>2: 18MHz<br>3: 24MHz
651RC_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
652RC_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%
653RC_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)
654RC_PARAMID_RSSI_HIGH_BW_EN | En/disable high bandwidth RSSI signal | 0: Disable high bandwidth RSSI<br>1: Enable high bandwidth RSSI
655RC_PARAMID_TXLINEARITY_PADRIVER | Linearity of Tx PA driver circuit | [0,3]: [min,max] linearity
656RC_PARAMID_TXLINEARITY_VGA | Linearity of Tx VGA circuit | [0,3]: [min,max] linearity
657RC_PARAMID_TXLINEARITY_UPCONV | Linearity of Tx upconverter circuit | [0,3]: [min,max] linearity
658RC_PARAMID_TXGAINS_SPI_CTRL_EN |  En/disable SPI control of Tx gains | 0: Disable SPI control<br>1: Enable SPI control
659RC_PARAMID_RXGAINS_SPI_CTRL_EN |  En/disable SPI control of Rx gains | 0: Disable SPI control<br>1: Enable SPI control
660
661*/
662int radio_controller_setRadioParam(u32 ba, u32 rfSel, u32 paramID, u32 paramVal) {
663    u16 curRegData;
664    u16 newRegData;
665
666    u16 x, y;
667
668    //Sanity check inputs
669    if(((rfSel & RC_ANY_RF)==0))
670        return RC_INVALID_RFSEL;
671       
672       
673    switch(paramID) {
674#ifdef RC_INCLUDED_PARAMS_GAIN_CTRL
675        case RC_PARAMID_TXGAINS_SPI_CTRL_EN:
676            //reg9[10]: 0=B port controls Tx VGA gain, 1=SPI regC[5:0] controls Tx VGA gain
677            if(paramVal > 1) return RC_INVALID_PARAM;
678            x = paramVal ? 0x0400 : 0x0000;
679            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0400, x);
680            break;
681        case RC_PARAMID_RXGAINS_SPI_CTRL_EN:
682            //reg8[12]: 0=B port controls Rx gains, 1=SPI regB[6:0] controls Rx gains
683            if(paramVal > 1) return RC_INVALID_PARAM;
684            x = paramVal ? 0x1000 : 0x0000;
685            return radio_controller_SPI_setRegBits(ba, rfSel, 0x8, 0x1000, x);
686            break;
687        case RC_PARAMID_RXGAIN_RF:
688            //regB[6:5] sets LNA gain (but only if SPI control for Rx gains is enabled)
689            if(paramVal > 3) return RC_INVALID_PARAM;
690            x = (paramVal & 0x3)<<5;
691            return radio_controller_SPI_setRegBits(ba, rfSel, 0xB, 0x0060, x);
692        case RC_PARAMID_RXGAIN_BB:
693            //regB[4:0] sets Rx VGA gain (but only if SPI control for Rx gains is enabled)
694            if(paramVal > 31) return RC_INVALID_PARAM;
695            x = (paramVal & 0x1F);
696            return radio_controller_SPI_setRegBits(ba, rfSel, 0xB, 0x001F, x);
697            break;
698        case RC_PARAMID_TXGAIN_RF:
699            //regC[5:0] sets Tx RF VGA gain (but only if SPI control for Tx gains is enabled)
700            if(paramVal > 63) return RC_INVALID_PARAM;
701            x = (paramVal & 0x3F);
702            return radio_controller_SPI_setRegBits(ba, rfSel, 0xC, 0x003F, x);
703            break;
704        case RC_PARAMID_TXGAIN_BB:
705            //reg9[1:0] sets Tx BB gain (Tx BB gain always set via SPI)
706            if(paramVal > 3) return RC_INVALID_PARAM;
707            x = (paramVal & 0x3);
708            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0003, x);
709            break;
710#endif //RC_INCLUDED_PARAMS_GAIN_CTRL
711
712#ifdef RC_INCLUDED_PARAMS_FILTS
713        case RC_PARAMID_TXLPF_BW:
714            //reg7[6:5]: 00=undefined, 01=12MHz, 10=18MHz, 11=24MHz
715            if(paramVal == 0 || paramVal > 3) return RC_INVALID_PARAM;
716            x = (paramVal&0x3)<<5;
717            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0060, x);
718            break;
719        case RC_PARAMID_RXLPF_BW:
720            //reg7[4:3]: 00=7.5MHz, 01=9.5MHz, 10=14MHz, 11=18MHz
721            if(paramVal > 3) return RC_INVALID_PARAM;
722            x = (paramVal&0x3)<<3;
723            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0018, x);
724            break;
725        case RC_PARAMID_RXLPF_BW_FINE:
726            //reg7[2:0]: 000=90%, 001=95%, 010=100%, 011=105%, 100=110%
727            if(paramVal > 4) return RC_INVALID_PARAM;
728            x = (paramVal&0x7);
729            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0007, x);
730            break;
731        case RC_PARAMID_RXHPF_HIGH_CUTOFF_EN:
732            //reg8[2]: HPF corner freq when RxHP=0; 0=100Hz, 1=30kHz
733            if(paramVal > 1) return RC_INVALID_PARAM;
734            x = paramVal ? 0x0004 : 0x0000;
735            return radio_controller_SPI_setRegBits(ba, rfSel, 0x8, 0x0004, x);
736            break;
737#endif //RC_INCLUDED_PARAMS_FILTS
738
739#ifdef RC_INCLUDED_PARAMS_MISC
740        case RC_PARAMID_RSSI_HIGH_BW_EN:
741            //reg7[11]: 0=2MHz RSSI BW, 1=6MHZ RSSI BW
742            if(paramVal > 1) return RC_INVALID_PARAM;
743            x = paramVal ? 0x0800 : 0x0000;
744            return radio_controller_SPI_setRegBits(ba, rfSel, 0x7, 0x0800, x);
745            break;
746        case RC_PARAMID_TXLINEARITY_PADRIVER:
747            //reg9[9:8]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
748            if(paramVal > 3) return RC_INVALID_PARAM;
749            x = (paramVal&0x3)<<8;
750            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x0300, x);
751            break;
752        case RC_PARAMID_TXLINEARITY_VGA:
753            //reg9[7:6]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
754            if(paramVal > 3) return RC_INVALID_PARAM;
755            x = (paramVal&0x3)<<6;
756            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x00C0, x);
757            break;
758        case RC_PARAMID_TXLINEARITY_UPCONV:
759            //reg9[3:2]: [0,1,2,3]=[50%,63%,78%,100%] current; higher current -> more linear
760            if(paramVal > 3) return RC_INVALID_PARAM;
761            x = (paramVal&0x3)<<2;
762            return radio_controller_SPI_setRegBits(ba, rfSel, 0x9, 0x000C, x);
763            break;
764#endif //RC_INCLUDED_PARAMS_MISC
765        default:
766            //Either no paramters were #ifdef'd in, or user supplied invalid paramID
767            return RC_INVALID_PARAMID;
768            break;
769    }
770
771    return 0;
772}
773
774/**
775\brief Reads the TxDCO calibration values from the EEPROM and writes the values to the DACs of the selected RF interface. This function
776requires the eeprom_onewire core.
777\param rc_ba Base memory address of radio_controller core
778\param eeprom_ba Base memory address of eeprom_onewire core
779\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
780\return Returns non-zero if w3_ad_controller or w3_iic_eeprom core is not found; otherwise returns 0
781*/
782int radio_controller_apply_TxDCO_calibration(u32 rc_ba, u32 eeprom_ba, u32 rfSel) {
783#ifdef XPAR_EEPROM_ONEWIRE_NUM_INSTANCES
784    int i;
785    static u32 rfSel_ALL[4] = {RC_RFA, RC_RFB, RC_RFC, RC_RFD};
786    u32 cur_rfSel;
787   
788    int eepromStatus = 0;
789    short calReadback = 0;
790    signed short best_I, best_Q;
791    unsigned char radioNum;
792    Xuint8 memory[8], version, revision, valid;
793    Xuint16 serial;
794
795    //rfSel will be OR'd combo of [RC_RFA, RC_RFB, RC_RFC, RC_RFD]
796    // This function must iterate for each radio
797    for(i=0; i<4; i++) {
798        if(rfSel & rfSel_ALL[i]) {
799            cur_rfSel = rfSel_ALL[i];
800            radioNum = i+1;
801        } else {
802            //Skip this radio
803            continue;
804        }
805   
806        //Select the FPGA board EEPROM during init
807        eepromStatus = WarpEEPROM_EEPROMSelect((void*)eeprom_ba, 0);
808        if(eepromStatus != 0) {
809            xil_printf("WarpEEPROM_EEPROMSelect Select Failed! (%d)\n", eepromStatus);
810            return -1;
811        }
812
813        //Initialize the EEPROM controller
814        eepromStatus = WarpEEPROM_Initialize((void*)eeprom_ba);
815        if(eepromStatus != 0) {
816            xil_printf("WarpEEPROM_Initialize Failed! (%x)\n", eepromStatus);
817            return -1;
818        }
819
820        //Select the EEPROM on the current radio board
821        eepromStatus = WarpEEPROM_EEPROMSelect((void*)eeprom_ba, radioNum);
822        if(eepromStatus != 0) {
823            xil_printf("TxDCO: WarpEEPROM_EEPROMSelect error (%x)\n", eepromStatus);
824            return -1;
825        }
826
827        //Read the first page from the EERPOM
828        WarpEEPROM_ReadMem((void*)eeprom_ba, 0, 0, memory);
829        version = (memory[0] & 0xE0) >> 5;
830        revision = (memory[1] & 0xE0) >> 5;
831        valid = memory[1] & 0x1F;
832
833        //Read the Radio Board serial number
834        serial = WarpEEPROM_ReadWARPSerial((void*)eeprom_ba);
835
836        //Read the Tx DCO values
837        calReadback = WarpEEPROM_ReadRadioCal((void*)eeprom_ba, 2, 1);
838
839        //Scale the stored values
840        best_I = (signed short)(((signed char)(calReadback & 0xFF))<<1);
841        best_Q = (signed short)(((signed char)((calReadback>>8) & 0xFF))<<1);
842        xil_printf("  Radio WR-a-%05d Tx DCO I/Q: %d/%d\n", serial, best_I, best_Q);
843
844        //Write the Tx DCO values to the DAC offset registers
845        radio_controller_DAC_OffsetAdj(rc_ba, cur_rfSel, 0, best_I);
846        radio_controller_DAC_OffsetAdj(rc_ba, cur_rfSel, 1, best_Q);
847
848    }//END for(each radio)
849
850    return 0;
851#else
852    print("eerpom_oneiwre pcore is missing! Cannot apply TxDCO correction\n");
853    return -1;
854#endif
855}
856
857/**
858\brief Writes the AD9777 offset registers for the selected DACs and channel (I/Q)
859\param rc_ba Base memory address of radio_controller core
860\param rfSel Selects RF interfaces to affect (OR'd combination of [RC_RFA, RC_RFB, RC_RFC, RC_RFD])
861\param chan Selects I or Q DAC (0=I, 1=Q)
862\param dc_val DC Offset value to apply; must be in [-1024,1023]
863\return Returns non-zero for invalid inputs; retursn 0 on success
864*/
865int radio_controller_DAC_OffsetAdj(u32 rc_ba, u32 rfSel, u8 chan, short dc_val) {
866    short value;
867   
868    if (dc_val > 1023 || dc_val < -1024) {          // Make sure the value is in range.
869        return -1;
870    }
871
872    short reg8;
873    if (dc_val < 0) {                               // If the value is negative then store set the first bit of second register
874        reg8 = 0x0080;                              // to 1
875    }
876    else {
877        reg8 = 0x0000;                              // Or if positive set it to 0.
878    }
879
880    value = abs(dc_val);
881
882    short reg7 = ((value & 0x03FC) >> 2);           // b9:b2 of the value are the 8 bits in the first register
883    reg8 = reg8 + (value & 0x0003);                 // b1:b0 of the value are the last 2 bits in the second register
884
885    if (chan == 0) {
886        radio_controller_DAC_SPI_write(rc_ba, rfSel, 0x7, reg7);
887        radio_controller_DAC_SPI_write(rc_ba, rfSel, 0x8, reg8);
888    } else if (chan == 1) {
889        radio_controller_DAC_SPI_write(rc_ba, rfSel, 0xB, reg7);
890        radio_controller_DAC_SPI_write(rc_ba, rfSel, 0xC, reg8);
891    } else {
892        return -1;
893    }
894
895    return 0;
896}
897
898/** @}*/ //END group user_functions
Note: See TracBrowser for help on using the repository browser.