source: PlatformSupport/WARPMAC/warpphy.c

Last change on this file was 1712, checked in by murphpo, 12 years ago

Updating code for OFDM ref design v17 in ISE 13.4 tools

File size: 57.3 KB
RevLine 
[1028]1/*! \file warpphy.c
2 \brief Provide PHY-specific functions for interfacing WARPMAC (and MAC code) to the OFDM PHY peripherals
3 
[1598]4 @version 15.22
[1028]5 @author Chris Hunter & Patrick Murphy
6 
7 Many of the register names and bit assignments in this file depend on the design of the OFDM PHY. You must
8 use matching versions of WARPMAC, WARPPHY and ofdm_txrx_mimo. Refer to the wireless reference designs for
9 known-good combinations of versions.
10 */
11
12//XPS-generated header with peripheral parameters
[1203]13#include "warp_fpga_board.h"
[1028]14#include "xparameters.h"
15
16//Header for WARPPHY Interface
17#include "warpphy.h"
18
19//Header for WARPMAC framework (required for some global values)
20#include "warpmac.h"
21
[1169]22// These header files define some macros for reading/writing registers in the Sysgen-designed cores
23// This layer of macros keep this code independent from the name of the sysgen core
24//  (sysgen defines its register names as a function of the .mdl file name)
[1712]25#include "util/ofdm_txrx_mimo_regMacros.h"
26#include "util/ofdm_agc_mimo_regMacros.h"
27#include "util/warp_timer_regMacros.h"
28#include "util/warp_userio.h"
[1028]29
30//Headers for other WARP peripheral cores
31#include "EEPROM.h"
32#include "radio_controller_basic.h"
33#include "radio_controller_ext.h"
34#include "radio_controller_adv.h"
35#include "radio_controller_5ghz.h"
36
37//Other standard header files
[1712]38#include <sleep.h>
[1028]39#include <stdio.h>
40#include <string.h>
41
42//********Globals********
[1169]43int agc_targetRxPowerOut;
44int agc_noisePowerEstimate;
[1208]45
[1028]46unsigned char baseRateMod;
47unsigned int numTrainingSyms;
[1169]48unsigned int ofdmRx_pktDetDly;
[1028]49unsigned int numBaseRate;
50unsigned char txGain;
[1105]51unsigned char RxSoftDecodingEn;
[1616]52unsigned short pktDet_corrCounterLoad;
53unsigned char pktDet_corrWindowStart;
54unsigned char pktDet_corrWindowEnd;
[1028]55
[1169]56unsigned int pktDet_energyThresh;
57unsigned int pktDet_carrierSenseThresh;
[1170]58unsigned char pktDet_threshMinDur;
[1028]59
[1208]60unsigned int warpphy_txAntMode;
61unsigned int warpphy_rxAntMode;
62unsigned int activeRadios_Tx, activeRadios_Rx;
63unsigned int activePHYStatusBits;
[1245]64unsigned short longCorrThresh;
[1377]65unsigned int afScaling;
[1028]66
[1546]67unsigned short pktDetCFOsampCount;
68
[1028]69unsigned int RxFFT_Window_Offset;
[1169]70unsigned int txScaling_preamble;
71unsigned int txScaling_payload;
72
[1594]73unsigned int agcIIR_g, agcIIR_fb;
74
75
[1028]76/////////////////////////////////
77
78///@brief Initializes the OFDM PHY core
79///The OFDM PHY and radio controller cores have many options which must be configured before they can
80///be used over the air. This funciton configures these cores with sensible defaults.
81int warpphy_init(){
[1224]82    unsigned int i;
[1028]83    xil_printf("  Initializing WARPPHY:\r\n");
84
[1208]85    //Set the default antenna configuration
86    warpphy_txAntMode = TX_ANTMODE_SISO_ANTA;
87    warpphy_rxAntMode = RX_ANTMODE_SISO_ANTA;
88    activePHYStatusBits = DEFAULT_STATUSBITS;
89
[1203]90    //Hold the PHY in reset until everything it setup; the reset does not initialize the PHY's registers
91    mimo_ofdmTx_disable();
92    mimo_ofdmRx_disable();
93   
[1028]94    //Initialize global variables
[1625]95    longCorrThresh = 9000;//3500; //2750
[1616]96   
97    afScaling = 2944;//6656;
[1594]98
[1169]99    //AGC target output power, in units of dBv (voltage at MAX2829 output)
[1594]100    agc_targetRxPowerOut = -12;
[1028]101
[1169]102    //AGC noise power estimate, in dBm
103    agc_noisePowerEstimate = -95;
[1028]104
[1169]105    //Base-rate modulation scheme; should be QPSK
[1192]106    baseRateMod = QPSK;
[1064]107
[1169]108    //Number of training symbol periods (all on 1 antenna for SISO, split across antennas for MIMO)
109    numTrainingSyms = NUM_TRAINING_SYMBOLS;
[1064]110
[1169]111    //Number of base rate OFDM symbols; every node must agree on this number ahead of time
[1616]112    // IF FEC is enabled, the base rate symbols are always encoded at rate 1/2, so a 24-byte
113    // header at QPSK occupies 4 symbols (instead of 2 when uncoded)
114    numBaseRate = NUM_BASERATE_SYMBOLS;
[1064]115
[1169]116    //Packet detection delay, in sys_clk cycles
117    // The Rx PHY waits this long before searching for correlation peaks
[1616]118    ofdmRx_pktDetDly = 124;
[1064]119
[1169]120    //Tx RF gain (6-bit value in [0,63])
[1594]121    txGain = 0x3f;
[1064]122
[1169]123    //Tx scaling values; both are interpreted as UFix16_13 values
124    // The ratio of preamble/payload values should be approx 1/4
[1616]125    // Increasing these values will increase Tx power at the expense of clipping
126    txScaling_preamble = 3072;
127    txScaling_payload  = 12288;
[1594]128   
[1169]129    //Packet detector parameters
[1625]130    // Energy threshold - X/16 = RSSI
131    pktDet_energyThresh = 8000;
[1064]132
[1169]133    //Carrier sensing threshold - 8192/16 = RSSI of 512 (approx -65dBm Rx power)
[1616]134    pktDet_carrierSenseThresh = 8192;
[1245]135   
[1169]136    //Minimum duration of energy-above-energyThresh required to assert a packet detection
[1616]137    pktDet_threshMinDur = 24;
[1169]138   
[1616]139    //Define the FFT start offset (FFT will use (15 - offset) samples of cyclic prefix to handle synchronization
[1169]140    RxFFT_Window_Offset = INIT_RXFFTOFSET;
[1064]141
[1616]142    //Set some magic numbers for the CFO correction calculations; these are only used for pre-correcting CFO in DF mode
143    warpphy_setPilotCFOCorrection(0x8025AEE6);
144    warpphy_setCoarseCFOCorrection(30533);
145
[1028]146    /*****************Radio Setup******************/
[1640]147    xil_printf("\tInitializing Radio Transmitter...\r\n");
[1028]148   
149    //The second argument sets the clock ratio in the radio controller's SPI controller
[1169]150    // 1 is good for a 40MHz bus
[1028]151    // 2 is the right value for an 80MHz bus
152    WarpRadio_v1_Reset((unsigned int *)XPAR_RADIO_CONTROLLER_0_BASEADDR, 1);
153   
[1640]154    xil_printf("\tStarting TxDCO correction...\r\n");
[1064]155
[1028]156    //Apply the stored TX DC offset correction values for each radio
157    warpphy_applyTxDCOCalibration(FIRST_RADIO);
158    warpphy_applyTxDCOCalibration(SECOND_RADIO);
159   
[1169]160    //Configure some MAX2829 Tx parameters for good wideband performance
161
[1208]162    //Disable software control of the TxEn/RxEn signals; the PHY will control these
163    WarpRadio_v1_RxEnSoftControlDisable(BOTH_RADIOS);
164    WarpRadio_v1_TxEnSoftControlDisable(BOTH_RADIOS);
165   
[1169]166    //Set Tx bandwidth - 0x1 = 24MHz (minimum)
[1208]167    WarpRadio_v1_TxLpfCornFreqCoarseAdj(0x1, BOTH_RADIOS);
[1028]168   
169    //Enable hardware control of Tx gains (handled by the radio controller Tx state machine)
[1208]170    WarpRadio_v1_SoftwareTxGainControl(0, BOTH_RADIOS);
[1028]171   
172    //Four arguments: dly_TxEn, dly_TxStart, dly_GainRampEn, dly_PowerAmpEn, each in units of bus clock cycles
[1208]173    WarpRadio_v1_SetTxTiming(BOTH_RADIOS, 0, 200, 100, 0);
[1164]174
[1028]175    //Three arguments: targetGain, gainStep, stepInterval; max targetGain is 0x3F
[1208]176    WarpRadio_v1_SetTxGainTiming(BOTH_RADIOS, txGain, 0xF, 1);
[1028]177   
[1169]178    //Set the MAX2829 Tx baseband gain; 0x3 is max gain
[1208]179    WarpRadio_v1_BaseBandTxGain(0x3, BOTH_RADIOS);
[1028]180   
[1640]181    xil_printf("\tInitializing Radio Receiver...");
[1028]182
183    //Enable hardware AGC control of receive gains & RxHP
[1208]184    WarpRadio_v1_RxHpSoftControlDisable(BOTH_RADIOS);
185    WarpRadio_v1_SoftwareRxGainControl(0, BOTH_RADIOS);
[1028]186
187    //Set bandwith with RxHP=0; RxHighPassCornerFreq(0) is critical for good performance
[1208]188    WarpRadio_v1_RxHighPassCornerFreq(0, BOTH_RADIOS);
[1028]189   
[1594]190    //Set Rx bandwidth; 0x0 = 15MHz (minimum)
191    WarpRadio_v1_RxLpfCornFreqCoarseAdj(0, BOTH_RADIOS);
[1028]192   
193    xil_printf("complete!\r\n");
194    /**********************************************************/
195   
[1164]196    /*******************Packet Detector************************/
[1640]197    xil_printf("\tInitializing Packet Detection...");
[1169]198
199    //Assert the packet detection output reset
200    ofdm_txrx_mimo_WriteReg_Rx_PktDet_ignoreDet(1);
201
202    //Set the RSSI clock ratio; 0=sys_clk/4; 1=sys_clk/8
203    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setRSSIclkRatio(0);
204
205    //Set the minimum energy duration
[1170]206    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMinDuration(pktDet_threshMinDur);
[1164]207   
[1169]208    //Enable the carrier-sensing block's IDLE output (the timer can choose to use or ignore it)
[1164]209    ofdm_txrx_mimo_WriteReg_Rx_CSMA_enableIdle(1);
210   
[1169]211    //Hold the packet detector's running sum in reset
[1164]212    ofdm_txrx_mimo_WriteReg_Rx_PktDet_resetSum(1);
213   
[1169]214    //Configure the packet detector's antenna masks (1=antA, 2=antB, 3=both)
[1210]215    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMask(PKTDET_MASK_ANTA);
[1164]216   
[1169]217    //Set the packet detector's logic mode for the two antenna ports; 0 = AND, 1 = OR
[1164]218    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMode(1);
219   
[1169]220    //Set the running sum length; 16 is a good default
221    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setAvgLen(PKTDET_RSSI_SUMLEN);
[1164]222   
[1169]223    //Set the detector's energy threshold; this value must be scaled relative to the sum-length
224    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setThresh(pktDet_energyThresh);
[1164]225   
[1169]226    //Set the carrier sensing threshold to a very high level, disabling it by default
227    ofdm_txrx_mimo_WriteReg_Rx_CSMA_setThresh(CSMA_DISABLED_THRESH);
228
229    //Set the DIFS period; this is the require IDLE time before the IDLE output will assert
230    // Units are sys_clk/4 cycles (10MHz), so 300 = 30us
231    // This delay must exceed the TxDATA->TxACK turn around time (currently 23us)
232    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setDIFSPeriod(300);
[1164]233   
[1169]234    //Deassert the running sum reset; the sum will run continuously after this
[1164]235    ofdm_txrx_mimo_WriteReg_Rx_PktDet_resetSum(0);
236   
[1640]237    //Set thresholds for the autoCorrelation detector
[1631]238    //CorrThresh (UFix8_7): 0.7 ≈ 90
[1640]239    //MinPoiwer (UFix12_0); 2048 is theoretical max, 100-300 is more realistic, 0 works too
[1631]240    ofdm_txrx_mimo_WriteReg_Rx_PktDetCorr_params(90, 0);
[1640]241
242    //Enable both the RSSI and autoCorrelation packet detectors
[1631]243    ofdm_txrx_mimo_WriteReg_Rx_PktDet_rssiDetEn(1);
244    ofdm_txrx_mimo_WriteReg_Rx_PktDet_corrDetEn(1);
[1164]245   
[1640]246    //Deassert the packet detection output reset; packet detection events will start after this
247    ofdm_txrx_mimo_WriteReg_Rx_PktDet_ignoreDet(0);
[1631]248   
[1164]249    xil_printf("complete!\r\n");
250    /**********************************************************/
251   
[1028]252    /*************************PHY******************************/
[1169]253
[1640]254    xil_printf("\tInitializing OFDM Transmitter...");
[1028]255   
[1203]256    //Clear all the match and action blocks in the auto response system
257    mimo_ofdmTxRx_setAction0(0);
258    mimo_ofdmTxRx_setAction1(0);
259    mimo_ofdmTxRx_setAction2(0);
260    mimo_ofdmTxRx_setAction3(0);
261    mimo_ofdmTxRx_setAction4(0);
262    mimo_ofdmTxRx_setAction5(0);
263    mimo_ofdmTxRx_setMatch0(0);
264    mimo_ofdmTxRx_setMatch1(0);
265    mimo_ofdmTxRx_setMatch2(0);
266    mimo_ofdmTxRx_setMatch3(0);
267    mimo_ofdmTxRx_setMatch4(0);
268    mimo_ofdmTxRx_setMatch5(0);
269
[1224]270    //Fill in the header translator with non-translating values by default
271    // This will "overwrite" the header with the same pktbuf/byte combos as the template buffer
272    // User code will override some entries here to implement a protocol
273    for(i=0; i<(32*32); i++)
274    {
275        //Each entry is a 10-bit number of {srcBuf[4:0], srcByteAddr[4:0]}
276        XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXHEADERTRANSLATE+i*sizeof(int), (i & 0x3FF));
277    }
278   
[1377]279    //Set the AF scaling
280    mimo_ofdmRx_setAFTxScaling(afScaling);
281   
[1524]282    //Set the minimum magnitude for channels to use their pilots
283    mimo_ofdmRx_setPilotCalcParams(0xFFF); //MinMag as UFix12_12 (41 ~= 0.01)
[1222]284   
[1028]285    //Configure the FFT scaling values in the PHY Tx and Rx
[1169]286    // 6-bits each, 6LSB are Tx scaling; 6LSB+6 are Rx scaling
287    mimo_ofdmTxRx_setFFTScaling((unsigned int)((
288                                (16*RX_FFT_SCALING_STAGE1 + 4*RX_FFT_SCALING_STAGE2 + 1*RX_FFT_SCALING_STAGE3)<<6 ) | 
289                                (16*TX_FFT_SCALING_STAGE1 + 4*TX_FFT_SCALING_STAGE2 + 1*TX_FFT_SCALING_STAGE3)));
[1028]290   
291    //Subcarrier indicies for pilot tones - the values here must line up with zeros in the modulation setup for each subcarrier
292    // Subcarriers [-21,-7,7,21] are the default, matching the 802.11a spec
[1494]293    mimo_ofdmTx_setPilotIndcies((7 + ((64-21)<<8) + ((64-7)<<16) + ((21)<<24) ));
[1028]294   
295    //Pilot tone values are Fix16_15, so
[1169]296    // Pilot 1 should be negative, pilot 2 should be positive
[1028]297    // 0x7FFF is +1, 0x8000 is -1
298    // 0xA57D is ~-0.707, 0x5A82 is ~+0.707
[1222]299    mimo_ofdmTxRx_setPilotValues( (0xA57D) + (0x5A82 << 16));
[1028]300   
[1226]301    //2 values in this write: number of training symbols and number of base rate symbols
302    // The Tx/Rx nodes must agree on these values ahead of time
[1537]303    warpphy_setTxNumSyms(numBaseRate, numTrainingSyms);
304    warpphy_setRxNumSyms(numBaseRate, numTrainingSyms);
[1028]305   
306    //Scaling constant for the transmitted preamble; helps normalize the amplitude of the stored preamble and actual IFFT output
[1169]307    mimo_ofdmTx_setTxScaling(txScaling_preamble, txScaling_payload);
[1028]308
309    //Configure various options in the Tx PHY
310    mimo_ofdmTx_setControlBits (
[1226]311                                (3 << 4) | //Preamble shift for antenna B
[1555]312                                ((0&0x3F) << 20) | //Cyclic shift
[1028]313                                TX_PILOT_SCRAMBLING | //Pseudo-random scrambling of pilot tones
[1208]314                                TX_SOFTWARE_TXEN | //Use the PHY TxStart register to start the overall PHY/radio Tx state machine
[1236]315                                //TX_RANDOM_PAYLOAD | //Use random payload bytes (user must still provide valid header!)
[1504]316                                //TX_ALWAYS_USE_PRECFO | //Always apply Tx CFO, even if the packet isn't triggered by auto responders
[1028]317                                //TX_DISABLE_ANTB_PREAMBLE | //Disables preamble on antenna B
318                                0
319                                );
320   
[1616]321    //Shift antenna B preambles by -3 samples
322    warpphy_setAntBPreambleShift(13);
323
[1028]324    xil_printf("complete!\r\n");
325   
[1640]326    xil_printf("\tInitializing OFDM Receiver...");
[1049]327
[1615]328    //Configure the FEC blocks
[1616]329    // (CodingEn, SoftDecodingEn, ZeroTailEn, QPSK_Scaling, 16QAM_Scaling)
[1615]330    mimo_ofdmTxRx_setFECoptions(1, 1, 0, 6, 16);
331   
[1028]332    //Configures the default number of samples of the cyclic prefix to use for synchronization offset tolerance
333    // Larger values here reduce multipath tolerance
334    mimo_ofdmRx_setFFTWindowOffset(INIT_RXFFTOFSET);
335   
336    //Scaling value is a 32-bit value, composed of two UFix16_11 values
337    // So 0x08000800 scales A/B by exactly 1
338    // This value is dependent on the number of training symbols
339    // For SISO mode and numTraining=2, use 0x10001000 (the default)
340    mimo_ofdmRx_setRxScaling(0x10001000); 
341   
342    //Long correlator parameters (for packet detection confirmation and symbol timing)
[1169]343    // Top 16-bits are long-correlation threshold; 3000 works well over-the-air
344    // Bottom 16-bits are sample index corresponding to the long correlation event
345    //  (basically a magic number that aligns the Rx PHY state machine with the incoming packet)
[1616]346
347    warpphy_setLongCorrThresh(longCorrThresh);
348   
349    //The correlator only accepts peaks inside a window relative to the energy detection event
350    // Adjust the Start/End values below to grow/shrink the window as needed
351    pktDet_corrWindowStart = 90-32;
352    pktDet_corrWindowEnd = 180+32;
353
354    pktDet_corrCounterLoad = 251;//232;
[1546]355    pktDetCFOsampCount = 255;
[1616]356    mimo_ofdmRx_setLongCorrParams(((pktDet_corrCounterLoad & 0x00FF)    << 0 ) | \
357                                  ((pktDetCFOsampCount  & 0x00FF)   << 8 ) | \
358                                  ((pktDet_corrWindowStart & 0xFF)  << 16 ) | \
359                                  ((pktDet_corrWindowEnd & 0xFF)    << 24 )); //corr window start/end
[1169]360
361    //Sets the delay between the pkt detection assertion and the PHY searching for correlation peaks
362    mimo_ofdmRx_setPktDetDly(ofdmRx_pktDetDly);
[1616]363    mimo_ofdmRx_setCFOCalcDly(0);
[1494]364    mimo_ofdmRx_setCFOMaxDiff(255); //UFix8_8 - 0.15 * 256 ≈ 38
[1169]365
[1516]366    warpphy_setPreCFOoptions( (PRECFO_USECOARSE | PRECFO_USEPILOTS) );
[1494]367   
[1028]368    //Bottom 8 bits are the number of header bytes per packet; nodes must agree on this at build time
369    //  bits[7:0]: number of header bytes (bytes in base-rate symbols)
370    //Three more 8-bit values are stored here - each is an index of a byte in the header:
371    //  bits[15:8]: less-significant byte of pkt length
372    //  bits[23:16]: more-significant byte of pkt length
373    //  bits[31:24]: dynamic modulation masks
374    //  mimo_ofdmRx_setByteNums( (unsigned int)(NUM_HEADER_BYTES + (2<<8) + (3<<16) + (0<<24) ));
375    mimo_ofdmRx_setByteNums( (unsigned int)(NUM_HEADER_BYTES + (3<<8) + (2<<16) + (0<<24) ));
376   
[1208]377    //Configure some sane defaults in the Rx PHY
[1028]378    mimo_ofdmRx_setOptions
379    (
[1208]380        RESET_BER | //Hold the BER meter in reset
381        REQ_LONG_CORR | //Require long correlation for packet detection
[1597]382        //RSSI_GAIN_ADJ | //Compensate RSSI input to pkt detector for RF gain changes
[1516]383        //BYPASS_CARR_REC | //Hold the Rx DDS in reset (ignoring any coarse CFO estimate)
[1512]384        COARSE_CFO_EN | //Enable coarse CFO estimation
[1208]385        TX_DISABLE_PKTDET | //Ignore packet detection during Tx
[1279]386        SIMPLE_DYN_MOD_EN | //Use the header's fullRate field for demodulation
[1028]387        RESET_ON_BAD_HDR | //Reset Rx PHY if header fails CRC
[1537]388        RECORD_CHAN_ESTS | //Enable the channel estimate recording buffer
389        RECORD_CHAN_ESTMAGS | //Enable the channel estimate recording buffer
[1546]390        //CHANMAG_MASKING_EN | //Enable channel magnitude masking
[1028]391        0,
[1210]392        activePHYStatusBits
[1494]393    );
[1028]394   
[1208]395    //Set the modulation masks to sane defaults
396    // 0xF enables dynamic modulation for that path
[1279]397    warpphy_set_modulation(baseRateMod, 0xF, 0xF, 0xF, 0xF);
398
[1208]399    //Set the antenna modes to SISO by default
400    warpphy_setAntennaMode(TX_ANTMODE_SISO_ANTA, RX_ANTMODE_SISO_ANTA);
401   
[1169]402    warpphy_setNumTrainingSyms(NUM_TRAINING_SYMBOLS);
403
[1546]404    //Set min chanest magnitudes (UFix16_15 values; set to zero to effectively disable)
[1616]405    warpphy_setChanEstMinMags(0);
[1546]406   
407    //Set AF blanking interval (set to zeros to disable)
408    warpphy_setAFblanking(0, 0);
409   
[1712]410    XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RX_FIXEDPKTLEN, 0);
[1546]411   
[1028]412    xil_printf("complete!\r\n");
413    /**********************************************************/
414   
415    /***************************AGC****************************/
[1640]416    xil_printf("\tInitializing AGC...");
[1616]417    //agcIIR_fb = 0x20990; //20kHz cutoff, Fix18_17
418    //agcIIR_g =  0x1fb38; //20kHz cutoff, UFix18_17
419    agcIIR_fb = 0x20000; //0kHz cutoff, Fix18_17
420    agcIIR_g =  0x20000; //0kHz cutoff, UFix18_17
[1169]421    ofdm_AGC_Initialize(agc_noisePowerEstimate);
422    ofdm_AGC_setNoiseEstimate(agc_noisePowerEstimate);
[1597]423
424    ofdm_AGC_SetDCO(0x6); //enable both subtraction and IIR filter
425   
[1169]426    ofdm_AGC_SetTarget(agc_targetRxPowerOut);
[1028]427    ofdm_AGC_Reset();
[1594]428
429    XIo_Out32(XPAR_OFDM_AGC_MIMO_PLBW_0_MEMMAP_DCO_IIR_COEF_FB, agcIIR_fb);
430    XIo_Out32(XPAR_OFDM_AGC_MIMO_PLBW_0_MEMMAP_DCO_IIR_COEF_GAIN, agcIIR_g);
431   
[1028]432    xil_printf("complete!\r\n");
433    /**********************************************************/
434   
435    /**************************Timer***************************/
[1169]436    //Initialize the timer hardware; the individual timers will get setup in WARPMAC
[1049]437    warp_timer_init();
[1028]438    /**********************************************************/
439   
[1203]440    //Finally enable the PHY
441    mimo_ofdmTx_enable();
442    mimo_ofdmRx_enable();
443   
[1028]444    return 0;
445}
446
[1169]447///@brief Clears any pending Rx pkt status in the PHY. Was warpphy_pktAck() in previous versions.
[1164]448///
[1169]449///The Rx PHY blocks after asserting either its good or bad packet status bits. The bits
450///are cleared by asserting then de-asserting a register bit per status bit. This funciton clears
451///both good and bad pkt bits; there is no harm in clearing a status bit that isn't actually asserted.
452void warpphy_clearRxPktStatus(){
[1028]453   
454    //The TxRx_Interrupt_PktBuf_Ctrl register has many bits.
[1169]455    // bits[2:0] are the Rx status enables
456    // bits[6:4] are the Rx status resets
457    // bit[3] and bit[7] are used for the TxDone status and are preserved here
458    ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) | DEFAULT_STATUSBITRESETS);
459    ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) &  ~DEFAULT_STATUSBITRESETS);
[1028]460
461    return;
462}
463
464///@brief Releases the OFDM Rx PHY master reset
465///
466///De-asserting RX_GLOBAL_RESET allows the Rx PHY to begin processing packets.
467void mimo_ofdmRx_enable(){
468   
469    //Clear any stale interrupts; this should never really be required
[1169]470    warpphy_clearRxPktStatus();
[1028]471   
472    //De-asert the global reset
473    ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) & ~RX_GLOBAL_RESET);
474   
475    return;
476}
477
478///@brief Holds the OFDM Rx PHY in reset
479///
480///Asserting the RX_GLOBAL_RESET bit clears nearly all the state in the OFDM Rx. Configuration registers are not cleared.
481void mimo_ofdmRx_disable(){
482   
483    //Assert the global reset
484    ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) | RX_GLOBAL_RESET);
485
486    //Clear any stale interrupts; this should never really be required
[1169]487    warpphy_clearRxPktStatus();
[1028]488   
489    return;
490}
491
492///@brief Configures options in the Rx PHY
493///
494///@param someOptions 32-bit options value, composed on bitwise OR'd values from warpphy.h
[1645]495///@param blockingStatusBits Configures which PHY Rx events block future receptions (good/bad header/payload)
[1169]496void mimo_ofdmRx_setOptions(unsigned int someOptions, unsigned int blockingStatusBits){
[1028]497   
498    //Write the full controlBits register
499    ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, someOptions);
500   
501    //The interrupt control bits are in the Interrupt_PktBuf_Ctrl register - bits[7:4]
502    //Clear the interrupt control bits
503    ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) & 0xFFFFFF00);
504   
505    //Write just the interrupt control bits
[1169]506    ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) | (ALL_STATUSBITS_ENABLE & blockingStatusBits));
[1028]507   
508    return;
509}
510
511///@brief Returns the current value of the Rx PHY configuration register
512///
513/// Returns the value of the OFDM Rx ControlBits register. Use the bit masks from warpphy.h to decode the indivitual bits.
514unsigned int mimo_ofdmRx_getOptions(){
515   
516    return ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR);
517}
518
519
520///@brief Holds the OFDM Tx in reset
521///
522/// Holds the OFDM Tx in reset; this prevents any state changes in the Tx PHY. Configuration registers are not affected.
523void mimo_ofdmTx_disable(){
524   
525    //Assert the OFDM Tx master reset and pktDone reset
[1169]526    ofdm_txrx_mimo_WriteReg_Tx_Start_Reset_Control(OFDM_BASEADDR, TX_MASTER_RESET);
[1028]527   
528    return;
529}
530
531///@brief Releases the OFDM Tx reset
532///
533/// Releases the OFDM Tx reset
534void mimo_ofdmTx_enable(){
535   
536    //Assert then clear the OFDM Tx master reset and pktDone reset
[1169]537    ofdm_txrx_mimo_WriteReg_Tx_Start_Reset_Control(OFDM_BASEADDR, TX_MASTER_RESET);
[1028]538    ofdm_txrx_mimo_WriteReg_Tx_Start_Reset_Control(OFDM_BASEADDR, 0x0);
539   
540    return;
541}
542
543
544///@brief Initiates the transmission of a packet
545///
546///Starts the transmission of a packet from the OFDM Tx PHY. If blocking is enabled, this function returns only
547///after the transmission finishes. In this mode, the radio receiver is automatically re-enabled. If blocking is disabled,
548///the receiver must be re-enabled in user code later.
549///
[1645]550///@param block DEPRECATED Selects whether this funciton blocks until the transmission finishes; use TXBLOCK or TXNOBLOCK
[1176]551inline int warpphy_pktTx(unsigned int block){
[1028]552   
[1164]553   
[1028]554    /* Should there be a check here whether the Rx PHY is receiving a packet?
555     And what should happen if it is? It's sort of carrier sensing, but if
556     CSMA is disabled, should the Tx pkt be discarded, or held until the Rx
557     is no longer busy...
558     */
[1176]559   
[1208]560    //Pulse the PHY's TxEn register bit. This will propogate to the radio bridge to activate
561    // the radio controller's Tx state machine for whatever radio is enabled (by setAntennaMode() )
562    mimo_ofdmTx_setStartTx(1);
563    mimo_ofdmTx_setStartTx(0);
[1176]564   
[1169]565    //Sleep long enough for the PHY to start transmitting; depends on second argument to SetTxTiming
566    usleep(6);
[1028]567   
568    //Return successfully
569    return 0;
570}
571
572///@brief Polls PHY transmitter and re-enables reception upon completion
573///
574///This function blocks until the transmitter is complete and then re-enables
575///reception by enabing the radio receiver and enabling packet detection.
576int warpphy_waitForTx(){
[1169]577
[1164]578    //warpmac_setDebugGPIO(0xF);
[1169]579
[1028]580    //Poll the PHY transmitter until it's finished transmitting
[1203]581    while(ofdm_txrx_mimo_ReadReg_Tx_PktRunning(OFDM_BASEADDR) & OFDM_TX_BUSY) {
[1169]582        //warpmac_incrementLEDLow();
[1164]583    }
[1169]584
[1631]585    //Workaround for very rare PHY race condition, where a goodHeader event occurred immediately
586    // before the transmission
587    warpphy_clearRxPktStatus();
588
[1028]589    return 0;
590}
591
592
593///@brief Sets the packet buffer indicies for the OFDM Tx and Rx PHY.
594///
595///The PLB_BRAM used a the PHY packet buffer is large enough to hold many PHY packets.
596///This BRAM is divided into many sub-buffers; the PHY can be set to use any sub-buffer for Tx or Rx.
597///
598///@param txBufOffset 6-bit integer selecting the sub-buffer for the PHY Tx
599///@param rxBufOffset 6-bit integer selecting the sub-buffer for the PHY Rx
600void warpphy_setBuffs(unsigned char txBufOffset, unsigned char rxBufOffset){
601   
602    //TxRx_Interrupt_PktBuf_Ctrl[21:16] compose the Rx buffer offset
603    //TxRx_Interrupt_PktBuf_Ctrl[13:8]  compose the Tx buffer offset
604
605    //First, zero out the current pkt buff offsets
606    //Preserve the bottom 8 bits of the register (used for interrupt control)
607    ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) & 0x000000FF);
608   
609    //Then write the new pkt buff offsets
610    ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR,
611        ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) |
612        ( (txBufOffset & 0x3F) << 8 ) |
613        ( (rxBufOffset & 0x3F) << 16 )
614    );
615
616    return;
617}
618
[1375]619void warpphy_AFrecordEnable(unsigned char recordEn)
620{
621    if(recordEn)
622    {
623        mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | AF_SAVEWAVEFORM, activePHYStatusBits);
624    }
625    else
626    {
627        mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(AF_SAVEWAVEFORM), activePHYStatusBits);
628    }
629   
630    return;
631}
632
[1208]633///@brief Configures the PHY for the chosen antenna modes (SISO, Alamouti, multiplexing, etc.)
634///
635///@param txMode Constant (defined in warphphy.h) specifying the Tx antenna mode
636///@param rxMode Constant (defined in warphphy.h) specifying the Rx antenna mode
637int warpphy_setAntennaMode(unsigned int txMode, unsigned int rxMode)
638{
639    //Reset the Tx and Rx PHYs during this reconfiguration
640    // This will interrupt any active Tx/Rx events but won't clear any registers
641    mimo_ofdmRx_disable();
642    mimo_ofdmTx_disable();
[1028]643   
[1226]644    //Tx configuration
[1208]645    if(txMode != ANTMODE_UNCHANGED)
646    {
647        //Update the gloabl variable (used throughout to calculate "magic" numbers for the PHY)
648        warpphy_txAntMode = txMode;
[1028]649
[1208]650        //Take software control and disable both radio's Tx paths
651        // The correct radios will be re-enabled below
652        WarpRadio_v1_TxEnSoftControlEnable(BOTH_RADIOS);
653        WarpRadio_v1_TxRxDisable(BOTH_RADIOS);
[1028]654
[1226]655        //Enable hardware Tx control of either or both radios
656        switch(txMode & ANTMODE_MASK_ANTSEL)
[1208]657        {
[1226]658            case ANTMODE_ANTSEL_RADA:
[1208]659                activeRadios_Tx = FIRST_RADIO;
660                WarpRadio_v1_TxEnSoftControlDisable(FIRST_RADIO);
[1226]661                break;
[1208]662               
[1226]663            case ANTMODE_ANTSEL_RADB:
664                activeRadios_Tx = SECOND_RADIO;
665                WarpRadio_v1_TxEnSoftControlDisable(SECOND_RADIO);
666                break;
667               
668            case ANTMODE_ANTSEL_BOTHRADS:
669                activeRadios_Tx = BOTH_RADIOS;
670                WarpRadio_v1_TxEnSoftControlDisable(BOTH_RADIOS);
671                break;
672
673            default:
674                xil_printf("Invalid Tx antenna mode!\r\n");
675                return -1;
676                break;
677        }
678
679        //Configure the PHY's Tx mode
680        switch(txMode & ANTMODE_MASK_PHYMODE)
681        {
682            case PHYMODE_SISO:
[1208]683                //Set SISO mode, disable MIMO modes in the Tx PHY registers
[1226]684                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & ~(TX_ALAMOUTI_MODE) );
[1208]685                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() | TX_SISO_MODE);
[1226]686                break;
687               
688            case PHYMODE_2X2MULT:
689                //Disable SISO/Alamouti modes in the Tx PHY registers
690                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & ~(TX_SISO_MODE | TX_ALAMOUTI_MODE) );
691                break;
692
693            case PHYMODE_ALAMOUTI:
694                //Set Alamouti mode, disable SISO mode in the Tx PHY registers
695                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & ~(TX_SISO_MODE) );
696                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() | TX_ALAMOUTI_MODE);
697                break;
698
[1208]699            default:
[1226]700                xil_printf("Invalid Tx PHY mode!\r\n");
701                return -1;
702                break;
[1208]703        }
[1226]704
705        //Configure the PHY's Tx antenna configuration
706        switch(txMode & ANTMODE_MASK_PHYANTCFG)
707        {
708            case PHYANTCFG_TX_NORMAL:
709                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & ~(TX_SWAP_ANTENNAS) );
710                break;
711
712            case PHYANTCFG_TX_SWAPPED:
713                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() | TX_SWAP_ANTENNAS);
714                break;
715
716            default:
717                xil_printf("Invalid Tx PHYANT mode!\r\n");
718                return -1;
719                break;
720        }
[1208]721    }
[1110]722
[1208]723    if(rxMode != ANTMODE_UNCHANGED)
724    {
725        //Update the gloabl variable (used throughout to calculate "magic" numbers for the PHY)
726        warpphy_rxAntMode = rxMode;
[1028]727
[1208]728        //Take software control and disable both radio's Rx paths
729        // The correct radios will be re-enabled below
730        WarpRadio_v1_RxEnSoftControlEnable(BOTH_RADIOS);
731        WarpRadio_v1_TxRxDisable(BOTH_RADIOS);
[1226]732   
733        //Enable hardware Rx control of either or both radios
734        switch(rxMode & ANTMODE_MASK_ANTSEL)
[1208]735        {
[1226]736            case ANTMODE_ANTSEL_RADA:
[1208]737                activeRadios_Rx = FIRST_RADIO;
738                WarpRadio_v1_RxEnSoftControlDisable(FIRST_RADIO);
[1226]739                ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMask(PKTDET_MASK_ANTA);
740                break;
[1208]741               
[1226]742            case ANTMODE_ANTSEL_RADB:
743                activeRadios_Rx = SECOND_RADIO;
744                WarpRadio_v1_RxEnSoftControlDisable(SECOND_RADIO);
745                ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMask(PKTDET_MASK_ANTB);
746                break;
[1208]747               
[1226]748            case ANTMODE_ANTSEL_BOTHRADS:
749                activeRadios_Rx = BOTH_RADIOS;
750                WarpRadio_v1_RxEnSoftControlDisable(BOTH_RADIOS);
751                ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMask(PKTDET_MASK_ANTA | PKTDET_MASK_ANTB);
752                break;
753               
754            default:
755                xil_printf("Invalid Rx antenna mode!\r\n");
756                return -1;
757                break;
758        }
759       
760       
761        //Configure the PHY's Rx mode
762        switch(rxMode & ANTMODE_MASK_PHYMODE)
763        {
764            case PHYMODE_SISO:
[1208]765                //Set SISO mode, disable MIMO modes in the Rx PHY registers
[1226]766                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(RX_ALAMOUTI_MODE), activePHYStatusBits);
[1208]767                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | RX_SISO_MODE, activePHYStatusBits);
[1226]768                mimo_ofdmRx_setRxScaling(0x10001000); 
769                break;
770               
771            case PHYMODE_2X2MULT:
772                //Disable SISO/Alamouti modes in the Rx PHY registers
773                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(RX_ALAMOUTI_MODE | RX_SISO_MODE), activePHYStatusBits);
774                mimo_ofdmRx_setRxScaling(0x08000800); 
775                break;
776               
777            case PHYMODE_ALAMOUTI:
778                //Set Alamouti mode, disable SISO mode in the Rx PHY registers
779                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(RX_SISO_MODE), activePHYStatusBits);
780                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() |  RX_ALAMOUTI_MODE, activePHYStatusBits);
781                mimo_ofdmRx_setRxScaling(0x08000800); 
782                break;
783               
[1208]784            default:
[1226]785                xil_printf("Invalid Rx PHY mode!\r\n");
786                return -1;
787                break;
[1208]788        }
[1226]789       
790        //Configure the PHY's Rx antenna configuration
791        switch(rxMode & ANTMODE_MASK_PHYANTCFG)
792        {
793            case PHYANTCFG_RX_NORMAL:
794                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(SISO_ON_ANTB | SWITCHING_DIV_EN), activePHYStatusBits);
795                break;
796               
797            case PHYANTCFG_RX_SWAPPED:
798                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(SWITCHING_DIV_EN), activePHYStatusBits);
799                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | SISO_ON_ANTB, activePHYStatusBits);
800                break;
801               
802            case PHYANTCFG_RX_SELDIV:
803                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(SISO_ON_ANTB), activePHYStatusBits);
804                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | SWITCHING_DIV_EN, activePHYStatusBits);
805                break;
806               
807            default:
808                xil_printf("Invalid Rx PHYANT mode!\r\n");
809                return -1;
810                break;
811               
812        }
[1208]813    }
[1028]814
[1208]815    //Finally, re-enbale the PHY Tx/Rx subsystems
816    mimo_ofdmRx_enable();
817    mimo_ofdmTx_enable();
[1210]818
[1226]819    //Pulse the PHY's RxEn register to re-enable receive paths on the active radios
[1210]820    // This must occur after calling ofdmRx_enable, as this register's output is ignored while the Rx PHY is in reset
821    mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | PHY_RADIO_RXEN, activePHYStatusBits);
822    mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(PHY_RADIO_RXEN), activePHYStatusBits);
[1028]823   
[1208]824    return 0;
[1028]825}
826
[1232]827///@brief Fast and dangerous way of switching TX PHY mode... note... this function cannot change physical radios
828///
829///@param txMode Constant (defined in warphphy.h) specifying the Tx antenna mode
830int warpphy_setTxAntennaSwap(unsigned int txMode)
831{
832    //Tx configuration
833    if(txMode != ANTMODE_UNCHANGED)
834    {
835        //Update the gloabl variable (used throughout to calculate "magic" numbers for the PHY)
836        warpphy_txAntMode = txMode;
837       
838        //Configure the PHY's Tx antenna configuration
839        switch(txMode & ANTMODE_MASK_PHYANTCFG)
840        {
841            case PHYANTCFG_TX_NORMAL:
842                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & ~(TX_SWAP_ANTENNAS) );
843                break;
844               
845            case PHYANTCFG_TX_SWAPPED:
846                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() | TX_SWAP_ANTENNAS);
847                break;
848               
849            default:
850                xil_printf("Invalid Tx PHYANT mode!\r\n");
851                return -1;
852                break;
853        }
854    }
855       
856    return 0;
857}
[1049]858
[1260]859inline void warpphy_clearAutoResponseFlag(unsigned char flagID){
[1232]860
[1260]861    switch(flagID)
862    {
863        case AUTORESP_FLAGID_A:
864            ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) | (AUTORESP_FLAGA_RST));
865            ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) & ~(AUTORESP_FLAGA_RST));
866            break;
867        case AUTORESP_FLAGID_B:
868            ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) | (AUTORESP_FLAGB_RST));
869            ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) & ~(AUTORESP_FLAGB_RST));
870            break;
871    }
[1232]872
[1260]873    return;
874}
875
[1028]876///@brief Sets the number of training symbol periods used per packet
877///
878///Configures the number of training symbols which are transmitted with each packet. The Tx and Rx nodes must be
879///configured for the same number. In SISO mode, the single channel is trained c times. In MIMO mode, each channel
880///is trained c/2 times
881///
[1645]882///@param numTraining number of training periods; must be even
[1169]883void warpphy_setNumTrainingSyms(unsigned int numTraining){
884    //Update the global variable; used each time a packet is transmitted
885    numTrainingSyms = numTraining;
[1028]886   
[1537]887    //Configure the PHY
888    warpphy_setTxNumSyms(numBaseRate, numTrainingSyms);
889    warpphy_setRxNumSyms(numBaseRate, numTrainingSyms);
[1028]890}
891
[1537]892void warpphy_setNumBaseRateSyms(unsigned int numSyms){
893    //Update the global variable; used each time a packet is transmitted
894    numBaseRate = numSyms;
895   
896    //Configure the PHY
897    warpphy_setTxNumSyms(numBaseRate, numTrainingSyms);
898    warpphy_setRxNumSyms(numBaseRate, numTrainingSyms);
899}
900
[1028]901///@brief Configure the flexible modulation/demodulation in the OFDM PHY
902///
903///The OFDM PHY supports flexible modulation, allowing any combination of schemes per subcarrier
904///Currently this code supports simple dynamic modulation, with 48 of 64 subcarriers assigned to carry data, 4 for pilots and 12 empty.
905///The modulation scheme in the 48 data subcarriers is set by this funciton.
[1616]906///NOTE: When FEC is enabled the modulation rate of all data bearing subcarriers must be the same and one of BPSK/QPSK/16-QAM
[1028]907///
908///@param baseRate Modulation scheme for base rate symbols
[1208]909///@param TxAntAFullRate Modulation scheme for Tx full rate symbols on antenna A
910///@param TxAntBFullRate Modulation scheme for Tx full rate symbols on antenna B
911///@param RxAntAFullRate Modulation scheme for Rx full rate symbols on antenna A
912///@param RxAntBFullRate Modulation scheme for Rx full rate symbols on antenna B
913void warpphy_set_modulation(unsigned char baseRate, unsigned char TxAntAFullRate, unsigned char TxAntBFullRate, unsigned char RxAntAFullRate, unsigned char RxAntBFullRate)
[1028]914{
915    unsigned int modIndex;
[1049]916
[1028]917    //Define the standard subcarrier mapping - 48 used for data (0xF here), 4 pilots & 12 unused (0x0 here)
918    // The vector contains 192 elements:
919    //    0:63 - Antenna A full rate masks for subcarriers [0,1,2,...31,-31,-30,...-1]
920    //  64:127 - Antenna B full rate masks for subcarriers [0,1,2,...31,-31,-30,...-1]
921    // 128:191 - Base rate masks for subcarriers [0,1,2,...31,-31,-30,...-1]
922    //The default masks are 3 copies of the same 64-length vector; yes, it's inefficient, but this scheme maintains flexibility in changing the mapping per antenna
923    unsigned char modMasks[192] = {
924            0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF,
925            0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF,
926            0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF, 0x0, 0xF, 0xF, 0xF, 0xF, 0xF, 0xF
927    };
928
929    //The PHY's shared memories for modulation masks have 192 4-bit entries; each entry's address is 4-byte aligned (hence the *sizeof(int) below )
[1208]930    if(TxAntAFullRate != MOD_UNCHANGED)
931    {
932        //Configure Tx antenna A full rate
933        for(modIndex=0; modIndex<64; modIndex++)
934        {
935            XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & TxAntAFullRate);
936        }
937    }
[1028]938
[1208]939    if(TxAntBFullRate != MOD_UNCHANGED)
940    {
941        //Configure Tx antenna B full rate
942        for(modIndex=64; modIndex<128; modIndex++)
943        {
944            XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & TxAntBFullRate);
945        }
946    }
[1028]947   
[1208]948    if(RxAntAFullRate != MOD_UNCHANGED)
949    {
950        //Configure Rx antenna A full rate
951        for(modIndex=0; modIndex<64; modIndex++)
952        {
953            XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & RxAntAFullRate);
954        }
955    }
[1169]956
[1208]957    if(RxAntBFullRate != MOD_UNCHANGED)
[1028]958    {
[1208]959        //Configure Rx antenna B full rate
960        for(modIndex=64; modIndex<128; modIndex++)
961        {
962            XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & RxAntBFullRate);
963        }
[1028]964    }
[1208]965   
966    //Update the global baseRate modulation variable
967    if(baseRate != MOD_UNCHANGED)
[1028]968    {
[1208]969        baseRateMod = baseRate;
970   
971        //Configure the Tx and Rx base rate
972        for(modIndex=128; modIndex<192; modIndex++)
973        {
974            XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & baseRate);
975            XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & baseRate);
976        }
[1028]977    }
[1169]978
[1028]979    return;
980}
981
982///@brief Set the center frequency of the radio transceivers
983///@param band Selects 2.4GHz or 5GHz bands (using GHZ_2 or GHZ_5)
[1645]984///@param chan Selects the channel number in the chosen band
[1028]985///@return Returns -1 if an invalid band or channel was specified; otherwise returns the new center frequency in MHz
[1169]986int warpphy_setChannel(unsigned char band, unsigned int chan){
[1028]987    int newFreq = -1;
988   
989    if (band == GHZ_2){
[1169]990        newFreq = WarpRadio_v1_SetCenterFreq2GHz(chan, FIRST_RADIO | SECOND_RADIO);
[1028]991    }
992    if (band == GHZ_5){
[1169]993        newFreq = WarpRadio_v1_SetCenterFreq5GHz(chan, FIRST_RADIO | SECOND_RADIO);
[1028]994    }
[1064]995       
[1028]996    return newFreq;
997}
998
999///@brief Set the center frequency of the radio transceivers independently
1000///@param antA_band Selects 2.4GHz or 5GHz bands (using GHZ_2 or GHZ_5) for antenna A
1001///@param antB_band Selects 2.4GHz or 5GHz bands (using GHZ_2 or GHZ_5) for antenna B
1002///@param antA_chan Selects the channel number in the chosen band for antenna A
1003///@param antB_chan Selects the channel number in the chosen band for antenna B
1004///@return Returns -1 if an invalid band or channel was specified; otherwise returns the new center frequency for antenna A in MHz
1005int warpphy_setSeparateChannels(unsigned char antA_band, unsigned int antA_chan, unsigned char antB_band, unsigned int antB_chan){
1006
1007    int newFreq_A = -1;
1008    int newFreq_B = -1;
1009   
1010    if (antA_band == GHZ_2)
1011        newFreq_A = WarpRadio_v1_SetCenterFreq2GHz(antA_chan, FIRST_RADIO);
1012    if (antB_band == GHZ_2)
1013        newFreq_B = WarpRadio_v1_SetCenterFreq2GHz(antB_chan, SECOND_RADIO);
1014    if (antA_band == GHZ_5)
1015        newFreq_A = WarpRadio_v1_SetCenterFreq5GHz(antA_chan, FIRST_RADIO);
1016    if (antB_band == GHZ_5)
1017        newFreq_B = WarpRadio_v1_SetCenterFreq5GHz(antB_chan, SECOND_RADIO);
1018    if(newFreq_A == -1 || newFreq_B == -1)
1019        return -1;
1020    else
1021        return newFreq_A;
1022}
1023
1024///@brief Applies TX DC offset calibration to the specified radios; the calibration values are stored in the radio's EEPROM
1025///@param radioSelection OR'd combinaton of RADIOx_ADDR values, specifying which radios to update
1026///@return Returns -1 if an EEPROM error occurs; returns 0 if successful
1027int warpphy_applyTxDCOCalibration(unsigned int radioSelection)
1028{
1029    int eepromStatus = 0;
1030    short calReadback = 0;
1031    signed short best_I, best_Q;
[1064]1032    unsigned char radioNum;
[1712]1033    Xuint8 memory[8], version, revision, valid;
[1064]1034    Xuint16 serial;
[1028]1035
[1064]1036    //Radio selection will be 0x11111111, 0x22222222, 0x44444444 or 0x88888888
1037    // corresponding to radios in slots 1, 2, 3 or 4
1038    // We need the slot number to initialize the EEPROM
1039    radioNum = (radioSelection & 0xF) == 1 ? 1 : ( (radioSelection & 0xF) == 2 ? 2 : ( (radioSelection & 0xF) == 4 ? 3 : 4 ) );
[1640]1040//  xil_printf("Applying TxDCO correction for radio %d\r\n", radioNum);
[1064]1041
1042    //Mimic the radio test code, in hopes of a more stable EEPROM read...
1043    //Choose the EEPROM on the selected radio board; second arg is [0,1,2,3,4] for [FPGA, radio1, radio2, radio3, radio4]
[1712]1044    eepromStatus = WarpEEPROM_EEPROMSelect((unsigned int *)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, 0);
[1064]1045    if(eepromStatus != 0)
1046    {
1047        xil_printf("EEPROM Select Failed!\r\n");
[1712]1048        return -1;
[1064]1049    }
[1028]1050   
[1064]1051    //Initialize the EEPROM controller
[1712]1052    eepromStatus = WarpEEPROM_Initialize((unsigned int *)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR);
[1064]1053    if(eepromStatus != 0)
1054    {
1055        xil_printf("EEPROM Init Returned %x\r\n", eepromStatus);
1056        xil_printf("EEPROM Init Failed!\r\n");
[1712]1057        return -1;
[1064]1058    }
1059
1060    //Select the EEPROM on the current radio board
[1712]1061    eepromStatus = WarpEEPROM_EEPROMSelect((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, radioNum);
[1064]1062
1063    if(eepromStatus != 0)
1064    {
1065        xil_printf("TxDCO: EEPROM error\r\n");
1066        return -1;
1067    }
1068   
1069    //Read the first page from the EERPOM
[1712]1070    WarpEEPROM_ReadMem((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, 0, 0, memory);
[1064]1071    version = (memory[0] & 0xE0) >> 5;
1072    revision = (memory[1] & 0xE0) >> 5;
1073    valid = memory[1] & 0x1F;
1074
[1640]1075//  xil_printf("\r\n\r\nEEPROM Values for Radio Board in Slot %d\r\n", radioNum);
[1064]1076
[1640]1077//  xil_printf("    WARP Radio Board Version %d.%d\r\n", version, revision);
[1064]1078
[1712]1079    serial = WarpEEPROM_ReadWARPSerial((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR);
[1064]1080
[1640]1081//  xil_printf("    Serial Number (WARP): WR-a-%05d\r\n", serial);
[1064]1082
[1712]1083    WarpEEPROM_ReadDSSerial((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, memory);
[1640]1084//  print("    EEPROM Hard-wired Serial Number: ");
1085//  for(i=1;i<7;i++)
1086//      xil_printf(" %x",memory[7-i]);
1087//  xil_printf("\r\n\r\n");
[1064]1088    //Read the Tx DCO values
[1712]1089    calReadback = WarpEEPROM_ReadRadioCal((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, 2, 1);
[1064]1090   
1091    //Scale the stored values
1092    best_I = (signed short)(((signed char)(calReadback & 0xFF))<<1);
1093    best_Q = (signed short)(((signed char)((calReadback>>8) & 0xFF))<<1);
1094   
[1640]1095    xil_printf("\t\tTxDCO values for radio %d - I: %d\tQ: %d\r\n", radioNum, best_I, best_Q);
[1064]1096   
1097    //Finally, write the Tx DCO values to the DAC
1098    WarpRadio_v1_DACOffsetAdj(ICHAN, best_I, radioSelection);
1099    WarpRadio_v1_DACOffsetAdj(QCHAN, best_Q, radioSelection);
1100   
[1028]1101    return 0;
1102}
1103
1104
1105/******* AGC core control functions ********/
[1477]1106
1107unsigned int warpphy_returnGainsDB(){
1108/*  int rfGain;
1109    switch(warpphy_returnAGCgainRF(antenna)){
1110        case 0:
1111            rfGain=1;
1112        break;
1113        case 1:
1114            rfGain=16;
1115        break;
1116        case 2:
1117            rfGain=31.5;
1118        break;
1119    }
1120    xil_printf("BBGAIN %d\r\n",(warpphy_returnAGCgainBB(antenna)<<1));
1121    return ((warpphy_returnAGCgainBB(antenna)<<1) + rfGain);
1122*/
1123
1124unsigned int rfGain,bbGain,gainDB,rfGainDB,bbGainDB;
1125unsigned int agcGains;
1126   
1127
1128        agcGains = ofdm_AGC_GetGains();
1129        rfGain = agcGains&0x3;
1130        bbGain = (agcGains>>2)&0x1F;
1131       
1132        switch(rfGain){
1133        case 0:
1134            rfGainDB=1;
1135        break;
1136        case 1:
1137            rfGainDB=1;
1138        break;
1139        case 2:
1140            rfGainDB=16;
1141        break;
1142        case 3:
1143            rfGainDB=32; //really 31.5...
1144        break;
1145    }
1146   
1147    bbGainDB=bbGain<<1;
1148    gainDB = bbGainDB + rfGainDB;
1149       return gainDB;
1150
1151   
1152   
1153   
1154}
1155
1156
1157
1158
[1594]1159inline void ofdm_AGC_SetDCO(unsigned int AGCstate){
[1597]1160
[1594]1161    // register bits:
1162    // [1:0]- DCO mode
1163    //   0x0=bypass DCO correction entirely
1164    //   0x1=bypass IIR filter, allow subtraction
1165    //   0x2=enable IIR filter, allow subtraction
1166    // [2]- enable subtraction (only has effect if [1:0] != 0)
[1597]1167    // Valid values:
1168    // [1 1 0]=0x6: Enable filter, use subtraction
1169    OFDM_AGC_MIMO_WriteReg_Bits(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, (AGCstate & 0x7));
[1028]1170   
1171    return;
1172}
1173
1174void ofdm_AGC_Reset(){
1175   
1176    // Cycle the agc's software reset port
1177   
1178    OFDM_AGC_MIMO_WriteReg_SRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 1);
1179    usleep(10);
1180    OFDM_AGC_MIMO_WriteReg_SRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
1181    usleep(100);
1182   
1183    return;
1184}
1185
1186
1187void ofdm_AGC_MasterReset(){
1188   
1189    // Cycle the master reset register in the AGC and enable it
1190   
1191    OFDM_AGC_MIMO_WriteReg_AGC_EN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
1192    usleep(10);
1193    OFDM_AGC_MIMO_WriteReg_MRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
1194    usleep(10);
1195    OFDM_AGC_MIMO_WriteReg_MRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 1);
1196    usleep(10);
1197    OFDM_AGC_MIMO_WriteReg_MRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
1198    usleep(10);
1199    OFDM_AGC_MIMO_WriteReg_AGC_EN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 1);
1200   
1201    return;
1202}
1203
1204void ofdm_AGC_Initialize(int noise_estimate){
1205   
1206    int g_bbset = 0;
1207   
1208    // First set all standard parameters
1209   
1210    // Turn off both resets and the master enable
1211    OFDM_AGC_MIMO_WriteReg_AGC_EN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
1212    OFDM_AGC_MIMO_WriteReg_SRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
1213    OFDM_AGC_MIMO_WriteReg_MRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
1214   
1215    // An adjustment parameter
1216    OFDM_AGC_MIMO_WriteReg_ADJ(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 8);
1217   
1218    // Timing for the DC-offset correction
[1597]1219//  OFDM_AGC_MIMO_WriteReg_DCO_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x46403003); //as used through v21
1220    OFDM_AGC_MIMO_WriteReg_DCO_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x463C2C03); //
[1028]1221   
1222    // Initial baseband gain setting
1223    OFDM_AGC_MIMO_WriteReg_GBB_init(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 52);
1224   
1225    // RF gain AGCstate thresholds
[1032]1226    OFDM_AGC_MIMO_WriteReg_Thresholds(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 
1227        ((AGC_THRESH_1&0xFF)<<16) +
1228        ((AGC_THRESH_2&0xFF)<<8) + 
1229         (AGC_THRESH_3&0xFF)
1230    );
[1049]1231   
[1028]1232    // Overall AGC timing
[1524]1233//  OFDM_AGC_MIMO_WriteReg_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x9A962A28);//0x826E3C0A;
[1597]1234//  OFDM_AGC_MIMO_WriteReg_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0xAA962A28);//added time between GBB change and AGC_DONE (pom 2010-06-19)
1235//  OFDM_AGC_MIMO_WriteReg_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0xEAC65A58);
[1642]1236    OFDM_AGC_MIMO_WriteReg_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0xFAC62A28);//delayed I/Q sensitive steps by 12 samples for new Rx filter latency
[1028]1237   
1238    // vIQ and RSSI average lengths
1239    OFDM_AGC_MIMO_WriteReg_AVG_LEN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x10F); //103
1240   
[1594]1241    // Disable DCO, disable DCO subtraction
[1028]1242    OFDM_AGC_MIMO_WriteReg_Bits(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x0);
1243   
1244    // Compute and set the initial g_BB gain value from the noise estimate
1245    // The initial g_bb sets noise to -19 db, assuming 32 db RF gain
1246   
1247    g_bbset = -19 - 32 - noise_estimate;
1248    OFDM_AGC_MIMO_WriteReg_GBB_init(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, g_bbset);
1249   
1250    // Perform a master reset
1251    ofdm_AGC_MasterReset();
1252   
1253    // Agc is now reset and enabled, ready to go!
1254    return;
1255}
1256
1257
1258void ofdm_AGC_setNoiseEstimate(int noise_estimate){
1259    int g_bbset;
1260   
1261    g_bbset = -19 - 32 - noise_estimate;
1262   
1263    OFDM_AGC_MIMO_WriteReg_GBB_init(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, g_bbset);
1264   
1265    return;
1266}
1267
1268unsigned int ofdm_AGC_GetGains(void){
1269   
1270    unsigned int gBB_A, gRF_A, gBB_B, gRF_B, gains;
1271   
1272    // Get the gains from the registers
1273    gBB_A = OFDM_AGC_MIMO_ReadReg_GBB_A(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR);
1274    gRF_A = OFDM_AGC_MIMO_ReadReg_GRF_A(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR);
1275   
1276    gBB_B = OFDM_AGC_MIMO_ReadReg_GBB_B(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR);
1277    gRF_B = OFDM_AGC_MIMO_ReadReg_GRF_B(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR);
1278   
1279    // First concatenate the two radios together, into the gRF register
1280    // 2 lowest bits are RF, 5 higher bits are BB, last bit is unused
1281    // Multiply by 2^2, shift gBB right by 2 bits
1282   
1283    gRF_A = gRF_A + (gBB_A * 4);
1284    gRF_B = gRF_B + (gBB_B * 4);
1285   
1286    // Multiply by 2^8 shift gRF right by 8 bits
1287    gains = gRF_A + (gRF_B * 256);
1288   
1289    // Returns hi[0 gBB_B g_RF_B | 0 g_BB_A g_RF_A]lo
1290    return gains;
1291}
1292
1293void ofdm_AGC_SetTarget(unsigned int target){
1294    OFDM_AGC_MIMO_WriteReg_T_dB(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, target);
1295    return;
1296}
1297/******* END AGC core control functions ********/
1298
[1049]1299
1300
1301/******* WARP Timer core control functions *******/
1302void warp_timer_start(unsigned char timer) {
[1177]1303    warp_timer_WriteReg_control(warp_timer_ReadReg_control() | (TIMER_MASK_CALC(timer) & TIMER_CONTROL_START_MASK));
1304    warp_timer_WriteReg_control(warp_timer_ReadReg_control() & ~(TIMER_MASK_CALC(timer) & TIMER_CONTROL_START_MASK));
[1049]1305}
1306
[1177]1307void warp_timer_pause(unsigned char timer) {
1308    warp_timer_WriteReg_control(warp_timer_ReadReg_control() | (TIMER_MASK_CALC(timer) & TIMER_CONTROL_PAUSE_MASK));
[1049]1309}
[1177]1310
[1049]1311void warp_timer_resume(unsigned char timer) {
[1177]1312    warp_timer_WriteReg_control(warp_timer_ReadReg_control() & ~(TIMER_MASK_CALC(timer) & TIMER_CONTROL_PAUSE_MASK));
[1049]1313}
1314
1315void warp_timer_setMode(unsigned char timer, unsigned char mode) {
1316    if(mode == 1)
[1177]1317        warp_timer_WriteReg_control(warp_timer_ReadReg_control() | (TIMER_MASK_CALC(timer) & TIMER_CONTROL_MODE_MASK));
[1049]1318    else
[1177]1319        warp_timer_WriteReg_control(warp_timer_ReadReg_control() & ~(TIMER_MASK_CALC(timer) & TIMER_CONTROL_MODE_MASK));
[1049]1320}
1321
[1177]1322void warp_timer_resetDone(unsigned char timer) {
1323    warp_timer_WriteReg_control(warp_timer_ReadReg_control() | (TIMER_MASK_CALC(timer) & TIMER_CONTROL_RESETDONE_MASK));
1324    warp_timer_WriteReg_control(warp_timer_ReadReg_control() & ~(TIMER_MASK_CALC(timer) & TIMER_CONTROL_RESETDONE_MASK));
[1049]1325}
1326
[1177]1327void warp_timer_resetAllDoneStatus() {
1328    warp_timer_WriteReg_control(warp_timer_ReadReg_control() | (TIMER_CONTROL_RESETDONE_MASK));
1329    warp_timer_WriteReg_control(warp_timer_ReadReg_control() & ~(TIMER_CONTROL_RESETDONE_MASK));
[1049]1330}
1331
[1177]1332void warp_timer_setTimer(unsigned char timer, unsigned int slotTime, unsigned int slotCount) {
[1049]1333    switch(timer) {
1334    case 0:
[1177]1335        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER0_SLOTCOUNT, (Xuint32)(slotCount));
[1279]1336        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS01_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS01_SLOTTIME) & 0xFFFF0000) | slotTime) );
[1049]1337        return;
1338    case 1:
[1177]1339        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER1_SLOTCOUNT, (Xuint32)(slotCount));
[1279]1340        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS01_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS01_SLOTTIME) & 0x0000FFFF) | (slotTime<<16) ) ); 
[1049]1341        return;
1342    case 2:
[1177]1343        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER2_SLOTCOUNT, (Xuint32)(slotCount));
[1279]1344        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS23_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS23_SLOTTIME) & 0xFFFF0000) | slotTime) );
[1049]1345        return;
1346    case 3:
[1177]1347        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER3_SLOTCOUNT, (Xuint32)(slotCount));
[1279]1348        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS23_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS23_SLOTTIME) & 0x0000FFFF) | (slotTime<<16) ) );
[1049]1349        return;
[1177]1350    case 4:
1351        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER4_SLOTCOUNT, (Xuint32)(slotCount));
[1279]1352        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS45_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS45_SLOTTIME) & 0xFFFF0000) | slotTime) );
[1177]1353        return;
1354    case 5:
1355        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER5_SLOTCOUNT, (Xuint32)(slotCount));
[1279]1356        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS45_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS45_SLOTTIME) & 0x0000FFFF) | (slotTime<<16) ) );
[1177]1357        return;
1358    case 6:
1359        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER6_SLOTCOUNT, (Xuint32)(slotCount));
[1279]1360        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS67_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS67_SLOTTIME) & 0xFFFF0000) | slotTime) );
[1177]1361        return;
1362    case 7:
1363        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER7_SLOTCOUNT, (Xuint32)(slotCount));
[1279]1364        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS67_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS67_SLOTTIME) & 0x0000FFFF) | (slotTime<<16) ) );
[1177]1365        return;
1366    default:
1367        return;
[1049]1368    }
1369}
1370
1371unsigned char warp_timer_getStatus(unsigned char timer) {
[1177]1372    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) >> (timer*4)) & 0xf;
[1049]1373}
1374
[1177]1375unsigned char warp_timer_isDone(unsigned char timer) {
1376    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) & TIMER_MASK_CALC(timer) & TIMER_STATUS_DONE_MASK) != 0;
[1049]1377}
1378
1379unsigned char warp_timer_isActive(unsigned char timer) {
[1177]1380    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) & TIMER_MASK_CALC(timer) & TIMER_STATUS_RUNNING_MASK) != 0;
[1049]1381}
1382
1383unsigned char warp_timer_isPaused(unsigned char timer) {
[1177]1384    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) & TIMER_MASK_CALC(timer) & TIMER_STATUS_PASUED_MASK) != 0;
[1049]1385}
1386
1387unsigned int warp_timer_getStatuses() {
1388    return XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS);
1389}
1390
[1177]1391unsigned char warp_timer_getDoneStatus() {
1392    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) & TIMER_STATUS_DONE_MASK);
[1049]1393}
1394
[1177]1395void warp_timer_init(){
1396    //Clear all start/pause/mode/donereset bits
1397    XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_CONTROL, 0);
[1049]1398
[1177]1399    //Set sane values for the slot times and slot counts
1400    warp_timer_setTimer(0, 500, 32);
1401    warp_timer_setTimer(1, 500, 32);
1402    warp_timer_setTimer(2, 500, 32);
1403    warp_timer_setTimer(3, 500, 32);
1404    warp_timer_setTimer(4, 500, 32);
1405    warp_timer_setTimer(5, 500, 32);
1406    warp_timer_setTimer(6, 500, 32);
1407    warp_timer_setTimer(7, 500, 32);
1408
1409    //Clear any stale timer-done status bits
1410    warp_timer_resetAllDoneStatus();
[1049]1411    return;
1412}
[1169]1413/******* END WARP Timer core control functions *******/
[1028]1414
[1103]1415///@brief Set the transmit power (via the radio's RF VGA)
1416///@param txPwr Desired transmit power; must be integer in [0,63]
1417///@return Returns -1 if an invalid power is requested; 0 on success
1418int warpphy_setTxPower(unsigned char txPwr)
1419{
1420    if(txPwr > 63)
1421        return -1;
1422    else
[1169]1423        WarpRadio_v1_SetTxGainTiming(FIRST_RADIO | SECOND_RADIO, (0x3F & txPwr), 0xF, 1);
[1103]1424
1425    return 0;
1426}
[1105]1427
[1633]1428void warpphy_setAutoCorrDetParams(unsigned short corrThresh, unsigned short energyThresh) {
1429    ofdm_txrx_mimo_WriteReg_Rx_PktDetCorr_params(corrThresh, energyThresh);
1430    return;
1431}
1432
[1616]1433void warpphy_setLongCorrThresh(unsigned short thresh) {
[1661]1434    pktDet_carrierSenseThresh = thresh;
[1712]1435    XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RX_PKTDET_LONGCORR_THRESHOLDS, thresh);
[1616]1436}
[1105]1437
[1661]1438void warpphy_setCarrierSenseThresh(unsigned short thresh) {
1439    longCorrThresh = thresh;
1440    ofdm_txrx_mimo_WriteReg_Rx_CSMA_setThresh(pktDet_carrierSenseThresh);
1441}
[1633]1442
[1616]1443void warpphy_setEnergyDetThresh(unsigned short thresh) {
1444    pktDet_energyThresh = thresh;
1445    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setThresh(thresh);
1446}
[1105]1447
[1616]1448
1449void warpphy_setAntBPreambleShift(unsigned char shift)
1450{
1451    mimo_ofdmTx_setControlBits( (mimo_ofdmTx_getOptions() & ~(0xF0)) | ((shift&0xF)<<4) );
[1105]1452}
[1169]1453
1454/*********************************************************************/
1455/* A whole bunch of debugging functions - these will go away someday */
1456/*********************************************************************/
1457
1458#if INCLUDE_WARPPHY_DEBUG_FUNCTIONS
1459
[1316]1460void warpphy_incrementTxScaling(int incr_preamble, int incr_payload)
1461{
1462    txScaling_preamble += incr_preamble;
1463    txScaling_payload += incr_payload;
1464    mimo_ofdmTx_setTxScaling(txScaling_preamble, txScaling_payload);
1465    xil_printf("TxScaling: Preamble = %d\tPayload = %d\r\n", txScaling_preamble, txScaling_payload);
1466    return;
1467}
1468
1469
[1169]1470void warpphy_setPktDlyPlus(){
1471    ofdmRx_pktDetDly++;
1472    xil_printf("+ofdmRx_pktDetDly = %d\r\n", ofdmRx_pktDetDly);
1473    mimo_ofdmRx_setPktDetDly(ofdmRx_pktDetDly);
1474}
1475void warpphy_setPktDlyMinus(){
1476    ofdmRx_pktDetDly--;
1477    xil_printf("-ofdmRx_pktDetDly = %d\r\n", ofdmRx_pktDetDly);
1478    mimo_ofdmRx_setPktDetDly(ofdmRx_pktDetDly);
1479}
1480
1481/*********************/
1482/* Other PHY options */
1483/*********************/
1484
1485void warpphy_set_FFTOffset_Plus(){
1486    RxFFT_Window_Offset++;
1487    mimo_ofdmRx_setFFTWindowOffset(RxFFT_Window_Offset);
1488    xil_printf("Rx FFT Offset: %d\r\n", RxFFT_Window_Offset);
1489}
1490
1491void warpphy_set_FFTOffset_Minus(){
1492    RxFFT_Window_Offset--;
1493    mimo_ofdmRx_setFFTWindowOffset(RxFFT_Window_Offset);
1494    xil_printf("Rx FFT Offset: %d\r\n", RxFFT_Window_Offset);
1495}
1496
1497void warpphy_setNoiseTargetPlus(){
1498    agc_noisePowerEstimate++;
1499    xil_printf("+Noise Estimate = %d\r\n", agc_noisePowerEstimate);
1500    ofdm_AGC_setNoiseEstimate(agc_noisePowerEstimate);
1501}
1502
1503void warpphy_setNoiseTargetMinus(){
1504    agc_noisePowerEstimate--;
1505    xil_printf("-Noise Estimate = %d\r\n", agc_noisePowerEstimate);
1506    ofdm_AGC_setNoiseEstimate(agc_noisePowerEstimate);
1507}
1508
1509void warpphy_setTargetPlus(){
1510    agc_targetRxPowerOut++;
1511    xil_printf("+agc_targetRxPowerOut = %d\r\n", agc_targetRxPowerOut);
1512    ofdm_AGC_SetTarget(agc_targetRxPowerOut);
1513}
1514
1515void warpphy_setTargetMinus(){
1516    agc_targetRxPowerOut--;
1517    xil_printf("-agc_targetRxPowerOut = %d\r\n", agc_targetRxPowerOut);
1518    ofdm_AGC_SetTarget(agc_targetRxPowerOut);
1519}
1520
1521void warpphy_setPktDetPlus(unsigned int offset){
1522    pktDet_energyThresh=pktDet_energyThresh+offset;
1523    //ofdm_pktDetector_mimo_WriteReg_pktDet_avgThresh(PKTDET_BASEADDR, pktDet_energyThresh);
1524    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setThresh(pktDet_energyThresh);
1525    xil_printf("pktDet_energyThresh = %d\r\n",pktDet_energyThresh);
1526}
1527
1528void warpphy_setPktDetMinus(unsigned int offset){
1529    pktDet_energyThresh=pktDet_energyThresh-offset;
1530    //ofdm_pktDetector_mimo_WriteReg_pktDet_avgThresh(PKTDET_BASEADDR, pktDet_energyThresh);
1531    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setThresh(pktDet_energyThresh);
1532   
1533    xil_printf("pktDet_energyThresh = %d\r\n",pktDet_energyThresh);
1534}
1535
[1170]1536void warpphy_setPktDetMinDurPlus(unsigned int offset){
1537    pktDet_threshMinDur = pktDet_threshMinDur + offset;
[1169]1538
[1170]1539    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMinDuration(pktDet_threshMinDur);
1540    xil_printf("Minimum Duration = %d\r\n", pktDet_threshMinDur);
[1169]1541}
1542
[1170]1543void warpphy_setPktDetMinDurMinus(unsigned int offset){
1544    pktDet_threshMinDur = pktDet_threshMinDur - offset;
[1169]1545   
[1170]1546    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMinDuration(pktDet_threshMinDur);
1547    xil_printf("Minimum Duration = %d\r\n", pktDet_threshMinDur);
[1169]1548}
1549
1550void warpphy_setCSMAPlus(unsigned int offset){
1551    pktDet_carrierSenseThresh = pktDet_carrierSenseThresh + offset;
1552
1553    ofdm_txrx_mimo_WriteReg_Rx_CSMA_setThresh(pktDet_carrierSenseThresh);
1554    xil_printf("Carrier Sense Thresh = %d\r\n", pktDet_carrierSenseThresh);
1555}
1556
1557void warpphy_setCSMAMinus(unsigned int offset){
1558    pktDet_carrierSenseThresh = pktDet_carrierSenseThresh - offset;
1559   
1560    ofdm_txrx_mimo_WriteReg_Rx_CSMA_setThresh(pktDet_carrierSenseThresh);
1561    xil_printf("Carrier Sense Thresh = %d\r\n", pktDet_carrierSenseThresh);
1562}
1563
1564void warpphy_setGainPlus(unsigned int offset){
1565    txGain=txGain+offset;
1566    WarpRadio_v1_SetTxGainTiming(FIRST_RADIO | SECOND_RADIO, txGain, 0xF, 2);
1567    xil_printf("TxGain = %x\r\n",txGain);
1568}
1569
1570void warpphy_setGainMinus(unsigned int offset){
1571    txGain=txGain-offset;
1572    WarpRadio_v1_SetTxGainTiming(FIRST_RADIO | SECOND_RADIO, txGain, 0xF, 2);
1573    xil_printf("TxGain = %x\r\n",txGain);
1574}
[1232]1575
[1264]1576
[1169]1577#endif
1578
Note: See TracBrowser for help on using the repository browser.