warpphy.c

Go to the documentation of this file.
00001 
00012 //XPS-generated header with peripheral parameters
00013 #include "xparameters.h"
00014 
00015 //Header for WARPPHY Interface
00016 #include "warpphy.h"
00017 
00018 //Header for WARPMAC framework (required for some global values)
00019 #include "warpmac.h"
00020 
00021 //These are used for 10.1 PLB46-based designs
00022 // These macros map the old sysgen2opb register access macros to the new PLB46 export macros
00023 #include "ofdm_txrx_mimo_regMacros.h"
00024 #include "ofdm_agc_mimo_regMacros.h"
00025 #include "ofdm_pktdetector_mimo_regMacros.h"
00026 #include "warp_timer_regMacros.h"
00027 
00028 //Headers for other WARP peripheral cores
00029 #include "EEPROM.h"
00030 #include "radio_controller_basic.h"
00031 #include "radio_controller_ext.h"
00032 #include "radio_controller_adv.h"
00033 #include "radio_controller_5ghz.h"
00034 
00035 //Other standard header files
00036 #include <stdio.h>
00037 #include <string.h>
00038 
00039 //********Globals********
00040 int agctarget;
00041 int agcnoiseEst;
00042 unsigned int warpphy_sisoMode;
00043 unsigned char baseRateMod;
00044 unsigned int numTrainingSyms;
00045 unsigned int pktDly;
00046 unsigned char globalReset;
00047 unsigned int numBaseRate;
00048 unsigned char txGain;
00049 
00050 unsigned int pktdetthresh = 9000;
00051 unsigned int csmathresh = 4000;
00052 
00053 unsigned int bothRadios = FIRST_RADIO | SECOND_RADIO;
00054 unsigned int activeRadio, lastActiveRadio;
00055 
00056 unsigned int A_KPval;
00057 unsigned int B_KIval;
00058 unsigned int B_KPval;
00059 unsigned int PN_KVal;
00060 unsigned int RxFFT_Window_Offset;
00062 
00066 int warpphy_init(){
00067 
00068         xil_printf("  Initializing WARPPHY:\r\n");
00069 
00070         //Initialize global variables
00071         agctarget = -15;
00072         agcnoiseEst = -95;
00073         warpphy_sisoMode = 1;
00074         baseRateMod = QPSK;
00075         numTrainingSyms = NUM_TRAINING_SYMBOLS;
00076         pktDly = 58;
00077         globalReset = 0;
00078         numBaseRate = NUM_BASERATE_SYMBOLS;
00079         txGain = 0x3f;
00080 
00081         pktdetthresh = 9000;
00082         csmathresh = 4000;
00083 
00084         activeRadio = FIRST_RADIO;      
00085 
00086         A_KPval = INIT_A_KPVAL;
00087         B_KIval = INIT_B_KIVAL;
00088         B_KPval = INIT_B_KPVAL;
00089         PN_KVal = INIT_PN_KVAL;
00090         RxFFT_Window_Offset = INIT_RXFFTOFSET;
00091 
00092         /*****************EEPROM Setup******************/
00093 /*
00094         int eepromStatus;
00095         unsigned int calReadback;
00096         Xuint8 memory[8], version, revision, valid, MAC[6], i;
00097         Xuint16 serial;
00098         //Extract the various numbers from the EEPROM bytes
00099         version = (memory[0] & 0xE0) >> 5;
00100         revision = (memory[1] & 0xE0) >> 5;
00101         valid = memory[1] & 0x1F;
00102 
00103         //Choose the EEPROM on the selected radio board; second arg is [0,1,2,3,4] for [FPGA, radio1, radio2, radio3, radio4]
00104         eepromStatus = WarpEEPROM_EEPROMSelect((unsigned int *)XPAR_EEPROM_0_MEM0_BASEADDR, 0);
00105 
00106         if(eepromStatus != 0)
00107         {
00108                 xil_printf("EEPROM Select Failed!\r\n");
00109                 return;
00110         }
00111 
00112         //Initialize the EEPROM controller
00113         eepromStatus = WarpEEPROM_Initialize((unsigned int *)XPAR_EEPROM_0_MEM0_BASEADDR);
00114         if(eepromStatus != 0)
00115         {
00116                 xil_printf("EEPROM Init Returned %x\r\n", eepromStatus);
00117                 xil_printf("EEPROM Init Failed!\r\n");
00118                 return;
00119         }
00120 
00121         eepromStatus = WarpEEPROM_EEPROMSelect((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR, 2);
00122         usleep(100);
00123 
00124         //Read the first page from the EERPOM
00125         WarpEEPROM_ReadMem((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR, 0, 0, memory);
00126 
00127         xil_printf("\r\n\r\nEEPROM Values for Radio Board in Slot %d\r\n", 2);
00128 
00129         xil_printf("    WARP Radio Board Version %d.%d\r\n", version, revision);
00130 
00131         serial = WarpEEPROM_ReadWARPSerial((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR);
00132 
00133         xil_printf("    Serial Number (WARP): WR-a-%05d\r\n", serial);
00134 
00135         WarpEEPROM_ReadDSSerial((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR, memory);
00136         print("    EEPROM Hard-wired Serial Number: ");
00137         for(i=1;i<7;i++)
00138                 xil_printf(" %x",memory[7-i]);
00139 
00140         calReadback = WarpEEPROM_ReadRadioCal((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR, 2, 1);
00141         xil_printf("\r\n  Current TxDCO Values: I: %d Q: %d\r\n", (signed short)(((signed char)(calReadback & 0xFF))<<1), (signed short)(((signed char)((calReadback>>8) & 0xFF))<<1));
00142 */
00143 
00144         /*****************END EEPROM Setup*************/
00145 
00146 
00147         /*****************Radio Setup******************/
00148         xil_printf("    Initializing Radio Transmitter...\r\n");
00149         
00150         //The second argument sets the clock ratio in the radio controller's SPI controller
00151         // 2 is the right value for an 80MHz bus
00152         // 1 is good for a 40MHz bus
00153         WarpRadio_v1_Reset((unsigned int *)XPAR_RADIO_CONTROLLER_0_BASEADDR, 1);
00154         
00155         xil_printf("    Starting TxDCO...\r\n");
00156 
00157         //Apply the stored TX DC offset correction values for each radio
00158         warpphy_applyTxDCOCalibration(FIRST_RADIO);
00159         warpphy_applyTxDCOCalibration(SECOND_RADIO);
00160         
00161         //Set Tx bandwidth - 0x1 = 24MHz (minimum)
00162         WarpRadio_v1_TxLpfCornFreqCoarseAdj(0x1, FIRST_RADIO | SECOND_RADIO);
00163         
00164         //Enable hardware control of Tx gains (handled by the radio controller Tx state machine)
00165         WarpRadio_v1_SoftwareTxGainControl(0, FIRST_RADIO | SECOND_RADIO);
00166         
00167         //Four arguments: dly_TxEn, dly_TxStart, dly_GainRampEn, dly_PowerAmpEn, each in units of bus clock cycles
00168         WarpRadio_v1_SetTxTiming(FIRST_RADIO | SECOND_RADIO, 0, 250, 100, 0);
00169         
00170         //Three arguments: targetGain, gainStep, stepInterval; max targetGain is 0x3F
00171         WarpRadio_v1_SetTxGainTiming(FIRST_RADIO | SECOND_RADIO, 0x3F, 0xF, 1);
00172         
00173         //0x3 is max gain
00174         WarpRadio_v1_BaseBandTxGain(0x3, FIRST_RADIO | SECOND_RADIO);
00175         
00176         xil_printf("    complete!\r\n");
00177         
00178         xil_printf("    Initializing Radio Receiver...");
00179 
00180         //Enable hardware AGC control of receive gains & RxHP
00181         WarpRadio_v1_RxHpSoftControlDisable(FIRST_RADIO | SECOND_RADIO);
00182         WarpRadio_v1_SoftwareRxGainControl(0, FIRST_RADIO | SECOND_RADIO);
00183 
00184         /*
00185          //Bypass AGC - contorl Rx gain via software
00186          WarpRadio_v1_RxHpSoftControlEnable(FIRST_RADIO | SECOND_RADIO);
00187          WarpRadio_v1_SoftwareRxGainControl(1, FIRST_RADIO | SECOND_RADIO);
00188          
00189          WarpRadio_v1_RxLNAGainControl(0x2, FIRST_RADIO | SECOND_RADIO);
00190          WarpRadio_v1_RxVGAGainControl(0x10, FIRST_RADIO | SECOND_RADIO);
00191         */
00192         
00193         //Set bandwith with RxHP=0; RxHighPassCornerFreq(0) is critical for good performance
00194         WarpRadio_v1_RxHighPassCornerFreq(0, FIRST_RADIO | SECOND_RADIO);
00195         
00196         //Set Rx bandwidth; 0x0 = 15MHz (minimum)
00197         WarpRadio_v1_RxLpfCornFreqCoarseAdj(0, FIRST_RADIO | SECOND_RADIO);
00198         
00199         xil_printf("complete!\r\n");
00200         /**********************************************************/
00201         
00202         /*************************PHY******************************/
00203         //Disable processing in the Tx PHY to prevent any accidental transmissions during setup
00204         mimo_ofdmTx_disable();
00205         //Disable processing in the Rx PHY to prevent any accidental receptions during setup
00206         mimo_ofdmRx_disable();
00207 
00208         xil_printf("    Initializing OFDM Transmitter...");
00209         
00210         //Configure the FFT scaling values in the PHY Tx and Rx
00211         mimo_ofdmTxRx_setFFTScaling((unsigned int)(((16*RX_FFT_SCALING_STAGE1 + 4*RX_FFT_SCALING_STAGE2 + 1*RX_FFT_SCALING_STAGE3)<<6 ) | (16*TX_FFT_SCALING_STAGE1 + 4*TX_FFT_SCALING_STAGE2 + 1*TX_FFT_SCALING_STAGE3)));
00212         
00213         //Subcarrier indicies for pilot tones - the values here must line up with zeros in the modulation setup for each subcarrier
00214         // Subcarriers [-21,-7,7,21] are the default, matching the 802.11a spec
00215         mimo_ofdmTx_setPilot1Index((7 + ((64-7)<<16) ));
00216         mimo_ofdmTx_setPilot2Index((21 + ((64-21)<<16)));
00217         
00218         //Pilot tone values are Fix16_15, so
00219         // 0x7FFF is +1, 0x8000 is -1
00220         // 0xA57D is ~-0.707, 0x5A82 is ~+0.707
00221         mimo_ofdmTx_setPilot1Value(0xA57D);
00222         mimo_ofdmTx_setPilot2Value(0x5A82);
00223         
00224         //3 values in this write: number of training symbols, number of base rate symbols and number of full rate symbols
00225         //The number of full rate symbols is updated with each packet transmission, so it's set to a sensible non-zero value here
00226         warpphy_setNumSyms(numTrainingSyms + (numBaseRate*256) + (40*65536));
00227         
00228         //Scaling constant for the transmitted preamble; helps normalize the amplitude of the stored preamble and actual IFFT output
00229         mimo_ofdmTx_setPreambleScaling(18350);
00230 
00231         //Configure various options in the Tx PHY
00232         mimo_ofdmTx_setControlBits (
00233                                                                 (2 << 4) | //Preamble shift for antenna B
00234                                                                 (TX_SISO_MODE * warpphy_sisoMode) | //SISO mode
00235                                                                 TX_PILOT_SCRAMBLING | //Pseudo-random scrambling of pilot tones
00236                                                                 //TX_DISABLE_ANTB_PREAMBLE | //Disables preamble on antenna B
00237                                                                 //TX_SISO_ON_ANTB | //Uses antenna B for SISO mode
00238                                                                 0
00239                                                                 );
00240         
00241         xil_printf("complete!\r\n");
00242         
00243         //Finally enable the transmitter; it won't actually do anything until user code transmits a packet
00244         mimo_ofdmTx_enable();
00245         
00246         xil_printf("    Initializing OFDM Receiver...");
00247 
00248         //Configures the default number of samples of the cyclic prefix to use for synchronization offset tolerance
00249         // Larger values here reduce multipath tolerance
00250         mimo_ofdmRx_setFFTWindowOffset(INIT_RXFFTOFSET);
00251         
00252         //Scaling value is a 32-bit value, composed of two UFix16_11 values
00253         // So 0x08000800 scales A/B by exactly 1
00254         // This value is dependent on the number of training symbols
00255         // For SISO mode and numTraining=2, use 0x10001000 (the default)
00256         mimo_ofdmRx_setRxScaling(0x10001000); 
00257         
00258         //Long correlator parameters (for packet detection confirmation and symbol timing)
00259         mimo_ofdmRx_setLongCorrParams(251-16-3  + (3000*65536));
00260         
00261         mimo_ofdmRx_setPktDetDly(50);
00262         mimo_ofdmRx_setNumOFDMSyms(numTrainingSyms + (numBaseRate<<16));
00263         
00264         //Bottom 8 bits are the number of header bytes per packet; nodes must agree on this at build time
00265         //      bits[7:0]: number of header bytes (bytes in base-rate symbols)
00266         //Three more 8-bit values are stored here - each is an index of a byte in the header:
00267         //      bits[15:8]: less-significant byte of pkt length
00268         //      bits[23:16]: more-significant byte of pkt length
00269         //      bits[31:24]: dynamic modulation masks
00270         //      mimo_ofdmRx_setByteNums( (unsigned int)(NUM_HEADER_BYTES + (2<<8) + (3<<16) + (0<<24) ));
00271         mimo_ofdmRx_setByteNums( (unsigned int)(NUM_HEADER_BYTES + (3<<8) + (2<<16) + (0<<24) ));
00272         
00273         //Set filter coefficients for the CFO and phase noise tracking systems
00274         mimo_ofdmRx_setCFO_B_KI(INIT_B_KIVAL);
00275         mimo_ofdmRx_setCFO_B_KP(INIT_B_KPVAL);
00276         mimo_ofdmRx_setPNTrack_K(INIT_PN_KVAL);
00277         
00278         //Configure a bunch of options in the Rx PHY
00279         mimo_ofdmRx_setOptions
00280         (
00281                 //RESET_BER |
00282                 REQ_LONG_CORR |
00283                 //BIG_PKTBUF_MODE |
00284                 DYNAMC_PKT_LENGTHS |
00285                 REQ_TWO_LONG_CORR |
00286                 REQ_SHORT_CORR |
00287                 (RX_SISO_MODE * warpphy_sisoMode) |
00288                 CFO_USE_LONGCORR |
00289                 DEBUG_CFO_OUTSEL |
00290                 COARSE_CFO_EN | //Enable coarse CFO estimation
00291                 USE_PILOT_ARCTAN |
00292                 //SWITCHING_DIV_EN | //Enable switching diversity at the receiver
00293                 SIMPLE_DYN_MOD_EN |
00294                 EXT_PKT_DETECT |
00295                 //SISO_ON_ANTB | //Receive SISO stream on second radio
00296                 //INT_PKT_DETECT |
00297                 //EQ_BYPASS_DIVISION |
00298                 RESET_ON_BAD_HDR | //Reset Rx PHY if header fails CRC
00299                 0,
00300                 DEFAULT_INTERRUPTS
00301          );
00302         
00303         //Finally enable the Rx PHY
00304         mimo_ofdmRx_enable();
00305         
00306         //Set the modulation schemes (baseRate, antA_fullRate, antB_fullRate):
00307         // By default, we're in SISO mode, so antenna B gets 0 bits
00308         // 0xF enables dynamic modulation for antenna A (0xF gets AND'd with the header's full-rate field)
00309         warpphy_set_modulation(baseRateMod, 0xF, 0x0);
00310         
00311         //If you disable dynamic modulation, replace 0xF with an actual modulation scheme:
00312         //warpphy_set_modulation(QPSK, QPSK, 0x0);
00313         
00314         xil_printf("complete!\r\n");
00315         /**********************************************************/
00316         
00317         /***************************AGC****************************/
00318         xil_printf("    Initializing AGC...");
00319         ofdm_AGC_Initialize(agcnoiseEst);
00320         ofdm_AGC_setNoiseEstimate(agcnoiseEst);
00321         ofdm_AGC_SetDCO(1);
00322         ofdm_AGC_SetTarget(agctarget);
00323         ofdm_AGC_Reset();
00324         xil_printf("complete!\r\n");
00325         /**********************************************************/
00326         
00327         /*******************Packet Detector************************/
00328         xil_printf("    Initializing Packet Detection...");
00329         ofdm_pktDetector_mimo_WriteReg_csma_enableBusy(PKTDET_BASEADDR, 1);
00330         ofdm_pktDetector_mimo_WriteReg_csma_enableIdle(PKTDET_BASEADDR, 1);
00331         ofdm_pktDetector_mimo_WriteReg_pktDet_masterReset(PKTDET_BASEADDR, 1);
00332         //              ofdm_pktDetector_mimo_WriteReg_pktDet_detectionMask(PKTDET_BASEADDR, 2); //2 = radio slot 3
00333         ofdm_pktDetector_mimo_WriteReg_pktDet_detectionMask(PKTDET_BASEADDR, 1); //1 = radio slot 2
00334         ofdm_pktDetector_mimo_WriteReg_pktDet_detectionMode(PKTDET_BASEADDR, 1); //0 = AND, 1 = OR
00335         ofdm_pktDetector_mimo_WriteReg_pktDet_resetDuration(PKTDET_BASEADDR, 32);
00336         ofdm_pktDetector_mimo_WriteReg_pktDet_avgLen(PKTDET_BASEADDR, 16);
00337         ofdm_pktDetector_mimo_WriteReg_pktDet_avgThresh(PKTDET_BASEADDR, pktdetthresh); //7000
00338         ofdm_pktDetector_mimo_WriteReg_csma_avgThresh(PKTDET_BASEADDR, 16000);
00339         ofdm_pktDetector_mimo_WriteReg_csma_difsPeriod(PKTDET_BASEADDR, 1000); //625
00340         ofdm_pktDetector_mimo_WriteReg_pktDet_masterReset(PKTDET_BASEADDR, 0);
00341         ofdm_pktDetector_mimo_WriteReg_pktDet_reset(PKTDET_BASEADDR, 0);
00342         xil_printf("complete!\r\n");
00343         /**********************************************************/
00344         
00345         /**************************Timer***************************/
00346         warp_timer_init();
00347         /**********************************************************/
00348         
00349         //Finally, enable the Rx paths in the radios
00350         WarpRadio_v1_RxEnable(activeRadio);
00351         
00352         warpphy_enableSisoMode();
00353         warpphy_setNumTrainingSyms(NUM_TRAINING_SYMBOLS);
00354 
00355         //Setup the PHY's encoder/decoder blocks
00356         //FIXME: the values below should be masked by their actual sizes
00357         ofdm_txrx_mimo_WriteReg_FEC_Coding(OFDM_BASEADDR,
00358                 (SOFT_DECODING * 2) |
00359                 (QPSK_SCL * 2^4) |
00360                 (QAM16_SCL * 2^8)
00361                 );
00362 
00363         return 0;
00364 }
00365 
00371 void warpphy_clearRxInterrupts(){
00372         
00373         //The TxRx_Interrupt_PktBuf_Ctrl register has many bits.
00374         // bits[2:0] are the Rx interrupt enables
00375         // bits[6:4] are the Rx interrupt resets
00376         // bit[3] and bit[7] are used for the TxDone interrupt and are preserved here
00377         ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) | DEFAULT_INTERRUPTRESETS);
00378         ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) &  ~DEFAULT_INTERRUPTRESETS);
00379 
00380         return;
00381 }
00382 
00386 void mimo_ofdmRx_enable(){
00387         
00388         //Clear any stale interrupts; this should never really be required
00389         warpphy_clearRxInterrupts();
00390         
00391         //De-asert the global reset
00392         ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) & ~RX_GLOBAL_RESET);
00393         
00394         return;
00395 }
00396 
00400 void mimo_ofdmRx_disable(){
00401         
00402         //Assert the global reset
00403         ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) | RX_GLOBAL_RESET);
00404 
00405         //Clear any stale interrupts; this should never really be required
00406         warpphy_clearRxInterrupts();
00407         
00408         return;
00409 }
00410 
00415 void mimo_ofdmRx_setOptions(unsigned int someOptions, unsigned int intType){
00416         
00417         //Write the full controlBits register
00418         ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, someOptions);
00419         
00420         //The interrupt control bits are in the Interrupt_PktBuf_Ctrl register - bits[7:4]
00421         //Clear the interrupt control bits
00422         ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) & 0xFFFFFF00);
00423         
00424         //Write just the interrupt control bits
00425         ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) | (ALL_INTERRUPT_ENABLE & intType));
00426         
00427         return;
00428 }
00429 
00433 unsigned int mimo_ofdmRx_getOptions(){
00434         
00435         return ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR);
00436 }
00437 
00438 
00442 void mimo_ofdmTx_disable(){
00443         
00444         //Assert the OFDM Tx master reset and pktDone reset
00445         ofdm_txrx_mimo_WriteReg_Tx_Start_Reset_Control(OFDM_BASEADDR, 0x1 | 0x4);
00446         
00447         return;
00448 }
00449 
00453 void mimo_ofdmTx_enable(){
00454         
00455         //Assert then clear the OFDM Tx master reset and pktDone reset
00456         ofdm_txrx_mimo_WriteReg_Tx_Start_Reset_Control(OFDM_BASEADDR, 0x1 | 0x4);
00457         ofdm_txrx_mimo_WriteReg_Tx_Start_Reset_Control(OFDM_BASEADDR, 0x0);
00458         
00459         return;
00460 }
00461 
00462 
00471 int warpphy_pktTx(unsigned int block){
00472         
00473         //First checks whether the Tx PHY is already transmitting a packet
00474         //If so, give up and return
00475         if(ofdm_txrx_mimo_ReadReg_Tx_PktRunning(OFDM_BASEADDR) == 1)
00476         {
00477                 //Tx PHY was already busy sending a packet, which should be impossible
00478                 xil_printf("Tx PHY was already transmitting! Failing...\r\n");
00479                 
00480                 // Return with a failure
00481                 return 1;
00482         }
00483         
00484         //xil_printf("PHY: %x\r\n", ((phyHeader*)(warpphy_getBuffAddr(1)))->destAddr[5]);
00485 
00486         
00487 
00488         /* Should there be a check here whether the Rx PHY is receiving a packet?
00489          And what should happen if it is? It's sort of carrier sensing, but if
00490          CSMA is disabled, should the Tx pkt be discarded, or held until the Rx
00491          is no longer busy...
00492          */
00493         WarpRadio_v1_TxEnable(activeRadio);
00494         usleep(6);//Sleep long enough for the PHY to start transmitting; depends on second argument to SetTxTiming
00495         
00496         //If the user requested blocking, wait here until the PHY is done, then re-enable the radio Rx
00497         // Otherwise, return immediately - NOTE! in this mode, the user must re-enable the radio Rx at some point
00498         if(block == TXBLOCK)
00499         {
00500                 //Do nothing while the Tx PHY is still busy
00501                 while(ofdm_txrx_mimo_ReadReg_Tx_PktRunning(OFDM_BASEADDR) == 1) {}
00502                 
00503                 //Re-enable the radio receiver
00504                 WarpRadio_v1_RxEnable(activeRadio);
00505         }
00506         
00507         //Return successfully
00508         return 0;
00509 }
00510 
00515 int warpphy_waitForTx(){
00516 
00517         //Poll the PHY transmitter until it's finished transmitting
00518         while(ofdm_txrx_mimo_ReadReg_Tx_PktRunning(OFDM_BASEADDR) == 1) {}
00519 
00520         //Re-enable the radio receiver
00521         WarpRadio_v1_RxEnable(activeRadio);
00522 
00523         //Re-enable packet detection
00524         ofdm_pktDetector_mimo_WriteReg_pktDet_reset(PKTDET_BASEADDR, 0);
00525 
00526         return 0;
00527 }
00528 
00529 
00537 void warpphy_setBuffs(unsigned char txBufOffset, unsigned char rxBufOffset){
00538         
00539         //TxRx_Interrupt_PktBuf_Ctrl[21:16] compose the Rx buffer offset
00540         //TxRx_Interrupt_PktBuf_Ctrl[13:8]  compose the Tx buffer offset
00541 
00542         //First, zero out the current pkt buff offsets
00543         //Preserve the bottom 8 bits of the register (used for interrupt control)
00544         ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) & 0x000000FF);
00545         
00546         //Then write the new pkt buff offsets
00547         ofdm_txrx_mimo_WriteReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR,
00548                 ofdm_txrx_mimo_ReadReg_TxRx_Interrupt_PktBuf_Ctrl(OFDM_BASEADDR) |
00549                 ( (txBufOffset & 0x3F) << 8 ) |
00550                 ( (rxBufOffset & 0x3F) << 16 )
00551         );
00552 
00553         return;
00554 }
00555 
00557 void warpphy_enableSisoMode(){
00558         
00559         //Disable the TxRx paths during the switch
00560         WarpRadio_v1_TxRxDisable(FIRST_RADIO | SECOND_RADIO);
00561 
00562         //Update the global variable
00563         warpphy_sisoMode = 1;
00564         
00565         //Disable full-rate modulation for second anteanna
00566         warpphy_set_modulation(baseRateMod, 0xF, 0);
00567 
00568         //Enable only one radio
00569         activeRadio = FIRST_RADIO;
00570         
00571         //Set SISO mode in the Tx and Rx PHY registers
00572         mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() | TX_SISO_MODE);
00573         mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | RX_SISO_MODE, DEFAULT_INTERRUPTS);
00574 
00575         //Re-enable reception on just the first radio
00576         WarpRadio_v1_RxEnable(activeRadio);
00577         
00578         return;
00579 }
00580 
00582 void warpphy_enableMimoMode(){
00583 
00584         //Disable the TxRx paths during the switch
00585         WarpRadio_v1_TxRxDisable(FIRST_RADIO | SECOND_RADIO);
00586 
00587         //Update the global variable
00588         warpphy_sisoMode = 0;
00589         
00590         //Enable full-rate modulation for both anteannas
00591         warpphy_set_modulation(baseRateMod, 0xF, 0xF);
00592 
00593         //Enable both radios
00594         activeRadio = FIRST_RADIO | SECOND_RADIO;
00595         
00596         //Un-set SISO mode in the Tx and Rx PHY registers
00597         mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & (~TX_SISO_MODE));
00598         mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & (~RX_SISO_MODE),  DEFAULT_INTERRUPTS);
00599 
00600         //Re-enable reception on both radios
00601         WarpRadio_v1_RxEnable(activeRadio);
00602 
00603         return;
00604 }
00605 
00607 void warpphy_enableMisoMode(){
00608         WarpRadio_v1_TxRxDisable(FIRST_RADIO | SECOND_RADIO);
00609         warpphy_sisoMode = 0;
00610         lastActiveRadio = activeRadio;
00611         activeRadio = FIRST_RADIO | SECOND_RADIO;
00612         mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & (~TX_SISO_MODE));
00613         WarpRadio_v1_RxEnable(activeRadio);
00614 }
00615 
00617 void warpphy_disableMisoMode(){
00618         WarpRadio_v1_TxRxDisable(FIRST_RADIO | SECOND_RADIO);
00619         warpphy_sisoMode = 1;
00620         activeRadio = lastActiveRadio;
00621         mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() | TX_SISO_MODE);
00622         WarpRadio_v1_RxEnable(activeRadio);
00623 }
00624 
00632 void warpphy_setNumTrainingSyms(unsigned int c){
00633         //Update the global variable; use each time a packet is transmitted
00634         numTrainingSyms = c;
00635         
00636         //Configure the receiver
00637         mimo_ofdmRx_setNumOFDMSyms(numTrainingSyms + (numBaseRate<<16));
00638 }
00639 
00649 void warpphy_set_modulation(unsigned char baseRate, unsigned char antAFullRate, unsigned char antBFullRate)
00650 {
00651         xil_printf("warpphy_set_modulation: Flexible modulation not currently supported in coded PHY! Giving up...\r\n");
00652         return;
00653 
00654 /*
00655         unsigned int modIndex;
00656 
00657         //Update the global baseRate modulation variable
00658         baseRateMod = baseRate;
00659         
00660         //Define the standard subcarrier mapping - 48 used for data (0xF here), 4 pilots & 12 unused (0x0 here)
00661         // The vector contains 192 elements:
00662         //    0:63 - Antenna A full rate masks for subcarriers [0,1,2,...31,-31,-30,...-1]
00663         //  64:127 - Antenna B full rate masks for subcarriers [0,1,2,...31,-31,-30,...-1]
00664         // 128:191 - Base rate masks for subcarriers [0,1,2,...31,-31,-30,...-1]
00665         //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
00666         unsigned char modMasks[192] = {
00667                         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,
00668                         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,
00669                         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
00670         };
00671 
00672         //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 )
00673         //Configure Tx and Rx antenna A full rate
00674          for(modIndex=0; modIndex<64; modIndex++)
00675          {
00676                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & antAFullRate);
00677                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & antAFullRate);
00678          }
00679 
00680          //Configure Tx and Rx antenna B full rate
00681          for(modIndex=64; modIndex<128; modIndex++)
00682          {
00683                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & antBFullRate);
00684                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & antBFullRate);
00685          }
00686          
00687          //Configure the Tx and Rx base rate
00688          for(modIndex=128; modIndex<192; modIndex++)
00689          {
00690                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & baseRate);
00691                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RXMODULATION+(modIndex*sizeof(int)), modMasks[modIndex] & baseRate);
00692          }
00693 
00694         return;
00695         */
00696 }
00697 
00703 void warpphy_setSISOAntenna(unsigned char antSel)
00704 {
00705         
00706         if(warpphy_sisoMode != 1) return; //Not valid if using MIMO mode
00707         if(mimo_ofdmRx_getOptions()  & SWITCHING_DIV_EN) return; //Not valid if using switching diversity
00708         
00709         if(antSel == 0) //choose radio in slot 2
00710         {
00711                 //Temporarily disable packet detections
00712                 ofdm_pktDetector_mimo_WriteReg_pktDet_reset(PKTDET_BASEADDR, 1);
00713                 
00714                 activeRadio = FIRST_RADIO;
00715                 
00716                 //Switch the pkt detector to listen to just radio #2
00717                 ofdm_pktDetector_mimo_WriteReg_pktDet_detectionMask(PKTDET_BASEADDR, 1);
00718                 
00719                 //Disable antB selection in the PHY
00720                 mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & (~TX_SISO_ON_ANTB) );
00721                 mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & (~SISO_ON_ANTB),  DEFAULT_INTERRUPTS);
00722                 
00723                 //Turn packet detection back on
00724                 ofdm_pktDetector_mimo_WriteReg_pktDet_reset(PKTDET_BASEADDR, 0);
00725                 WarpRadio_v1_RxEnable(activeRadio);
00726         }
00727         else if(antSel == 1) //chose radio in slot 3
00728         {
00729                 //Temporarily disable packet detections
00730                 ofdm_pktDetector_mimo_WriteReg_pktDet_reset(PKTDET_BASEADDR, 1);
00731                 
00732                 activeRadio = SECOND_RADIO;
00733                 
00734                 //Switch the pkt detector to listen to just radio #3
00735                 ofdm_pktDetector_mimo_WriteReg_pktDet_detectionMask(PKTDET_BASEADDR, 2);
00736                 
00737                 //Disable antB selection in the PHY
00738                 mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() | (TX_SISO_ON_ANTB) );
00739                 mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | (SISO_ON_ANTB),    DEFAULT_INTERRUPTS);
00740                 
00741                 //Turn packet detection back on
00742                 ofdm_pktDetector_mimo_WriteReg_pktDet_reset(PKTDET_BASEADDR, 0);
00743                 WarpRadio_v1_RxEnable(activeRadio);
00744         }
00745         
00746         return;
00747 }
00748 
00753 int warpphy_setChannel(unsigned char band, unsigned int c){
00754 
00755         int newFreq = -1;
00756         
00757         
00758         if (band == GHZ_2){
00759 
00760                 newFreq = WarpRadio_v1_SetCenterFreq2GHz(c, FIRST_RADIO | SECOND_RADIO);
00761         }
00762         if (band == GHZ_5){
00763                 newFreq = WarpRadio_v1_SetCenterFreq5GHz(c, FIRST_RADIO | SECOND_RADIO);
00764         }
00765                 
00766         return newFreq;
00767 }
00768 
00775 int warpphy_setSeparateChannels(unsigned char antA_band, unsigned int antA_chan, unsigned char antB_band, unsigned int antB_chan){
00776 
00777         int newFreq_A = -1;
00778         int newFreq_B = -1;
00779         
00780         if (antA_band == GHZ_2)
00781                 newFreq_A = WarpRadio_v1_SetCenterFreq2GHz(antA_chan, FIRST_RADIO);
00782 
00783         if (antB_band == GHZ_2)
00784                 newFreq_B = WarpRadio_v1_SetCenterFreq2GHz(antB_chan, SECOND_RADIO);
00785 
00786         if (antA_band == GHZ_5)
00787                 newFreq_A = WarpRadio_v1_SetCenterFreq5GHz(antA_chan, FIRST_RADIO);
00788 
00789         if (antB_band == GHZ_5)
00790                 newFreq_B = WarpRadio_v1_SetCenterFreq5GHz(antB_chan, SECOND_RADIO);
00791         
00792         if(newFreq_A == -1 || newFreq_B == -1)
00793                 return -1;
00794         else
00795                 return newFreq_A;
00796 
00797 }
00798 
00799 /*********************************************************************/
00800 /* A whole bunch of debugging functions - these will go away someday */
00801 /*********************************************************************/
00802 
00803 void warpphy_setPktDlyPlus(){
00804         pktDly++;
00805         xil_printf("+PktDly = %d\r\n",pktDly);
00806         mimo_ofdmRx_setPktDetDly(pktDly);
00807 }
00808 void warpphy_setPktDlyMinus(){
00809         pktDly--;
00810         xil_printf("-PktDly = %d\r\n",pktDly);
00811         mimo_ofdmRx_setPktDetDly(pktDly);
00812 }
00813 
00814 /****************************/
00815 /* Phase noise tracking */
00816 /****************************/
00817 void warpphy_set_PN_KPlus(unsigned int increment){
00818         PN_KVal=PN_KVal+increment;
00819         mimo_ofdmRx_setPNTrack_K(PN_KVal);
00820         xil_printf("K: %x\r\n", PN_KVal);
00821 }
00822 
00823 void warpphy_set_PN_KMinus(unsigned int decrement){
00824         PN_KVal=PN_KVal-decrement;
00825         mimo_ofdmRx_setPNTrack_K(PN_KVal);
00826         xil_printf("K: %x\r\n", PN_KVal);
00827 }
00828 
00829 /*****************/
00830 /* CFO Constants */
00831 /*****************/
00832 
00833 void print_CFO_constants ()
00834 {
00835         xil_printf("AK: %x\tBP: %x\tBI: %x\r\n", A_KPval, B_KPval, B_KIval);
00836 }
00837 
00838 void warpphy_set_B_KPPlus(unsigned int increment){
00839         B_KPval=B_KPval+increment;
00840         mimo_ofdmRx_setCFO_B_KP(B_KPval);
00841         print_CFO_constants();
00842 }
00843 
00844 void warpphy_set_B_KPMinus(unsigned int decrement){
00845         B_KPval=B_KPval-decrement;
00846         mimo_ofdmRx_setCFO_B_KP(B_KPval);
00847         print_CFO_constants();
00848 }
00849 
00850 void warpphy_set_B_KIPlus(unsigned int increment){
00851         B_KIval=B_KIval+increment;
00852         mimo_ofdmRx_setCFO_B_KI(B_KIval);
00853         print_CFO_constants();
00854 }
00855 
00856 void warpphy_set_B_KIMinus(unsigned int decrement){
00857         B_KIval=B_KIval-decrement;
00858         mimo_ofdmRx_setCFO_B_KI(B_KIval);
00859         print_CFO_constants();
00860 }
00861 
00862 void warpphy_set_CFODebugOutput(unsigned char outputSel){
00863         
00864         if(outputSel)
00865                 ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) | DEBUG_CFO_OUTSEL);
00866         else
00867                 ofdm_txrx_mimo_WriteReg_Rx_ControlBits(OFDM_BASEADDR, ofdm_txrx_mimo_ReadReg_Rx_ControlBits(OFDM_BASEADDR) & ~DEBUG_CFO_OUTSEL);
00868         
00869         xil_printf("CFO Debug Output %d\r\n",outputSel);
00870 }
00871 
00872 
00873 /*********************/
00874 /* Other PHY options */
00875 /*********************/
00876 
00877 void warpphy_set_FFTOffset_Plus(){
00878         RxFFT_Window_Offset++;
00879         mimo_ofdmRx_setFFTWindowOffset(RxFFT_Window_Offset);
00880         xil_printf("Rx FFT Offset: %d\r\n", RxFFT_Window_Offset);
00881 }
00882 
00883 void warpphy_set_FFTOffset_Minus(){
00884         RxFFT_Window_Offset--;
00885         mimo_ofdmRx_setFFTWindowOffset(RxFFT_Window_Offset);
00886         xil_printf("Rx FFT Offset: %d\r\n", RxFFT_Window_Offset);
00887 }
00888 
00889 void warpphy_setNoiseTargetPlus(){
00890         agcnoiseEst++;
00891         xil_printf("+Noise Estimate = %d\r\n",agcnoiseEst);
00892         ofdm_AGC_setNoiseEstimate(agcnoiseEst);
00893 }
00894 
00895 void warpphy_setNoiseTargetMinus(){
00896         agcnoiseEst--;
00897         xil_printf("-Noise Estimate = %d\r\n",agcnoiseEst);
00898         ofdm_AGC_setNoiseEstimate(agcnoiseEst);
00899 }
00900 
00901 void warpphy_setTargetPlus(){
00902         agctarget++;
00903         xil_printf("+agctarget = %d\r\n",agctarget);
00904         //XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, sevenSegmentMap(-agctarget%10));
00905         //XGpio_mSetDataReg(XPAR_LED_7SEGMENT_1_BASEADDR, 1, sevenSegmentMap(-agctarget/10));
00906         ofdm_AGC_SetTarget(agctarget);
00907 }
00908 
00909 void warpphy_setTargetMinus(){
00910         agctarget=agctarget-1;
00911         xil_printf("-agctarget = %d\r\n",agctarget);
00912         //XGpio_mSetDataReg(XPAR_LED_7SEGMENT_BASEADDR, 1, sevenSegmentMap(-agctarget%10));
00913         //XGpio_mSetDataReg(XPAR_LED_7SEGMENT_1_BASEADDR, 1, sevenSegmentMap(-agctarget/10));
00914         ofdm_AGC_SetTarget(agctarget);
00915 }
00916 
00917 
00921 int warpphy_applyTxDCOCalibration(unsigned int radioSelection)
00922 {
00923         int eepromStatus = 0;
00924         short calReadback = 0;
00925         signed short best_I, best_Q;
00926         unsigned char radioNum;
00927         Xuint8 memory[8], version, revision, valid, MAC[6], i;
00928         Xuint16 serial;
00929 
00930         //Radio selection will be 0x11111111, 0x22222222, 0x44444444 or 0x88888888
00931         // corresponding to radios in slots 1, 2, 3 or 4
00932         // We need the slot number to initialize the EEPROM
00933         radioNum = (radioSelection & 0xF) == 1 ? 1 : ( (radioSelection & 0xF) == 2 ? 2 : ( (radioSelection & 0xF) == 4 ? 3 : 4 ) );
00934         xil_printf("Applying TxDCO correction for radio %d\r\n", radioNum);
00935 
00936         //Mimic the radio test code, in hopes of a more stable EEPROM read...
00937         //Choose the EEPROM on the selected radio board; second arg is [0,1,2,3,4] for [FPGA, radio1, radio2, radio3, radio4]
00938         eepromStatus = WarpEEPROM_EEPROMSelect((unsigned int *)XPAR_EEPROM_0_MEM0_BASEADDR, 0);
00939         if(eepromStatus != 0)
00940         {
00941                 xil_printf("EEPROM Select Failed!\r\n");
00942                 return;
00943         }
00944         
00945         //Initialize the EEPROM controller
00946         eepromStatus = WarpEEPROM_Initialize((unsigned int *)XPAR_EEPROM_0_MEM0_BASEADDR);
00947         if(eepromStatus != 0)
00948         {
00949                 xil_printf("EEPROM Init Returned %x\r\n", eepromStatus);
00950                 xil_printf("EEPROM Init Failed!\r\n");
00951         return;
00952         }
00953 
00954         //Select the EEPROM on the current radio board
00955         eepromStatus = WarpEEPROM_EEPROMSelect((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR, radioNum);
00956 
00957         if(eepromStatus != 0)
00958         {
00959                 xil_printf("TxDCO: EEPROM error\r\n");
00960                 return -1;
00961         }
00962         
00963         //Read the first page from the EERPOM
00964         WarpEEPROM_ReadMem((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR, 0, 0, memory);
00965         version = (memory[0] & 0xE0) >> 5;
00966         revision = (memory[1] & 0xE0) >> 5;
00967         valid = memory[1] & 0x1F;
00968 
00969         xil_printf("\r\n\r\nEEPROM Values for Radio Board in Slot %d\r\n", radioNum);
00970 
00971         xil_printf("    WARP Radio Board Version %d.%d\r\n", version, revision);
00972 
00973         serial = WarpEEPROM_ReadWARPSerial((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR);
00974 
00975         xil_printf("    Serial Number (WARP): WR-a-%05d\r\n", serial);
00976 
00977         WarpEEPROM_ReadDSSerial((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR, memory);
00978         print("    EEPROM Hard-wired Serial Number: ");
00979         for(i=1;i<7;i++)
00980                 xil_printf(" %x",memory[7-i]);
00981         xil_printf("\r\n\r\n");
00982         //Read the Tx DCO values
00983         calReadback = WarpEEPROM_ReadRadioCal((unsigned int*)XPAR_EEPROM_0_MEM0_BASEADDR, 2, 1);
00984         
00985         //Scale the stored values
00986         best_I = (signed short)(((signed char)(calReadback & 0xFF))<<1);
00987         best_Q = (signed short)(((signed char)((calReadback>>8) & 0xFF))<<1);
00988         
00989         xil_printf("TxDCO: Applied values to radio %d - I: %d\tQ: %d\r\n", radioNum, best_I, best_Q);
00990         
00991         //Finally, write the Tx DCO values to the DAC
00992         WarpRadio_v1_DACOffsetAdj(ICHAN, best_I, radioSelection);
00993         WarpRadio_v1_DACOffsetAdj(QCHAN, best_Q, radioSelection);
00994         
00995         return 0;
00996 }
00997 
00998 
00999 void warpphy_setPktDetPlus(unsigned int offset){
01000         pktdetthresh=pktdetthresh+offset;
01001         ofdm_pktDetector_mimo_WriteReg_pktDet_avgThresh(PKTDET_BASEADDR, pktdetthresh);
01002         xil_printf("PktDetThresh = %d\r\n",pktdetthresh);
01003 }
01004 
01005 void warpphy_setPktDetMinus(unsigned int offset){
01006         pktdetthresh=pktdetthresh-offset;
01007         ofdm_pktDetector_mimo_WriteReg_pktDet_avgThresh(PKTDET_BASEADDR, pktdetthresh);
01008         xil_printf("PktDetThresh = %d\r\n",pktdetthresh);
01009 }
01010 
01011 
01012 void warpphy_setCSMAPlus(unsigned int offset){
01013         csmathresh=csmathresh+offset;
01014         ofdm_pktDetector_mimo_WriteReg_csma_avgThresh(PKTDET_BASEADDR, csmathresh);
01015         xil_printf("CSMATHRESH = %d\r\n",csmathresh);
01016 }
01017 
01018 void warpphy_setCSMAMinus(unsigned int offset){
01019         csmathresh=csmathresh-offset;
01020         ofdm_pktDetector_mimo_WriteReg_csma_avgThresh(PKTDET_BASEADDR, csmathresh);
01021         xil_printf("CSMATHRESH = %d\r\n",csmathresh);
01022 }
01023 
01024 
01025 void warpphy_setGainPlus(unsigned int offset){
01026         txGain=txGain+offset;
01027         WarpRadio_v1_SetTxGainTiming(FIRST_RADIO | SECOND_RADIO, txGain, 0xF, 2);
01028         xil_printf("TxGain = %x\r\n",txGain);
01029 }
01030 
01031 void warpphy_setGainMinus(unsigned int offset){
01032         txGain=txGain-offset;
01033         WarpRadio_v1_SetTxGainTiming(FIRST_RADIO | SECOND_RADIO, txGain, 0xF, 2);
01034         xil_printf("TxGain = %x\r\n",txGain);
01035 }
01036 
01037 /******* AGC core control functions ********/
01038 void ofdm_AGC_SetDCO(unsigned int AGCstate){
01039         
01040         // Enables DCO and DCO subtraction (correction scheme and butterworth hipass are active)
01041         
01042         unsigned int bits;
01043         
01044         bits = OFDM_AGC_MIMO_ReadReg_Bits(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR);
01045         
01046         if(AGCstate)
01047                 bits = bits | 0x6;
01048         else
01049                 bits = bits & 0x1;
01050         
01051         OFDM_AGC_MIMO_WriteReg_Bits(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, bits);
01052         
01053         return;
01054 }
01055 
01056 void ofdm_AGC_Reset(){
01057         
01058         // Cycle the agc's software reset port
01059         
01060         OFDM_AGC_MIMO_WriteReg_SRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 1);
01061         usleep(10);
01062         OFDM_AGC_MIMO_WriteReg_SRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
01063         usleep(100);
01064         
01065         return;
01066 }
01067 
01068 
01069 void ofdm_AGC_MasterReset(){
01070         
01071         // Cycle the master reset register in the AGC and enable it
01072         
01073         OFDM_AGC_MIMO_WriteReg_AGC_EN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
01074         usleep(10);
01075         OFDM_AGC_MIMO_WriteReg_MRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
01076         usleep(10);
01077         OFDM_AGC_MIMO_WriteReg_MRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 1);
01078         usleep(10);
01079         OFDM_AGC_MIMO_WriteReg_MRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
01080         usleep(10);
01081         OFDM_AGC_MIMO_WriteReg_AGC_EN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 1);
01082         
01083         return;
01084 }
01085 
01086 void ofdm_AGC_Initialize(int noise_estimate){
01087         
01088         int g_bbset = 0;
01089         
01090         // First set all standard parameters
01091         
01092         // Turn off both resets and the master enable
01093         OFDM_AGC_MIMO_WriteReg_AGC_EN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
01094         OFDM_AGC_MIMO_WriteReg_SRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
01095         OFDM_AGC_MIMO_WriteReg_MRESET_IN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0);
01096         
01097         // An adjustment parameter
01098         OFDM_AGC_MIMO_WriteReg_ADJ(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 8);
01099         
01100         // Timing for the DC-offset correction
01101         OFDM_AGC_MIMO_WriteReg_DCO_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x46403003);
01102         
01103         // Initial baseband gain setting
01104         OFDM_AGC_MIMO_WriteReg_GBB_init(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 52);
01105         
01106         // RF gain AGCstate thresholds
01107         OFDM_AGC_MIMO_WriteReg_Thresholds(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 
01108                 ((AGC_THRESH_1&0xFF)<<16) +
01109                 ((AGC_THRESH_2&0xFF)<<8) + 
01110                  (AGC_THRESH_3&0xFF)
01111         );
01112         
01113         // Overall AGC timing
01114         OFDM_AGC_MIMO_WriteReg_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x9A962A28);//0x826E3C0A;
01115         
01116         // vIQ and RSSI average lengths
01117         OFDM_AGC_MIMO_WriteReg_AVG_LEN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x10F); //103
01118         
01119         // Disable DCO, disable DCO subtraction, set filter to straight downsampling
01120         OFDM_AGC_MIMO_WriteReg_Bits(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x0);
01121         
01122         // Compute and set the initial g_BB gain value from the noise estimate
01123         // The initial g_bb sets noise to -19 db, assuming 32 db RF gain
01124         
01125         g_bbset = -19 - 32 - noise_estimate;
01126         OFDM_AGC_MIMO_WriteReg_GBB_init(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, g_bbset);
01127         
01128         // Perform a master reset
01129         ofdm_AGC_MasterReset();
01130         
01131         // Agc is now reset and enabled, ready to go!
01132         return;
01133 }
01134 
01135