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