source: PlatformSupport/WARPMAC/warp_v3/warpphy.c

Last change on this file was 2376, checked in by murphpo, 10 years ago

fixing typo (credit to asethi)

File size: 53.3 KB
Line 
1/*! \file warpphy.c
2 \brief Provide PHY-specific functions for interfacing WARPMAC (and MAC code) to the OFDM PHY peripherals
3 
4 @version 15.22
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
13//#include "warp_fpga_board.h"
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
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)
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"
29
30//Headers for other WARP peripheral cores
31#ifdef HAVE_EEPROM
32#include "EEPROM.h"
33#endif
34#include "radio_controller.h"
35
36//Other standard header files
37//#include <sleep.h>
38#include <stdio.h>
39#include <string.h>
40
41//********Globals********
42int agc_targetRxPowerOut;
43int agc_noisePowerEstimate;
44
45unsigned char baseRateMod;
46unsigned int numTrainingSyms;
47unsigned int ofdmRx_pktDetDly;
48unsigned int numBaseRate;
49unsigned char txGain;
50unsigned char RxSoftDecodingEn;
51unsigned short pktDet_corrCounterLoad;
52unsigned char pktDet_corrWindowStart;
53unsigned char pktDet_corrWindowEnd;
54
55unsigned int pktDet_energyThresh;
56unsigned int pktDet_carrierSenseThresh;
57unsigned char pktDet_threshMinDur;
58
59unsigned int warpphy_txAntMode;
60unsigned int warpphy_rxAntMode;
61unsigned int activeRadios_Tx, activeRadios_Rx;
62unsigned int activePHYStatusBits;
63unsigned short longCorrThresh;
64unsigned int afScaling;
65
66unsigned short pktDetCFOsampCount;
67
68unsigned int RxFFT_Window_Offset;
69unsigned int txScaling_preamble;
70unsigned int txScaling_payload;
71
72unsigned int agcIIR_g, agcIIR_fb;
73
74
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.
80int warpphy_init(){
81    unsigned int i;
82    xil_printf("  Initializing WARPPHY:\n");
83
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
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   
93    //Initialize global variables
94    longCorrThresh = 9000;//3500; //2750
95   
96    afScaling = 2944;//6656;
97
98    //AGC target output power, in units of dBv (voltage at MAX2829 output)
99    agc_targetRxPowerOut = -18;
100
101    //AGC noise power estimate, in dBm
102    agc_noisePowerEstimate = -95;
103
104    //Base-rate modulation scheme; should be QPSK
105    baseRateMod = QPSK;
106
107    //Number of training symbol periods (all on 1 antenna for SISO, split across antennas for MIMO)
108    numTrainingSyms = NUM_TRAINING_SYMBOLS;
109
110    //Number of base rate OFDM symbols; every node must agree on this number ahead of time
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;
114
115    //Packet detection delay, in sys_clk cycles
116    // The Rx PHY waits this long before searching for correlation peaks
117    ofdmRx_pktDetDly = 124;
118
119    //Tx RF gain (6-bit value in [0,63])
120    txGain = 58;
121
122    //Tx scaling values; both are interpreted as UFix16_13 values
123    // The ratio of preamble/payload values should be approx 1/4
124    // Increasing these values will increase Tx power at the expense of clipping
125    txScaling_preamble = 3072;
126    txScaling_payload  = 12288;
127   
128    //Packet detector parameters
129    // Energy threshold - X/16 = RSSI
130    pktDet_energyThresh = 8000;
131
132    //Carrier sensing threshold - 8192/16 = RSSI of 512 (approx -65dBm Rx power)
133    pktDet_carrierSenseThresh = 8192;
134   
135    //Minimum duration of energy-above-energyThresh required to assert a packet detection
136    pktDet_threshMinDur = 24;
137   
138    //Define the FFT start offset (FFT will use (15 - offset) samples of cyclic prefix to handle synchronization
139    RxFFT_Window_Offset = INIT_RXFFTOFSET;
140
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
145    /*****************Radio Setup******************/
146    xil_printf("\tInitializing Radio Transmitter...\n");
147   
148    radio_controller_init(RC_BASEADDR, (RC_RFA | RC_RFB), 2, 2);
149   
150    radio_controller_apply_TxDCO_calibration(AD_BASEADDR, EEPROM_BASEADDR, (RC_RFA | RC_RFB));
151
152    radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFA | RC_RFB), (RC_TXEN_CTRLSRC | RC_RXEN_CTRLSRC | RC_RXHP_CTRLSRC), RC_CTRLSRC_HW);
153
154    radio_controller_setRadioParam(RC_BASEADDR, (RC_RFA | RC_RFB), RC_PARAMID_TXLPF_BW, 1);
155
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
164    xil_printf("\tInitializing Radio Receiver...");
165
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);
170
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);
173   
174    //Set Rx bandwidth; 0x0 = 15MHz (minimum)
175    radio_controller_setRadioParam(RC_BASEADDR, (RC_RFA | RC_RFB), RC_PARAMID_RXLPF_BW, 0);
176
177    xil_printf("complete!\n");
178    /**********************************************************/
179   
180    /*******************Packet Detector************************/
181    xil_printf("\tInitializing Packet Detection...");
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
190    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMinDuration(pktDet_threshMinDur);
191   
192    //Enable the carrier-sensing block's IDLE output (the timer can choose to use or ignore it)
193    ofdm_txrx_mimo_WriteReg_Rx_CSMA_enableIdle(1);
194   
195    //Hold the packet detector's running sum in reset
196    ofdm_txrx_mimo_WriteReg_Rx_PktDet_resetSum(1);
197   
198    //Configure the packet detector's antenna masks (1=antA, 2=antB, 3=both)
199    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMask(PKTDET_MASK_ANTA);
200   
201    //Set the packet detector's logic mode for the two antenna ports; 0 = AND, 1 = OR
202    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMode(1);
203   
204    //Set the running sum length; 16 is a good default
205    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setAvgLen(PKTDET_RSSI_SUMLEN);
206   
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);
209   
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);
217   
218    //Deassert the running sum reset; the sum will run continuously after this
219    ofdm_txrx_mimo_WriteReg_Rx_PktDet_resetSum(0);
220   
221    //Set thresholds for the autoCorrelation detector
222    //CorrThresh (UFix8_7): 0.7 ≈ 90
223    //MinPoiwer (UFix12_0); 2048 is theoretical max, 100-300 is more realistic, 0 works too
224    ofdm_txrx_mimo_WriteReg_Rx_PktDetCorr_params(90, 0);
225
226    //Enable both the RSSI and autoCorrelation packet detectors
227    ofdm_txrx_mimo_WriteReg_Rx_PktDet_rssiDetEn(1);
228    ofdm_txrx_mimo_WriteReg_Rx_PktDet_corrDetEn(1);
229   
230    //Deassert the packet detection output reset; packet detection events will start after this
231    ofdm_txrx_mimo_WriteReg_Rx_PktDet_ignoreDet(0);
232   
233    xil_printf("complete!\n");
234    /**********************************************************/
235   
236    /*************************PHY******************************/
237
238    xil_printf("\tInitializing OFDM Transmitter...");
239   
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
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   
263    //Set the AF scaling
264    mimo_ofdmRx_setAFTxScaling(afScaling);
265   
266    //Set the minimum magnitude for channels to use their pilots
267    mimo_ofdmRx_setPilotCalcParams(0xFFF); //MinMag as UFix12_12 (41 ~= 0.01)
268   
269    //Configure the FFT scaling values in the PHY Tx and Rx
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)));
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
277    mimo_ofdmTx_setPilotIndcies((7 + ((64-21)<<8) + ((64-7)<<16) + ((21)<<24) ));
278   
279    //Pilot tone values are Fix16_15, so
280    // Pilot 1 should be negative, pilot 2 should be positive
281    // 0x7FFF is +1, 0x8000 is -1
282    // 0xA57D is ~-0.707, 0x5A82 is ~+0.707
283    mimo_ofdmTxRx_setPilotValues( (0xA57D) + (0x5A82 << 16));
284   
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
287    warpphy_setTxNumSyms(numBaseRate, numTrainingSyms);
288    warpphy_setRxNumSyms(numBaseRate, numTrainingSyms);
289   
290    //Scaling constant for the transmitted preamble; helps normalize the amplitude of the stored preamble and actual IFFT output
291    mimo_ofdmTx_setTxScaling(txScaling_preamble, txScaling_payload);
292
293    //Configure various options in the Tx PHY
294    mimo_ofdmTx_setControlBits (
295                                (3 << 4) | //Preamble shift for antenna B
296                                ((0&0x3F) << 20) | //Cyclic shift
297                                TX_PILOT_SCRAMBLING | //Pseudo-random scrambling of pilot tones
298                                TX_SOFTWARE_TXEN | //Use the PHY TxStart register to start the overall PHY/radio Tx state machine
299                                //TX_RANDOM_PAYLOAD | //Use random payload bytes (user must still provide valid header!)
300                                //TX_ALWAYS_USE_PRECFO | //Always apply Tx CFO, even if the packet isn't triggered by auto responders
301                                //TX_DISABLE_ANTB_PREAMBLE | //Disables preamble on antenna B
302                                0
303                                );
304   
305    //Shift antenna B preambles by -3 samples
306    warpphy_setAntBPreambleShift(13);
307
308    xil_printf("complete!\n");
309   
310    xil_printf("\tInitializing OFDM Receiver...");
311
312    //Configure the FEC blocks
313    // (CodingEn, SoftDecodingEn, ZeroTailEn, QPSK_Scaling, 16QAM_Scaling)
314    mimo_ofdmTxRx_setFECoptions(1, 1, 0, 6, 16);
315   
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)
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)
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;
339    pktDetCFOsampCount = 255;
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
344
345    //Sets the delay between the pkt detection assertion and the PHY searching for correlation peaks
346    mimo_ofdmRx_setPktDetDly(ofdmRx_pktDetDly);
347    mimo_ofdmRx_setCFOCalcDly(0);
348    mimo_ofdmRx_setCFOMaxDiff(255); //UFix8_8 - 0.15 * 256 ≈ 38
349
350    warpphy_setPreCFOoptions( (PRECFO_USECOARSE | PRECFO_USEPILOTS) );
351   
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   
361    //Configure some sane defaults in the Rx PHY
362    mimo_ofdmRx_setOptions
363    (
364        RESET_BER | //Hold the BER meter in reset
365        REQ_LONG_CORR | //Require long correlation for packet detection
366        //RSSI_GAIN_ADJ | //Compensate RSSI input to pkt detector for RF gain changes
367        //BYPASS_CARR_REC | //Hold the Rx DDS in reset (ignoring any coarse CFO estimate)
368        COARSE_CFO_EN | //Enable coarse CFO estimation
369        TX_DISABLE_PKTDET | //Ignore packet detection during Tx
370        SIMPLE_DYN_MOD_EN | //Use the header's fullRate field for demodulation
371        RESET_ON_BAD_HDR | //Reset Rx PHY if header fails CRC
372        RECORD_CHAN_ESTS | //Enable the channel estimate recording buffer
373        RECORD_CHAN_ESTMAGS | //Enable the channel estimate recording buffer
374        //CHANMAG_MASKING_EN | //Enable channel magnitude masking
375        //0x4000 | //Bypass division in EQ
376        0,
377        activePHYStatusBits
378    );
379   
380    //Set the modulation masks to sane defaults
381    // 0xF enables dynamic modulation for that path
382    warpphy_set_modulation(baseRateMod, 0xF, 0xF, 0xF, 0xF);
383
384    //Set the antenna modes to SISO by default
385    warpphy_setAntennaMode(TX_ANTMODE_SISO_ANTA, RX_ANTMODE_SISO_ANTA);
386   
387    warpphy_setNumTrainingSyms(NUM_TRAINING_SYMBOLS);
388
389    //Set min chanest magnitudes (UFix16_15 values; set to zero to effectively disable)
390    warpphy_setChanEstMinMags(0);
391   
392    //Set AF blanking interval (set to zeros to disable)
393    warpphy_setAFblanking(0, 0);
394   
395    XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RX_FIXEDPKTLEN, 0);
396   
397    xil_printf("complete!\n");
398    /**********************************************************/
399   
400    /***************************AGC****************************/
401    xil_printf("\tInitializing AGC...");
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
406    ofdm_AGC_Initialize(agc_noisePowerEstimate);
407    ofdm_AGC_setNoiseEstimate(agc_noisePowerEstimate);
408
409    ofdm_AGC_SetDCO(0x6); //enable both subtraction and IIR filter
410   
411    ofdm_AGC_SetTarget(agc_targetRxPowerOut);
412    ofdm_AGC_Reset();
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   
417    xil_printf("complete!\n");
418    /**********************************************************/
419   
420    /**************************Timer***************************/
421    //Initialize the timer hardware; the individual timers will get setup in WARPMAC
422    warp_timer_init();
423    /**********************************************************/
424   
425    //Finally enable the PHY
426    mimo_ofdmTx_enable();
427    mimo_ofdmRx_enable();
428   
429    return 0;
430}
431
432///@brief Clears any pending Rx pkt status in the PHY. Was warpphy_pktAck() in previous versions.
433///
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.
437void warpphy_clearRxPktStatus(){
438   
439    //The TxRx_Interrupt_PktBuf_Ctrl register has many bits.
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);
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.
452void mimo_ofdmRx_enable(){
453   
454    //Clear any stale interrupts; this should never really be required
455    warpphy_clearRxPktStatus();
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.
466void 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
472    warpphy_clearRxPktStatus();
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
480///@param blockingStatusBits Configures which PHY Rx events block future receptions (good/bad header/payload)
481void mimo_ofdmRx_setOptions(unsigned int someOptions, unsigned int blockingStatusBits){
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
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));
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.
499unsigned 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.
508void mimo_ofdmTx_disable(){
509   
510    //Assert the OFDM Tx master reset and pktDone reset
511    ofdm_txrx_mimo_WriteReg_Tx_Start_Reset_Control(OFDM_BASEADDR, TX_MASTER_RESET);
512   
513    return;
514}
515
516///@brief Releases the OFDM Tx reset
517///
518/// Releases the OFDM Tx reset
519void mimo_ofdmTx_enable(){
520   
521    //Assert then clear the OFDM Tx master reset and pktDone reset
522    ofdm_txrx_mimo_WriteReg_Tx_Start_Reset_Control(OFDM_BASEADDR, TX_MASTER_RESET);
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///
535///@param block DEPRECATED Selects whether this funciton blocks until the transmission finishes; use TXBLOCK or TXNOBLOCK
536inline int warpphy_pktTx(unsigned int block){
537   
538   
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     */
544   
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);
549   
550    //Sleep long enough for the PHY to start transmitting; depends on second argument to SetTxTiming
551    usleep(6);
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.
561int warpphy_waitForTx(){
562
563    //warpmac_setDebugGPIO(0xF);
564
565    //Poll the PHY transmitter until it's finished transmitting
566    while(ofdm_txrx_mimo_ReadReg_Tx_PktRunning(OFDM_BASEADDR) & OFDM_TX_BUSY) {
567        //warpmac_incrementLEDLow();
568    }
569
570    //Workaround for very rare PHY race condition, where a goodHeader event occurred immediately
571    // before the transmission
572    warpphy_clearRxPktStatus();
573
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
585void 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
604void 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
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
622int 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();
628   
629    //Tx configuration
630    if(txMode != ANTMODE_UNCHANGED)
631    {
632        //Update the gloabl variable (used throughout to calculate "magic" numbers for the PHY)
633        warpphy_txAntMode = txMode;
634
635        //Take software control and disable both radio's Tx paths
636        // The correct radios will be re-enabled below
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       
640        //Enable hardware Tx control of either or both radios
641        switch(txMode & ANTMODE_MASK_ANTSEL)
642        {
643            case ANTMODE_ANTSEL_RADA:
644                activeRadios_Tx = RC_RFA;
645                radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFA), (RC_TXEN_CTRLSRC), RC_CTRLSRC_HW);
646                break;
647               
648            case ANTMODE_ANTSEL_RADB:
649                activeRadios_Tx = RC_RFB;
650                radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFB), (RC_TXEN_CTRLSRC), RC_CTRLSRC_HW);
651                break;
652               
653            case ANTMODE_ANTSEL_BOTHRADS:
654                activeRadios_Tx = (RC_RFA | RC_RFB);
655                radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFA | RC_RFB), (RC_TXEN_CTRLSRC), RC_CTRLSRC_HW);
656                break;
657
658            default:
659                xil_printf("Invalid Tx antenna mode!\n");
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:
668                //Set SISO mode, disable MIMO modes in the Tx PHY registers
669                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() & ~(TX_ALAMOUTI_MODE) );
670                mimo_ofdmTx_setControlBits(mimo_ofdmTx_getOptions() | TX_SISO_MODE);
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
684            default:
685                xil_printf("Invalid Tx PHY mode!\n");
686                return -1;
687                break;
688        }
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:
702                xil_printf("Invalid Tx PHYANT mode!\n");
703                return -1;
704                break;
705        }
706    }
707
708    if(rxMode != ANTMODE_UNCHANGED)
709    {
710        //Update the gloabl variable (used throughout to calculate "magic" numbers for the PHY)
711        warpphy_rxAntMode = rxMode;
712
713        //Take software control and disable both radio's Rx paths
714        // The correct radios will be re-enabled below
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));
717   
718        //Enable hardware Rx control of either or both radios
719        switch(rxMode & ANTMODE_MASK_ANTSEL)
720        {
721            case ANTMODE_ANTSEL_RADA:
722                activeRadios_Rx = RC_RFA;
723                radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFA), (RC_RXEN_CTRLSRC), RC_CTRLSRC_HW);
724                ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMask(PKTDET_MASK_ANTA);
725                break;
726               
727            case ANTMODE_ANTSEL_RADB:
728                activeRadios_Rx = RC_RFB;
729                radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFB), (RC_RXEN_CTRLSRC), RC_CTRLSRC_HW);
730                ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMask(PKTDET_MASK_ANTB);
731                break;
732               
733            case ANTMODE_ANTSEL_BOTHRADS:
734                activeRadios_Rx = (RC_RFA | RC_RFB);
735                radio_controller_setCtrlSource(RC_BASEADDR, (RC_RFA | RC_RFB), (RC_RXEN_CTRLSRC), RC_CTRLSRC_HW);
736                ofdm_txrx_mimo_WriteReg_Rx_PktDet_setMask(PKTDET_MASK_ANTA | PKTDET_MASK_ANTB);
737                break;
738               
739            default:
740                xil_printf("Invalid Rx antenna mode!\n");
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:
750                //Set SISO mode, disable MIMO modes in the Rx PHY registers
751                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~(RX_ALAMOUTI_MODE), activePHYStatusBits);
752                mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | RX_SISO_MODE, activePHYStatusBits);
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               
769            default:
770                xil_printf("Invalid Rx PHY mode!\n");
771                return -1;
772                break;
773        }
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:
793                xil_printf("Invalid Rx PHYANT mode!\n");
794                return -1;
795                break;
796               
797        }
798    }
799
800    //Finally, re-enbale the PHY Tx/Rx subsystems
801    mimo_ofdmRx_enable();
802    mimo_ofdmTx_enable();
803
804    //Pulse the PHY's RxEn register to re-enable receive paths on the active radios
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);
808   
809    return 0;
810}
811
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
815int 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:
835                xil_printf("Invalid Tx PHYANT mode!\n");
836                return -1;
837                break;
838        }
839    }
840       
841    return 0;
842}
843
844inline void warpphy_clearAutoResponseFlag(unsigned char flagID){
845
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    }
857
858    return;
859}
860
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///
867///@param numTraining number of training periods; must be even
868void warpphy_setNumTrainingSyms(unsigned int numTraining){
869    //Update the global variable; used each time a packet is transmitted
870    numTrainingSyms = numTraining;
871   
872    //Configure the PHY
873    warpphy_setTxNumSyms(numBaseRate, numTrainingSyms);
874    warpphy_setRxNumSyms(numBaseRate, numTrainingSyms);
875}
876
877void 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
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.
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
892///
893///@param baseRate Modulation scheme for base rate symbols
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
898void warpphy_set_modulation(unsigned char baseRate, unsigned char TxAntAFullRate, unsigned char TxAntBFullRate, unsigned char RxAntAFullRate, unsigned char RxAntBFullRate)
899{
900    unsigned int modIndex;
901
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 )
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    }
923
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    }
932   
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    }
941
942    if(RxAntBFullRate != MOD_UNCHANGED)
943    {
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        }
949    }
950   
951    //Update the global baseRate modulation variable
952    if(baseRate != MOD_UNCHANGED)
953    {
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        }
962    }
963
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)
969///@param chan Selects the channel number in the chosen band
970///@return Returns -1 if an invalid band or channel was specified; otherwise returns the new center frequency in MHz
971int warpphy_setChannel(unsigned char band, unsigned int chan){
972    int newFreq = -1;
973   
974    if (band == GHZ_2){
975        newFreq = radio_controller_setCenterFrequency(RC_BASEADDR, (RC_RFA|RC_RFB), RC_24GHZ, chan);
976    }
977    if (band == GHZ_5){
978        newFreq = radio_controller_setCenterFrequency(RC_BASEADDR, (RC_RFA|RC_RFB), RC_5GHZ, chan);
979    }
980       
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
990int 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)
996        newFreq_A = radio_controller_setCenterFrequency(RC_BASEADDR, (RC_RFA), RC_24GHZ, antA_chan);
997    if (antB_band == GHZ_2)
998        newFreq_B = radio_controller_setCenterFrequency(RC_BASEADDR, (RC_RFB), RC_24GHZ, antB_chan);
999    if (antA_band == GHZ_5)
1000        newFreq_A = radio_controller_setCenterFrequency(RC_BASEADDR, (RC_RFA), RC_5GHZ, antA_chan);
1001    if (antB_band == GHZ_5)
1002        newFreq_B = radio_controller_setCenterFrequency(RC_BASEADDR, (RC_RFB), RC_5GHZ, antB_chan);
1003    if(newFreq_A == -1 || newFreq_B == -1)
1004        return -1;
1005    else
1006        return newFreq_A;
1007}
1008
1009#ifdef HAVE_EEPROM
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
1013int warpphy_applyTxDCOCalibration(unsigned int radioSelection)
1014{
1015    int eepromStatus = 0;
1016    short calReadback = 0;
1017    signed short best_I, best_Q;
1018    unsigned char radioNum;
1019    Xuint8 memory[8], version, revision, valid;
1020    Xuint16 serial;
1021
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 ) );
1026//  xil_printf("Applying TxDCO correction for radio %d\n", radioNum);
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]
1030    eepromStatus = WarpEEPROM_EEPROMSelect((unsigned int *)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, 0);
1031    if(eepromStatus != 0)
1032    {
1033        xil_printf("EEPROM Select Failed!\n");
1034        return -1;
1035    }
1036   
1037    //Initialize the EEPROM controller
1038    eepromStatus = WarpEEPROM_Initialize((unsigned int *)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR);
1039    if(eepromStatus != 0)
1040    {
1041        xil_printf("EEPROM Init Returned %x\n", eepromStatus);
1042        xil_printf("EEPROM Init Failed!\n");
1043        return -1;
1044    }
1045
1046    //Select the EEPROM on the current radio board
1047    eepromStatus = WarpEEPROM_EEPROMSelect((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, radioNum);
1048
1049    if(eepromStatus != 0)
1050    {
1051        xil_printf("TxDCO: EEPROM error\n");
1052        return -1;
1053    }
1054   
1055    //Read the first page from the EERPOM
1056    WarpEEPROM_ReadMem((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, 0, 0, memory);
1057    version = (memory[0] & 0xE0) >> 5;
1058    revision = (memory[1] & 0xE0) >> 5;
1059    valid = memory[1] & 0x1F;
1060
1061//  xil_printf("\n\nEEPROM Values for Radio Board in Slot %d\n", radioNum);
1062
1063//  xil_printf("    WARP Radio Board Version %d.%d\n", version, revision);
1064
1065    serial = WarpEEPROM_ReadWARPSerial((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR);
1066
1067//  xil_printf("    Serial Number (WARP): WR-a-%05d\n", serial);
1068
1069    WarpEEPROM_ReadDSSerial((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, memory);
1070//  print("    EEPROM Hard-wired Serial Number: ");
1071//  for(i=1;i<7;i++)
1072//      xil_printf(" %x",memory[7-i]);
1073//  xil_printf("\n\n");
1074    //Read the Tx DCO values
1075    calReadback = WarpEEPROM_ReadRadioCal((unsigned int*)XPAR_EEPROM_CONTROLLER_MEM0_BASEADDR, 2, 1);
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   
1081    xil_printf("\t\tTxDCO values for radio %d - I: %d\tQ: %d\n", radioNum, best_I, best_Q);
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   
1087    return 0;
1088}
1089
1090#endif
1091/******* AGC core control functions ********/
1092
1093unsigned 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    }
1106    xil_printf("BBGAIN %d\n",(warpphy_returnAGCgainBB(antenna)<<1));
1107    return ((warpphy_returnAGCgainBB(antenna)<<1) + rfGain);
1108*/
1109
1110unsigned int rfGain,bbGain,gainDB,rfGainDB,bbGainDB;
1111unsigned 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
1145inline void ofdm_AGC_SetDCO(unsigned int AGCstate){
1146
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)
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));
1156   
1157    return;
1158}
1159
1160void 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
1173void 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
1190void 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
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); //
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
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    );
1217   
1218    // Overall AGC timing
1219//  OFDM_AGC_MIMO_WriteReg_Timing(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x9A962A28);//0x826E3C0A;
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);
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
1223   
1224    // vIQ and RSSI average lengths
1225    OFDM_AGC_MIMO_WriteReg_AVG_LEN(XPAR_OFDM_AGC_MIMO_OPBW_0_BASEADDR, 0x10F); //103
1226   
1227    // Disable DCO, disable DCO subtraction
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
1244void 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
1254unsigned 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
1279void 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
1285
1286
1287/******* WARP Timer core control functions *******/
1288void warp_timer_start(unsigned char timer) {
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));
1291}
1292
1293void warp_timer_pause(unsigned char timer) {
1294    warp_timer_WriteReg_control(warp_timer_ReadReg_control() | (TIMER_MASK_CALC(timer) & TIMER_CONTROL_PAUSE_MASK));
1295}
1296
1297void warp_timer_resume(unsigned char timer) {
1298    warp_timer_WriteReg_control(warp_timer_ReadReg_control() & ~(TIMER_MASK_CALC(timer) & TIMER_CONTROL_PAUSE_MASK));
1299}
1300
1301void warp_timer_setMode(unsigned char timer, unsigned char mode) {
1302    if(mode == 1)
1303        warp_timer_WriteReg_control(warp_timer_ReadReg_control() | (TIMER_MASK_CALC(timer) & TIMER_CONTROL_MODE_MASK));
1304    else
1305        warp_timer_WriteReg_control(warp_timer_ReadReg_control() & ~(TIMER_MASK_CALC(timer) & TIMER_CONTROL_MODE_MASK));
1306}
1307
1308void 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));
1311}
1312
1313void 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));
1316}
1317
1318void warp_timer_setTimer(unsigned char timer, unsigned int slotTime, unsigned int slotCount) {
1319    switch(timer) {
1320    case 0:
1321        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER0_SLOTCOUNT, (Xuint32)(slotCount));
1322        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS01_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS01_SLOTTIME) & 0xFFFF0000) | slotTime) );
1323        return;
1324    case 1:
1325        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER1_SLOTCOUNT, (Xuint32)(slotCount));
1326        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS01_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS01_SLOTTIME) & 0x0000FFFF) | (slotTime<<16) ) ); 
1327        return;
1328    case 2:
1329        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER2_SLOTCOUNT, (Xuint32)(slotCount));
1330        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS23_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS23_SLOTTIME) & 0xFFFF0000) | slotTime) );
1331        return;
1332    case 3:
1333        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER3_SLOTCOUNT, (Xuint32)(slotCount));
1334        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS23_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS23_SLOTTIME) & 0x0000FFFF) | (slotTime<<16) ) );
1335        return;
1336    case 4:
1337        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER4_SLOTCOUNT, (Xuint32)(slotCount));
1338        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS45_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS45_SLOTTIME) & 0xFFFF0000) | slotTime) );
1339        return;
1340    case 5:
1341        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER5_SLOTCOUNT, (Xuint32)(slotCount));
1342        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS45_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS45_SLOTTIME) & 0x0000FFFF) | (slotTime<<16) ) );
1343        return;
1344    case 6:
1345        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER6_SLOTCOUNT, (Xuint32)(slotCount));
1346        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS67_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS67_SLOTTIME) & 0xFFFF0000) | slotTime) );
1347        return;
1348    case 7:
1349        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER7_SLOTCOUNT, (Xuint32)(slotCount));
1350        XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS67_SLOTTIME, ( (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMERS67_SLOTTIME) & 0x0000FFFF) | (slotTime<<16) ) );
1351        return;
1352    default:
1353        return;
1354    }
1355}
1356
1357unsigned char warp_timer_getStatus(unsigned char timer) {
1358    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) >> (timer*4)) & 0xf;
1359}
1360
1361unsigned 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;
1363}
1364
1365unsigned char warp_timer_isActive(unsigned char timer) {
1366    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) & TIMER_MASK_CALC(timer) & TIMER_STATUS_RUNNING_MASK) != 0;
1367}
1368
1369unsigned char warp_timer_isPaused(unsigned char timer) {
1370    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) & TIMER_MASK_CALC(timer) & TIMER_STATUS_PASUED_MASK) != 0;
1371}
1372
1373unsigned int warp_timer_getStatuses() {
1374    return XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS);
1375}
1376
1377unsigned char warp_timer_getDoneStatus() {
1378    return (XIo_In32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_STATUS) & TIMER_STATUS_DONE_MASK);
1379}
1380
1381void warp_timer_init(){
1382    //Clear all start/pause/mode/donereset bits
1383    XIo_Out32(XPAR_WARP_TIMER_PLBW_0_MEMMAP_TIMER_CONTROL, 0);
1384
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();
1397    return;
1398}
1399/******* END WARP Timer core control functions *******/
1400
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
1404int warpphy_setTxPower(unsigned char txPwr)
1405{
1406    if(txPwr > 63)
1407        return -1;
1408    else
1409        radio_controller_setTxGainTarget(RC_BASEADDR, (RC_RFA | RC_RFB), txPwr);
1410
1411    return 0;
1412}
1413
1414void warpphy_setAutoCorrDetParams(unsigned short corrThresh, unsigned short energyThresh) {
1415    ofdm_txrx_mimo_WriteReg_Rx_PktDetCorr_params(corrThresh, energyThresh);
1416    return;
1417}
1418
1419void warpphy_setLongCorrThresh(unsigned short thresh) {
1420    pktDet_carrierSenseThresh = thresh;
1421    XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_RX_PKTDET_LONGCORR_THRESHOLDS, thresh);
1422}
1423
1424void warpphy_setCarrierSenseThresh(unsigned short thresh) {
1425    longCorrThresh = thresh;
1426    ofdm_txrx_mimo_WriteReg_Rx_CSMA_setThresh(pktDet_carrierSenseThresh);
1427}
1428
1429void warpphy_setEnergyDetThresh(unsigned short thresh) {
1430    pktDet_energyThresh = thresh;
1431    ofdm_txrx_mimo_WriteReg_Rx_PktDet_setThresh(thresh);
1432}
1433
1434
1435void warpphy_setAntBPreambleShift(unsigned char shift)
1436{
1437    mimo_ofdmTx_setControlBits( (mimo_ofdmTx_getOptions() & ~(0xF0)) | ((shift&0xF)<<4) );
1438}
Note: See TracBrowser for help on using the repository browser.