[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] | 43 | int agc_targetRxPowerOut; |
---|
| 44 | int agc_noisePowerEstimate; |
---|
[1208] | 45 | |
---|
[1028] | 46 | unsigned char baseRateMod; |
---|
| 47 | unsigned int numTrainingSyms; |
---|
[1169] | 48 | unsigned int ofdmRx_pktDetDly; |
---|
[1028] | 49 | unsigned int numBaseRate; |
---|
| 50 | unsigned char txGain; |
---|
[1105] | 51 | unsigned char RxSoftDecodingEn; |
---|
[1616] | 52 | unsigned short pktDet_corrCounterLoad; |
---|
| 53 | unsigned char pktDet_corrWindowStart; |
---|
| 54 | unsigned char pktDet_corrWindowEnd; |
---|
[1028] | 55 | |
---|
[1169] | 56 | unsigned int pktDet_energyThresh; |
---|
| 57 | unsigned int pktDet_carrierSenseThresh; |
---|
[1170] | 58 | unsigned char pktDet_threshMinDur; |
---|
[1028] | 59 | |
---|
[1208] | 60 | unsigned int warpphy_txAntMode; |
---|
| 61 | unsigned int warpphy_rxAntMode; |
---|
| 62 | unsigned int activeRadios_Tx, activeRadios_Rx; |
---|
| 63 | unsigned int activePHYStatusBits; |
---|
[1245] | 64 | unsigned short longCorrThresh; |
---|
[1377] | 65 | unsigned int afScaling; |
---|
[1028] | 66 | |
---|
[1546] | 67 | unsigned short pktDetCFOsampCount; |
---|
| 68 | |
---|
[1028] | 69 | unsigned int RxFFT_Window_Offset; |
---|
[1169] | 70 | unsigned int txScaling_preamble; |
---|
| 71 | unsigned int txScaling_payload; |
---|
| 72 | |
---|
[1594] | 73 | unsigned 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. |
---|
| 81 | int 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. |
---|
| 452 | void 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. |
---|
| 467 | void 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. |
---|
| 481 | void 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] | 496 | void 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. |
---|
| 514 | unsigned 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. |
---|
| 523 | void 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 |
---|
| 534 | void 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] | 551 | inline 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. |
---|
| 576 | int 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 |
---|
| 600 | void 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] | 619 | void 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 |
---|
| 637 | int 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 |
---|
| 830 | int 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] | 859 | inline 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] | 883 | void 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] | 892 | void 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 |
---|
| 913 | void 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] | 986 | int 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 |
---|
| 1005 | int 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 |
---|
| 1027 | int 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 | |
---|
| 1107 | unsigned 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 | |
---|
| 1124 | unsigned int rfGain,bbGain,gainDB,rfGainDB,bbGainDB; |
---|
| 1125 | unsigned 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] | 1159 | inline 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 | |
---|
| 1174 | void 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 | |
---|
| 1187 | void 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 | |
---|
| 1204 | void 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 | |
---|
| 1258 | void 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 | |
---|
| 1268 | unsigned 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 | |
---|
| 1293 | void 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 *******/ |
---|
| 1302 | void 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] | 1307 | void 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] | 1311 | void 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 | |
---|
| 1315 | void 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] | 1322 | void 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] | 1327 | void 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] | 1332 | void 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 | |
---|
| 1371 | unsigned 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] | 1375 | unsigned 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 | |
---|
| 1379 | unsigned 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 | |
---|
| 1383 | unsigned 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 | |
---|
| 1387 | unsigned int warp_timer_getStatuses() { |
---|
| 1388 | return XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS); |
---|
| 1389 | } |
---|
| 1390 | |
---|
[1177] | 1391 | unsigned char warp_timer_getDoneStatus() { |
---|
| 1392 | return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) & TIMER_STATUS_DONE_MASK); |
---|
[1049] | 1393 | } |
---|
| 1394 | |
---|
[1177] | 1395 | void 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 |
---|
| 1418 | int 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] | 1428 | void warpphy_setAutoCorrDetParams(unsigned short corrThresh, unsigned short energyThresh) { |
---|
| 1429 | ofdm_txrx_mimo_WriteReg_Rx_PktDetCorr_params(corrThresh, energyThresh); |
---|
| 1430 | return; |
---|
| 1431 | } |
---|
| 1432 | |
---|
[1616] | 1433 | void 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] | 1438 | void warpphy_setCarrierSenseThresh(unsigned short thresh) { |
---|
| 1439 | longCorrThresh = thresh; |
---|
| 1440 | ofdm_txrx_mimo_WriteReg_Rx_CSMA_setThresh(pktDet_carrierSenseThresh); |
---|
| 1441 | } |
---|
[1633] | 1442 | |
---|
[1616] | 1443 | void warpphy_setEnergyDetThresh(unsigned short thresh) { |
---|
| 1444 | pktDet_energyThresh = thresh; |
---|
| 1445 | ofdm_txrx_mimo_WriteReg_Rx_PktDet_setThresh(thresh); |
---|
| 1446 | } |
---|
[1105] | 1447 | |
---|
[1616] | 1448 | |
---|
| 1449 | void 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] | 1460 | void 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] | 1470 | void warpphy_setPktDlyPlus(){ |
---|
| 1471 | ofdmRx_pktDetDly++; |
---|
| 1472 | xil_printf("+ofdmRx_pktDetDly = %d\r\n", ofdmRx_pktDetDly); |
---|
| 1473 | mimo_ofdmRx_setPktDetDly(ofdmRx_pktDetDly); |
---|
| 1474 | } |
---|
| 1475 | void 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 | |
---|
| 1485 | void 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 | |
---|
| 1491 | void 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 | |
---|
| 1497 | void warpphy_setNoiseTargetPlus(){ |
---|
| 1498 | agc_noisePowerEstimate++; |
---|
| 1499 | xil_printf("+Noise Estimate = %d\r\n", agc_noisePowerEstimate); |
---|
| 1500 | ofdm_AGC_setNoiseEstimate(agc_noisePowerEstimate); |
---|
| 1501 | } |
---|
| 1502 | |
---|
| 1503 | void warpphy_setNoiseTargetMinus(){ |
---|
| 1504 | agc_noisePowerEstimate--; |
---|
| 1505 | xil_printf("-Noise Estimate = %d\r\n", agc_noisePowerEstimate); |
---|
| 1506 | ofdm_AGC_setNoiseEstimate(agc_noisePowerEstimate); |
---|
| 1507 | } |
---|
| 1508 | |
---|
| 1509 | void warpphy_setTargetPlus(){ |
---|
| 1510 | agc_targetRxPowerOut++; |
---|
| 1511 | xil_printf("+agc_targetRxPowerOut = %d\r\n", agc_targetRxPowerOut); |
---|
| 1512 | ofdm_AGC_SetTarget(agc_targetRxPowerOut); |
---|
| 1513 | } |
---|
| 1514 | |
---|
| 1515 | void warpphy_setTargetMinus(){ |
---|
| 1516 | agc_targetRxPowerOut--; |
---|
| 1517 | xil_printf("-agc_targetRxPowerOut = %d\r\n", agc_targetRxPowerOut); |
---|
| 1518 | ofdm_AGC_SetTarget(agc_targetRxPowerOut); |
---|
| 1519 | } |
---|
| 1520 | |
---|
| 1521 | void 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 | |
---|
| 1528 | void 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] | 1536 | void 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] | 1543 | void 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 | |
---|
| 1550 | void 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 | |
---|
| 1557 | void 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 | |
---|
| 1564 | void 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 | |
---|
| 1570 | void 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 | |
---|