source: ResearchApps/PHY/WARPLAB/WARPLab7/C_Code_Reference/wl_interface.c

Last change on this file was 4989, checked in by chunter, 6 years ago

Added a new command, rx_lpf_corn_freq_fine, to adjust another parameter in the radio controller

File size: 19.7 KB
Line 
1/** @file wl_interface.c
2 *  @brief WARPLab Framework (Interface)
3 *
4 *  This contains the code for WARPLab Framework.
5 *
6 *  @copyright Copyright 2013-2015, Mango Communications. All rights reserved.
7 *          Distributed under the WARP license  (http://warpproject.org/license)
8 *
9 *  @author Chris Hunter (chunter [at] mangocomm.com)
10 *  @author Patrick Murphy (murphpo [at] mangocomm.com)
11 *  @author Erik Welsh (welsh [at] mangocomm.com)
12 */
13
14
15/**********************************************************************************************************************/
16/**
17 * @brief Common Functions
18 *
19 **********************************************************************************************************************/
20
21
22/***************************** Include Files *********************************/
23
24// Xilinx / Standard library includes
25#include <xparameters.h>
26#include <xio.h>
27
28#include <stdlib.h>
29#include <stdio.h>
30
31// Xilinx Peripheral includes
32#include <radio_controller.h>
33
34// WARPLab includes
35#include "wl_common.h"
36#include "wl_interface.h"
37#include "wl_baseband.h"
38
39
40
41/*************************** Constant Definitions ****************************/
42
43/*********************** Global Variable Definitions *************************/
44
45/*************************** Variable Definitions ****************************/
46
47/*************************** Functions Prototypes ****************************/
48
49/******************************** Functions **********************************/
50
51/*****************************************************************************/
52/**
53 * Process Interface Commands
54 *
55 * This function is part of the Ethernet processing system and will process the
56 * various interface related commands.
57 *
58 * @param   socket_index     - Index of the socket on which to send message
59 * @param   from             - Pointer to socket address structure (struct sockaddr *) where command is from
60 * @param   command          - Pointer to WARPLab Command
61 * @param   response         - Pointer to WARPLab Response
62 *
63 * @return  int              - Status of the command:
64 *                                 NO_RESP_SENT - No response has been sent
65 *                                 RESP_SENT    - A response has been sent
66 *
67 * @note    See on-line documentation for more information about the Ethernet
68 *          packet structure for WARPLab:  www.warpproject.org
69 *
70 ******************************************************************************/
71int ifc_process_cmd(int socket_index, void * from, wl_cmd_resp * command, wl_cmd_resp * response) {
72
73    //
74    // IMPORTANT ENDIAN NOTES:
75    //     - command
76    //         - header - Already endian swapped by the framework (safe to access directly)
77    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the command)
78    //     - response
79    //         - header - Will be endian swapped by the framework (safe to write directly)
80    //         - args   - Must be endian swapped as necessary by code (framework does not know the contents of the response)
81    //
82
83    // Standard variables
84    u32                 resp_sent      = NO_RESP_SENT;
85
86    wl_cmd_resp_hdr   * cmd_hdr        = command->header;
87    u32               * cmd_args_32    = command->args;
88    u32                 cmd_id         = WL_CMD_TO_CMDID(cmd_hdr->cmd);
89
90    wl_cmd_resp_hdr   * resp_hdr       = response->header;
91    u32               * resp_args_32   = response->args;
92    u32                 resp_index     = 0;
93
94    // Specific command variables
95    u32                 rf_sel;
96    u32                 rf_enable;
97    u32                 rf_state;
98    u32                 band, chan;
99    u32                 bb_gain, rf_gain;
100    u32                 enable;
101    u8                  corn_freq;
102
103    u32                 rxhp_val;
104    u32                 rxhp_en;
105
106    // Set up the response header
107    resp_hdr->cmd       = cmd_hdr->cmd;
108    resp_hdr->length    = 0;
109    resp_hdr->num_args  = 0;
110
111    // Process the command
112    switch(cmd_id){
113
114        //---------------------------------------------------------------------
115        case CMDID_INTERFACE_TX_EN:
116            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Tx enable\n");
117
118            rf_sel = Xil_Ntohl(cmd_args_32[0]);
119            radio_controller_TxEnable(RC_BASEADDR, rf_sel);
120        break;
121
122
123        //---------------------------------------------------------------------
124        case CMDID_INTERFACE_RX_EN:
125            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Rx enable\n");
126
127            rf_sel = Xil_Ntohl(cmd_args_32[0]);
128            radio_controller_RxEnable(RC_BASEADDR, rf_sel);
129        break;
130
131
132        //---------------------------------------------------------------------
133        case CMDID_INTERFACE_TXRX_DIS:
134            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Tx/Rx disable\n");
135
136            rf_sel =  Xil_Ntohl(cmd_args_32[0]);
137            radio_controller_TxRxDisable(RC_BASEADDR, rf_sel);
138        break;
139
140
141        //---------------------------------------------------------------------
142        case CMDID_INTERFACE_TXRX_STATE:
143            // Return the state of the TX and RX interface
144            //
145            // Message format:
146            //     cmd_args_32[0]      Interface Select (bit selects):
147            //                             - [28]     - Select RF A interface
148            //                             - [29]     - Select RF B interface
149            //                             - [30]     - Select RF C interface
150            //                             - [31]     - Select RF D interface
151            //
152            // Response format:
153            //     resp_args_32[0]     RF A state (optional)
154            //     resp_args_32[1]     RF B state (optional)
155            //     resp_args_32[2]     RF C state (optional)
156            //     resp_args_32[3]     RF D state (optional)
157            //
158            // NOTE:  The return value of the RF state will only get added to the return
159            //     arguments if the given RF interface is selected.
160            //
161            rf_sel   = Xil_Ntohl(cmd_args_32[0]);
162            rf_state = wl_get_radio_controller_state();
163
164            if (rf_sel & RC_RFA) {
165                rf_enable = RF_STATE_STANDBY;
166
167                if (rf_state & RF_RX_ANT_A) { rf_enable = RF_STATE_RX; }
168                if (rf_state & RF_TX_ANT_A) { rf_enable = RF_STATE_TX; }
169
170                resp_args_32[resp_index++] = Xil_Htonl(rf_enable);
171            }
172
173            if (rf_sel & RC_RFB) {
174                rf_enable = RF_STATE_STANDBY;
175
176                if (rf_state & RF_RX_ANT_B) { rf_enable = RF_STATE_RX; }
177                if (rf_state & RF_TX_ANT_B) { rf_enable = RF_STATE_TX; }
178
179                resp_args_32[resp_index++] = Xil_Htonl(rf_enable);
180            }
181
182            if (rf_sel & RC_RFC) {
183                rf_enable = RF_STATE_STANDBY;
184
185                if (rf_state & RF_RX_ANT_C) { rf_enable = RF_STATE_RX; }
186                if (rf_state & RF_TX_ANT_C) { rf_enable = RF_STATE_TX; }
187
188                resp_args_32[resp_index++] = Xil_Htonl(rf_enable);
189            }
190
191            if (rf_sel & RC_RFD) {
192                rf_enable = RF_STATE_STANDBY;
193
194                if (rf_state & RF_RX_ANT_D) { rf_enable = RF_STATE_RX; }
195                if (rf_state & RF_TX_ANT_D) { rf_enable = RF_STATE_TX; }
196
197                resp_args_32[resp_index++] = Xil_Htonl(rf_enable);
198            }
199
200            // Send response
201            resp_hdr->length  += (resp_index * sizeof(resp_args_32));
202            resp_hdr->num_args = resp_index;
203        break;
204
205
206        //---------------------------------------------------------------------
207        case CMDID_INTERFACE_CHANNEL:
208            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set channel\n");
209
210            rf_sel = Xil_Ntohl(cmd_args_32[0]);
211            band   = Xil_Ntohl(cmd_args_32[1]);
212            chan   = Xil_Ntohl(cmd_args_32[2]);
213
214            radio_controller_setCenterFrequency(RC_BASEADDR, rf_sel, band, chan);
215        break;
216
217
218        //---------------------------------------------------------------------
219        case CMDID_INTERFACE_TX_GAINS:
220            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set Tx gains\n");
221
222            rf_sel  = Xil_Ntohl(cmd_args_32[0]);
223            bb_gain = Xil_Ntohl(cmd_args_32[1]);
224            rf_gain = Xil_Ntohl(cmd_args_32[2]);
225
226            radio_controller_setRadioParam(RC_BASEADDR, rf_sel, RC_PARAMID_TXGAIN_BB, bb_gain);
227            radio_controller_setRadioParam(RC_BASEADDR, rf_sel, RC_PARAMID_TXGAIN_RF, rf_gain);
228        break;
229
230
231        //---------------------------------------------------------------------
232        case CMDID_INTERFACE_RX_GAINS:
233            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set Rx gains\n");
234
235            rf_sel  = Xil_Ntohl(cmd_args_32[0]);
236            rf_gain = Xil_Ntohl(cmd_args_32[1]);
237            bb_gain = Xil_Ntohl(cmd_args_32[2]);
238
239            // Get the current RXHP value
240            rxhp_val = (Xil_In32(RC_BASEADDR + RC_SLV_REG0_OFFSET) & RC_REG0_RXHP);
241
242            // Force RXHP to one
243            //   - This will minimize the impact of DC level changes during RX gain changes
244            //
245            radio_controller_setRxHP(RC_BASEADDR, rf_sel, RC_RXHP_ON);
246
247            radio_controller_setRadioParam(RC_BASEADDR, rf_sel, RC_PARAMID_RXGAIN_RF, rf_gain);
248            radio_controller_setRadioParam(RC_BASEADDR, rf_sel, RC_PARAMID_RXGAIN_BB, bb_gain);
249
250            // Set RXHP back to the original value
251            if(rf_sel & RC_RFA) {
252                rxhp_en = (rxhp_val & RC_CTRLREGMASK_RFA) ? RC_RXHP_ON : RC_RXHP_OFF;
253                radio_controller_setRxHP(RC_BASEADDR, RC_RFA, rxhp_en);
254            }
255            if(rf_sel & RC_RFB) {
256                rxhp_en = (rxhp_val & RC_CTRLREGMASK_RFB) ? RC_RXHP_ON : RC_RXHP_OFF;
257                radio_controller_setRxHP(RC_BASEADDR, RC_RFB, rxhp_en);
258            }
259            if(rf_sel & RC_RFC) {
260                rxhp_en = (rxhp_val & RC_CTRLREGMASK_RFC) ? RC_RXHP_ON : RC_RXHP_OFF;
261                radio_controller_setRxHP(RC_BASEADDR, RC_RFC, rxhp_en);
262            }
263            if(rf_sel & RC_RFD) {
264                rxhp_en = (rxhp_val & RC_CTRLREGMASK_RFD) ? RC_RXHP_ON : RC_RXHP_OFF;
265                radio_controller_setRxHP(RC_BASEADDR, RC_RFD, rxhp_en);
266            }
267        break;
268
269
270        //---------------------------------------------------------------------
271        case CMDID_INTERFACE_TX_LPF_CORN_FREQ:
272            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set Tx LPF corner freq\n");
273
274            rf_sel      = Xil_Ntohl(cmd_args_32[0]);
275            corn_freq   = Xil_Ntohl(cmd_args_32[1]);
276
277            radio_controller_setRadioParam(RC_BASEADDR, rf_sel, RC_PARAMID_TXLPF_BW, corn_freq);
278        break;
279
280
281        //---------------------------------------------------------------------
282        case CMDID_INTERFACE_RX_LPF_CORN_FREQ:
283            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set Rx LPF corner freq\n");
284
285            rf_sel      = Xil_Ntohl(cmd_args_32[0]);
286            corn_freq   = Xil_Ntohl(cmd_args_32[1]);
287
288            radio_controller_setRadioParam(RC_BASEADDR, rf_sel, RC_PARAMID_RXLPF_BW, corn_freq);
289        break;
290
291        //---------------------------------------------------------------------
292        case CMDID_INTERFACE_RX_LPF_CORN_FREQ_FINE:
293            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set Rx LPF corner freq\n");
294
295            rf_sel      = Xil_Ntohl(cmd_args_32[0]);
296            corn_freq   = Xil_Ntohl(cmd_args_32[1]);
297
298            radio_controller_setRadioParam(RC_BASEADDR, rf_sel, RC_PARAMID_RXLPF_BW_FINE, corn_freq);
299        break;
300
301        //---------------------------------------------------------------------
302        case CMDID_INTERFACE_RX_HPF_CORN_FREQ:
303            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set Rx HPF corner freq\n");
304
305            rf_sel      = Xil_Ntohl(cmd_args_32[0]);
306            corn_freq   = Xil_Ntohl(cmd_args_32[1]);
307
308
309            xil_printf("HPF CORN FREQ:  0x%08x    0x%08x\n", rf_sel, corn_freq);
310
311
312            //
313            // NOTE:  The setting of the RX HPF cutoff frequency only take effect if RXHP is 0.  Unfortunately,
314            //     we are not able to read the read the RXHP value to determine if this write actually takes
315            //     effect when we perform the setRadioParam function.  Therefore it is left up to the user to
316            //     make sure the state of the radio controller is correct to have this command take effect.
317            //
318
319            radio_controller_setRadioParam(RC_BASEADDR, rf_sel, RC_PARAMID_RXHPF_HIGH_CUTOFF_EN, corn_freq);
320        break;
321
322
323        //---------------------------------------------------------------------
324        case CMDID_INTERFACE_RX_GAIN_CTRL_SRC:
325            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set gain control source\n");
326
327            rf_sel = Xil_Ntohl(cmd_args_32[0]);
328            enable = Xil_Ntohl(cmd_args_32[1]) & 0x1;
329
330            if (enable == 0){
331                // Manual gain control
332                //   NOTE:  AGC will always run but values will be ignored
333                radio_controller_setCtrlSource(RC_BASEADDR, rf_sel, RC_REG0_RXHP_CTRLSRC, RC_CTRLSRC_REG);
334                radio_controller_setRxGainSource(RC_BASEADDR, rf_sel, RC_GAINSRC_SPI);
335
336                // De-select AGC I/Q signals for Rx buffers input and disable buffers->AGC trigger
337                wl_bb_clear_config(rf_sel >> 24);
338            } else {
339                // Automatic gain control
340                radio_controller_setCtrlSource(RC_BASEADDR, rf_sel, RC_REG0_RXHP_CTRLSRC, RC_CTRLSRC_HW);
341                radio_controller_setRxGainSource(RC_BASEADDR, rf_sel, RC_GAINSRC_HW);
342
343                // Select AGC I/Q signals for Rx buffers input and enable buffers->AGC trigger
344                wl_bb_set_config(rf_sel >> 24);
345            }
346
347        break;
348
349
350        //---------------------------------------------------------------------
351        case CMDID_INTERFACE_RXHP_CTRL:
352            // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Set rxhp value\n");
353
354            rf_sel = Xil_Ntohl(cmd_args_32[0]);
355            enable = Xil_Ntohl(cmd_args_32[1]) & 0x1;
356
357            if(enable == 0){
358                // Force RXHP to zero
359                radio_controller_setRxHP(RC_BASEADDR, rf_sel, RC_RXHP_OFF);
360            } else {
361                // Force RXHP to one
362                radio_controller_setRxHP(RC_BASEADDR, rf_sel, RC_RXHP_ON);
363            }
364
365        break;
366
367
368        //---------------------------------------------------------------------
369        default:
370            wl_printf(WL_PRINT_ERROR, print_type_interface, "Unknown command ID: %d\n", cmd_id);
371        break;
372    }
373    return resp_sent;
374}
375
376
377
378/*****************************************************************************/
379/**
380 * @brief Set Radio Controller defaults
381 *
382 * @param  None
383 *
384 * @return None
385 *
386 ******************************************************************************/
387void set_radio_controller_defaults(u32 all_rf_sel) {
388
389    // Set Tx bandwidth to nominal mode (Radios_Tx_LPF_Corn_Freq)
390    radio_controller_setRadioParam(RC_BASEADDR, all_rf_sel, RC_PARAMID_TXLPF_BW, 1);
391
392    // Set Rx bandwidth to nominal mode (Radios_Rx_LPF_Corn_Freq)
393    radio_controller_setRadioParam(RC_BASEADDR, all_rf_sel, RC_PARAMID_RXLPF_BW, 1);
394    radio_controller_setRadioParam(RC_BASEADDR, all_rf_sel, RC_PARAMID_RXLPF_BW_FINE, 2);
395
396    // Set Radios to use 30KHz cutoff on HPF
397    radio_controller_setRadioParam(RC_BASEADDR, all_rf_sel, RC_PARAMID_RXHPF_HIGH_CUTOFF_EN, 1);
398
399    // Set Tx VGA Linearity to 2 (78% current) see pg 36 of MAX2829 datasheet for more information
400    radio_controller_setRadioParam(RC_BASEADDR, all_rf_sel, RC_PARAMID_TXLINEARITY_VGA, 2);
401
402    // Disable all Tx / Rx
403    radio_controller_TxRxDisable(RC_BASEADDR, all_rf_sel);
404
405}
406
407
408
409
410/**********************************************************************************************************************/
411/**
412 * @brief WARP v3 Specific Functions
413 *
414 **********************************************************************************************************************/
415
416/***************************** Include Files *********************************/
417
418#include <w3_ad_controller.h>
419
420/*************************** Constant Definitions ****************************/
421
422/*********************** Global Variable Definitions *************************/
423
424/*************************** Variable Definitions ****************************/
425
426/*************************** Functions Prototypes ****************************/
427
428/******************************** Functions **********************************/
429
430/*****************************************************************************/
431/**
432 * @brief RF Interface subsystem initialization
433 *
434 * Initializes the RF interface subsystem
435 *
436 * @param  None
437 *
438 * @return  int              - Status of the command:
439 *                                 XST_SUCCESS - Command completed successfully
440 *                                 XST_FAILURE - There was an error in the command
441 *
442 ******************************************************************************/
443int ifc_init(){
444    // wl_printf(WL_PRINT_DEBUG, print_type_interface, "Configuring interface ...\n\n");
445
446    int status          = XST_SUCCESS;
447    u32 all_rf_sel;
448    u32 all_ad_sel;
449
450    // Set the "ALL" variables based on the RF config
451    if (WARPLAB_CONFIG_4RF) {
452        all_rf_sel = (RC_RFA | RC_RFB | RC_RFC | RC_RFD);
453        all_ad_sel = (RFA_AD_CS | RFB_AD_CS | RFC_AD_CS | RFD_AD_CS);
454    } else {
455        all_rf_sel = (RC_RFA | RC_RFB);
456        all_ad_sel = (RFA_AD_CS | RFB_AD_CS);
457    }
458
459    // Initialize the AD9963 ADCs/DACs
460    status = ad_init(AD_BASEADDR, all_ad_sel, 2);
461
462    if(status != XST_SUCCESS) {
463        wl_printf(WL_PRINT_ERROR, print_type_interface, "AD initialization failed with status: %d\n", status);
464        wl_printf(WL_PRINT_NONE, NULL, "\n************************************************************\n");
465        wl_printf(WL_PRINT_NONE, NULL, " Check that software and hardware config match\n  (this error may indicate 4-radio code on 2-radio hadrware)\n");
466        wl_printf(WL_PRINT_NONE, NULL, "************************************************************\n\n");
467        return XST_FAILURE;
468    }
469
470    // Initialize the radio_controller core and MAX2829 transceivers
471    status = radio_controller_init(RC_BASEADDR, (all_rf_sel), 1, 1);
472
473    if(status != XST_SUCCESS) {
474        wl_printf(WL_PRINT_ERROR, print_type_interface, "Radio controller initialization failed with status: %d\n", status);
475        return XST_FAILURE;
476    }
477
478    // Update the TX delays to match the 802.11 design
479    //     NOTE:  These values considerably reduces any "pop" in the transmission following a TX enable (TX_EN) command
480    //     NOTE:  Default value set in radio_controller_init() is:  radio_controller_setTxDelays(RC_BASEADDR, 150, 0, 0, 250);
481    //
482    radio_controller_setTxDelays(RC_BASEADDR, 40, 20, 0, 250);
483
484    // Default the Tx/Rx gain control sources to SPI
485    radio_controller_setTxGainSource(RC_BASEADDR, all_rf_sel, RC_GAINSRC_SPI);
486    radio_controller_setRxGainSource(RC_BASEADDR, all_rf_sel, RC_GAINSRC_SPI);
487
488    // Apply the TxDCO correction values stored in the on-board (and FMC, if present) EEPROMs
489    radio_controller_apply_TxDCO_calibration(AD_BASEADDR, EEPROM_BASEADDR, all_rf_sel);
490
491    // Set some sane defaults for the MAX2829 Tx/Rx paths; these can be changed by WARPLab commands later
492    set_radio_controller_defaults(all_rf_sel);
493
494    return status;
495}
496
497
498
Note: See TracBrowser for help on using the repository browser.