rtsctsMac.c

Go to the documentation of this file.
00001 
00038 #include <string.h>
00039 #include <errno.h>
00040 #include <stdlib.h>
00041 #include <stdio.h>
00042 
00043 #include "xparameters.h"
00044 #include "xutil.h"
00045 #include "ofdm_pktdetector_mimo_regMacros.h"
00046 #include "warp_timer_regMacros.h"
00047 #include "ofdm_txrx_mimo_regMacros.h"
00048 #include "warpmac.h"
00049 #include "warpphy.h"
00050 #include "rtsctsMac.h"
00051 #include "rtsctsTest.h"
00052 #include "ascii_characters.h"
00053 
00054 
00056 struct {
00058         Macframe rx;
00060         Macframe rts;
00062         Macframe cts;
00064         Macframe dat;
00066         Macframe ack;
00068         Macframe bcd;
00069 } pkt;
00070 
00072 enum {IDLE,BUSY};
00073 
00075 enum {RTS=1,CTS=2,DAT=3,ACK=4,BCD=5,ETH=6};
00076 
00078 struct {
00080         unsigned short slot;
00082         unsigned short SIFS;
00084         unsigned short DIFS;
00086         unsigned short EIFS;
00087         
00089         unsigned short header;
00091         unsigned short transmit[5];
00093         unsigned short timeout[5];
00094 } delay;
00095 
00097 unsigned int pktCtr[4][7];
00099 enum {TX=0, RXGOOD=1, RXUNEXP=2, RXBAD=3, DROP=3};
00100 
00102 struct {
00104         unsigned char antA[8];
00106         unsigned char antB[8];
00108         unsigned char half[8];
00110         unsigned char otherhalf[8];
00112         unsigned char alternating[8];
00114         unsigned char * current;
00115 } csi = {
00116         .antA = {0, 0, 0, 0, 0, 0, 0, 0},
00117         .antB = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
00118         .half = {0,0,0,0,0xFF,0xFF,0xFF,0xFF},
00119         .otherhalf = {0xFF,0xFF,0xFF,0xFF,0,0,0,0},
00120         .alternating = {0x55,0x55,0x55,0x55,0x55,0x55,0x55,0x55},
00121 };
00122 
00123 
00125 const unsigned char modMasks[64] = {
00126         0x0,0xF,0xF,0xF,0xF,0xF,0xF,0x0, 0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,
00127         0xF,0xF,0xF,0xF,0xF,0x0,0xF,0xF, 0xF,0xF,0xF,0x0,0x0,0x0,0x0,0x0,
00128         0x0,0x0,0x0,0x0,0x0,0x0,0xF,0xF, 0xF,0xF,0xF,0x0,0xF,0xF,0xF,0xF,
00129         0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF, 0xF,0x0,0xF,0xF,0xF,0xF,0xF,0xF};
00130 
00132 const unsigned char modFlags[64] = {
00133         0,1,1,1,1,1,1,0, 1,1,1,1,1,1,1,1,
00134         1,1,1,1,1,0,1,1, 1,1,1,0,0,0,0,0,
00135         0,0,0,0,0,0,1,1, 1,1,1,0,1,1,1,1,
00136         1,1,1,1,1,1,1,1, 1,0,1,1,1,1,1,1};
00137         
00139 struct {
00141         unsigned short rtsThreshold;
00143         unsigned char feedback_en;
00145         unsigned char mac;
00147         unsigned char chan;
00149         unsigned char currentAnt;
00151         unsigned char myID;
00153         unsigned char GPIOval;
00155         const unsigned char baseRate;
00157         const unsigned char fullRate;
00159         const unsigned char csiLength;
00160         
00162         struct {
00164                 unsigned short rts;
00166                 unsigned short dat;
00167         } maxResend;
00168         
00170         struct {
00172                 unsigned char my[6];
00174                 const unsigned char bc[6];
00176                 const unsigned char net[4];
00177         } addr;
00178         
00180         struct {
00181                 unsigned char addr[6];
00182         } routeTable[16];
00183         
00184 } state = {
00185         .rtsThreshold = 0,
00186         .feedback_en = 0,
00187         .mac = IDLE,
00188         .chan = 14,
00189         .currentAnt = 0,
00190         .GPIOval = 0,
00191         .baseRate = QPSK,
00192         .fullRate = QPSK,
00193         .csiLength = 0,         // set to 8 when using feedback
00194         .maxResend.rts = 4,
00195         .maxResend.dat = 2,
00196         .addr.bc = {0xff,0xff,0xff,0xff,0xff,0xff},
00197         .addr.net = {10,0,0,0},
00198 };
00199 
00200 
00201 
00207 static inline unsigned int ceil_div_uint(unsigned int a, unsigned int b) {
00208         return (a+b-1)/b;
00209 }
00210 
00211 
00216 static inline void setCSMAIdleTime(unsigned int newTime) {
00217         ofdm_pktDetector_mimo_WriteReg_csma_difsPeriod(PKTDET_BASEADDR, newTime*80);
00218 }
00219 
00220 
00226 static inline void setTXModMasks(unsigned char * newCSI) {
00227         unsigned char modIndex, csiByte, csiMask, antAmask, antBmask;
00228         /*
00229         for(modIndex=0; modIndex<64; modIndex++) {
00230                 csiByte = newCSI[modIndex/8];
00231                 csiMask = ((csiByte >> (modIndex & 3)) & 1) * 0xF;
00232                 antAmask = modMasks[modIndex] & ~csiMask;
00233                 antBmask = modMasks[modIndex] & csiMask;
00234 
00235                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), antAmask);
00236                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)+64), antBmask);
00237                 
00238                 //xil_printf("\n%02x\t%02x\t%02x\t%02x", csiByte, csiMask, antAmask, antBmask);
00239         }
00240         */
00241         
00242         for(modIndex=0; modIndex<64; modIndex++) {
00243                 if(modFlags[modIndex]) {
00244                         csiByte = newCSI[modIndex/8];
00245                         if((csiByte >> (modIndex % 8)) & 1) {
00246                                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), 0);
00247                                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+((modIndex+64)*sizeof(int)), 0xF);
00248                         } else {
00249                                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+(modIndex*sizeof(int)), 0xF);
00250                                 XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+((modIndex+64)*sizeof(int)), 0);
00251                         }
00252                 }
00253         }
00254         
00255         /*
00256         #define modset(i,j) \
00257         if(modFlags[modIndex]) { \
00258                 if(csiByte & i) { \
00259                         XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+((modIndex+j)*sizeof(int)), 0); \
00260                         XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+((modIndex+j+64)*sizeof(int)), 0xF); \
00261                 } else { \
00262                         XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+((modIndex+j)*sizeof(int)), 0xF); \
00263                         XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXMODULATION+((modIndex+j+64)*sizeof(int)), 0); \
00264                 } \
00265         }
00266         for(modIndex=0; modIndex<64; modIndex+=8) {
00267                 csiByte = newCSI[modIndex/8];
00268                 modset(1,0)
00269                 modset(2,1)
00270                 modset(4,2)
00271                 modset(8,3)
00272                 modset(16,4)
00273                 modset(32,5)
00274                 modset(64,6)
00275                 modset(128,7)
00276         }
00277         #undef modset
00278         */
00279 }
00280 
00281 
00284 void unlockRXantenna() {
00285         if(state.feedback_en) {
00286                 warpphy_setSISOAntenna(state.currentAnt = 0);
00287                 mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() | SWITCHING_DIV_EN,
00288                         DEFAULT_INTERRUPTS);
00289         }
00290 }
00291 
00292 
00296 void lockRXantenna() {
00297         if(state.feedback_en) {
00298                 mimo_ofdmRx_setOptions(mimo_ofdmRx_getOptions() & ~SWITCHING_DIV_EN,
00299                         DEFAULT_INTERRUPTS);
00300                 unsigned int g = ofdm_AGC_GetGains();
00301                 // choose ant. B if AGC gave it a lower gain, else choose ant. A
00302                 state.currentAnt = (((g >> 8) & 0x7F) < (g & 0x7F)) ? 1 : 0;
00303                 warpphy_setSISOAntenna(state.currentAnt);
00304         }
00305 }
00306 
00307 
00311 void loadCSI(unsigned char * newCSI) {
00312         extern Maccontrol controlStruct;
00313         if(state.csiLength > 0) {
00314                 memcpy((unsigned char *)(warpphy_getBuffAddr(3) + NUM_HEADER_BYTES),
00315                         (unsigned char *)newCSI,
00316                         state.csiLength);
00317         }
00318 }
00319 
00320 
00325 void updateTimer(unsigned char type, unsigned int newTime) {
00326         extern Maccontrol controlStruct;        // used for tracking the backoff
00327         switch(type) {
00328         case TIMEOUT:
00329                 if(!warp_timer_isActive(NAV)) {
00330                         // convert microseconds to timer clock cycles
00331                         newTime = (newTime + delay.slot) * 80;  // margin added for processing time
00332                         if(warp_timer_isActive(BACKOFF))
00333                                 warp_timer_pause(BACKOFF);
00334                         warp_timer_setVal(TIMEOUT, newTime);
00335                         warp_timer_start(TIMEOUT);
00336                 }
00337                 break;
00338         case BACKOFF:
00339                 state.mac = IDLE;
00340                 newTime = randNum(controlStruct.currBackoff) * delay.slot * 80;
00341                 if(!warp_timer_isActive(TIMEOUT) && !warp_timer_isActive(NAV)) {
00342                         if(warp_timer_isPaused(BACKOFF)) {
00343                                 warp_timer_resume(BACKOFF);
00344                         } else {
00345                                 warp_timer_setVal(BACKOFF, newTime);
00346                                 warp_timer_start(BACKOFF);
00347                                 if(controlStruct.currBackoff < controlStruct.maxBackoff)
00348                                         controlStruct.currBackoff++;
00349                         }
00350                 } else {
00351                         warp_timer_stop(BACKOFF);
00352                         warp_timer_setVal(BACKOFF, newTime);
00353                         warp_timer_start(BACKOFF);
00354                         warp_timer_pause(BACKOFF);
00355                         if(controlStruct.currBackoff < controlStruct.maxBackoff)
00356                                 controlStruct.currBackoff++;
00357                 }
00358                 break;
00359         case NAV:
00360                 // convert microseconds to timer clock cycles
00361                 newTime = newTime * 80;
00362                 if(warp_timer_isActive(TIMEOUT))
00363                         warp_timer_stop(TIMEOUT);
00364                 if(warp_timer_isActive(BACKOFF))
00365                         warp_timer_pause(BACKOFF);
00366                 if(warp_timer_isActive(NAV)) {
00367                         warp_timer_pause(NAV);
00368                         if(warp_timer_timeLeft(NAV) < newTime) {
00369                                 warp_timer_setVal(NAV, newTime);
00370                                 warp_timer_start(NAV);
00371                         } else {
00372                                 warp_timer_resume(NAV);
00373                         }
00374                 } else {
00375                         warp_timer_setVal(NAV, newTime);
00376                         warp_timer_start(NAV);
00377                 }
00378                 
00379                 break;
00380         }
00381 }
00382 
00383 
00386 int rtsmac_timer_callback(unsigned char unused) {
00387         extern unsigned char timerIntStatus;
00388         if(timerIntStatus & 2) {
00389                 // backoff expired
00390                 if(pkt.bcd.isNew)
00391                         sendBCD();
00392                 else if(pkt.dat.isNew)
00393                         initTX();
00394         } else {
00395                 // timeout or NAV expired
00396                 //tvar[state.mac]++;
00397                 updateTimer(BACKOFF, 0);
00398         }
00399         unlockRXantenna();
00400         return 0;
00401 }
00402 
00403 
00406 void dropPacket() {
00407         pkt.dat.isNew = 0;
00408         pkt.bcd.isNew = 0;
00409         state.mac = IDLE;
00410         pktCtr[DROP][ETH]++;
00411         warpmac_enableEthernet();
00412 }
00413 
00414 
00423 int rtsmac_emacRx_callback(Xuint32 length, char* payload) {
00424         UTime time;
00425         warpmac_disableEthernet();
00426         pktCtr[RXGOOD][ETH]++;
00427         
00428         if(*(unsigned char *)(payload+33)<16
00429                 && *(unsigned char *)(payload+32)==state.addr.net[2]
00430                 && *(unsigned char *)(payload+31)==state.addr.net[1]
00431                 && *(unsigned char *)(payload+30)==state.addr.net[0]) {
00432                 // complete the data packet header
00433                 // enable RTS/CTS if length of packet > RTS threshold
00434                 pkt.dat.header.reserved4 = (length > state.rtsThreshold) ? 0 : 1;
00435                 pkt.dat.header.length = length;
00436                 memcpy(pkt.dat.header.destAddr,
00437                         state.routeTable[*(unsigned char *)(payload+33)].addr,
00438                         6);
00439                 pkt.dat.header.currReSend = 0;
00440                 pkt.dat.isNew = 1;
00441                 
00442                 // calculate transmission time for data packet
00443                 delay.transmit[DAT] = delay.header + 8*ceil_div_uint((length+4), (state.fullRate & 0xF)*6);
00444                 delay.timeout[DAT] = delay.transmit[DAT] + 44;          //44us turnaround between CTS and DAT
00445                 // complete the RTS packet header
00446                 memcpy(pkt.rts.header.destAddr, pkt.dat.header.destAddr, 6);
00447                 pkt.rts.header.currReSend = 0;
00448                 time.uint16 = delay.timeout[CTS] + delay.timeout[DAT] + delay.timeout[ACK];
00449                 pkt.rts.header.reserved1 = time.uint8[0];
00450                 pkt.rts.header.reserved2 = time.uint8[1];
00451                 
00452                 initTX();
00453         } else {
00454                 // set up and load BCD packet once so that subsequent calls to sendBCD can skip this step
00455                 pkt.bcd.header.length = length;
00456                 pkt.bcd.isNew = 1;
00457                 warpmac_prepPhyForXmit(&pkt.bcd,1);
00458                 sendBCD();
00459         }
00460         
00461         return 0;
00462 }
00463 
00464 
00472 void initTX() {
00473         if(pkt.dat.isNew) {
00474                 if((pkt.rts.header.currReSend <= state.maxResend.rts) && (pkt.dat.header.currReSend <= state.maxResend.dat)) {
00475                         if(!warp_timer_isActive(NAV) && !warp_timer_isActive(TIMEOUT)) {
00476                                 if(warpmac_carrierSense()) {
00477                                         if(pkt.dat.header.reserved4 == 1) {
00478                                                 // begin with data packet (send without RTS/CTS exchange)
00479                                                 warpmac_prepPhyForXmit(&pkt.dat, 1);
00480                                                 sendDAT();
00481                                         } else {
00482                                                 // begin with RTS
00483                                                 warpmac_prepPhyForXmit(&pkt.rts, 2);
00484                                                 warpmac_startPhyXmit(2);
00485                                                 state.mac = CTS;
00486                                                 pktCtr[TX][RTS]++;
00487                                                 pkt.rts.header.currReSend++;
00488                                                 warpmac_finishPhyXmit();
00489                                                 updateTimer(TIMEOUT, delay.timeout[CTS]);
00490                                                 // set fullRate for MISO if feedback is enabled, SISO otherwise
00491                                                 pkt.dat.header.fullRate = (state.feedback_en) ? (state.fullRate | (state.fullRate<<4)) : state.fullRate;
00492                                                 // copy data packet header into PHY while waiting for CTS
00493                                                 warpmac_prepPhyForXmit(&pkt.dat, 1);
00494                                         }
00495                                         setCSMAIdleTime(delay.DIFS);    // reset to DIFS (in case EIFS was previously set)
00496                                 } else {
00497                                         updateTimer(BACKOFF, 0);
00498                                 }
00499                         }
00500                 } else {
00501                         // resend limit has been reached
00502                         dropPacket();
00503                 }
00504         }
00505 }
00506 
00507 
00512 void sendCTS(Macframe* packet) {
00513         UTime time;
00514         
00515         if(state.feedback_en) {
00516                 lockRXantenna();        // we send only CSI corresponding to the locked antenna
00517                 loadCSI(csi.current);
00518         }
00519         
00520         memcpy(pkt.cts.header.destAddr,packet->header.srcAddr,6);
00521         // set the NAV of other nodes to reserve the channel
00522         time.uint8[0] = packet->header.reserved1;
00523         time.uint8[1] = packet->header.reserved2;
00524         // calculate new NAV time using RTS's NAV time
00525         time.uint16 = time.uint16 - delay.timeout[CTS];
00526         pkt.cts.header.reserved1 = time.uint8[0];
00527         pkt.cts.header.reserved2 = time.uint8[1];
00528         
00529         delay.timeout[DAT] = time.uint16 - delay.timeout[ACK];
00530         
00531         warpmac_prepPhyForXmit(&pkt.cts, 3);
00532         
00533         // send CTS packet if NAV indicates channel is idle, else do not respond
00534         if(!warp_timer_isActive(NAV)) {
00535                 warpmac_startPhyXmit(3);                        // CSI must be in buffer 3
00536                 pktCtr[TX][CTS]++;
00537                 state.mac = DAT;
00538                 warpmac_finishPhyXmit();
00539                 updateTimer(TIMEOUT, delay.timeout[DAT]);
00540         }
00541 }
00542 
00543 
00545 void sendDAT() {
00546         extern Maccontrol controlStruct;
00547         if(state.feedback_en) {
00548                 //load modulation masks from received CTS packet
00549                 setTXModMasks(csi.current);
00550                 //setTXModMasks((unsigned char *)(warpphy_getBuffAddr(controlStruct.rxBuffIndex) + NUM_HEADER_BYTES));
00551                 warpmac_enableMisoMode();
00552                 warpmac_startPhyXmit(1);
00553                 warpmac_finishPhyXmit();
00554                 warpmac_disableMisoMode();
00555         } else {
00556                 warpmac_startPhyXmit(1);
00557                 warpmac_finishPhyXmit();
00558         }
00559         pktCtr[TX][DAT]++;
00560         pkt.dat.header.currReSend++;
00561         state.mac = ACK;
00562         updateTimer(TIMEOUT, delay.timeout[ACK]);
00563 }
00564 
00565 
00568 void sendBCD() {
00569         if(!warp_timer_isActive(NAV) && !warp_timer_isActive(TIMEOUT)) {
00570                 if(warpmac_carrierSense()) {
00571                         warpmac_startPhyXmit(1);
00572                         pkt.bcd.isNew = 0;
00573                         pktCtr[TX][BCD]++;
00574                         setCSMAIdleTime(delay.DIFS);
00575                         warpmac_finishPhyXmit();
00576                         warpmac_enableEthernet();
00577                 }
00578                 updateTimer(BACKOFF, 0);
00579         }
00580 }
00581 
00582 
00584 int rtsmac_phyRx_badHeader_callback() {
00585         updateTimer(BACKOFF, 0);
00586         setCSMAIdleTime(delay.EIFS);
00587         unlockRXantenna();
00588         warpmac_incrementLEDLow();
00589         return 0;
00590 }
00591 
00592 
00600 int rtsmac_phyRx_goodHeader_callback(Macframe* packet) {
00601         extern Maccontrol controlStruct;
00602         unsigned char rxStatus = INCOMPLETE;
00603         if(warpmac_addressedToMe(packet) && !warp_timer_isActive(NAV)) {
00604                 warp_timer_stop(TIMEOUT);
00605                 //warpmac_setDebugGPIO(state.GPIOval |= 1);
00606                 if(packet->header.pktType == RTS && (state.mac == IDLE || state.mac == DAT)) {
00607                         while(rxStatus == INCOMPLETE) {
00608                                 rxStatus = warpphy_pollRxStatus();
00609                         }
00610                         if(rxStatus == GOODPACKET) {
00611                                 sendCTS(packet);
00612                         }
00613                 } else if(packet->header.pktType == CTS && state.mac == CTS) {
00614                         while(rxStatus == INCOMPLETE) {
00615                                 rxStatus = warpphy_pollRxStatus();
00616                         }
00617                         if(rxStatus == GOODPACKET) {
00618                                 sendDAT();
00619                         }
00620                 } else if(packet->header.pktType == DAT
00621                         && (state.mac == DAT  && packet->header.reserved4 == 0
00622                          || state.mac == IDLE && packet->header.reserved4 == 1)) {
00623                         memcpy(pkt.ack.header.destAddr,packet->header.srcAddr,6);
00624                         warpmac_prepPhyForXmit(&pkt.ack,2);
00625                         while(rxStatus == INCOMPLETE) {
00626                                 rxStatus = warpphy_pollRxStatus();
00627                         }
00628                         if(rxStatus == GOODPACKET) {
00629                                 //Send packet buffer 2 containing the ACK
00630                                 warpmac_startPhyXmit(2);
00631                                 //Starts the DMA transfer of the payload into the EMAC
00632                                 warpmac_prepEmacForXmit(packet);
00633                                 pktCtr[TX][ACK]++;
00634                                 pktCtr[TX][ETH]++;
00635                                 //Blocks until the PHY is finished sending and enables the receiver
00636                                 warpmac_finishPhyXmit();
00637                                 //Waits until the DMA transfer is complete, then starts the EMAC
00638                                 warpmac_startEmacXmit(packet);
00639                                 updateTimer(BACKOFF, 0);
00640                                 unlockRXantenna();
00641                         }
00642                 } else if(packet->header.pktType == ACK && state.mac == ACK) {
00643                         // respond to ACK only if expecting ACK
00644                         while(rxStatus == INCOMPLETE) {
00645                                 rxStatus = warpphy_pollRxStatus();
00646                         }
00647                         if(rxStatus == GOODPACKET) {
00648                                 pkt.dat.isNew = 0;
00649                                 controlStruct.currBackoff = 0;
00650                                 updateTimer(BACKOFF, 0);
00651                                 warpmac_enableEthernet();
00652                         }
00653                 } else {
00654                         // packet was not expected, invoke backoff procedure
00655                         while(rxStatus == INCOMPLETE) {
00656                                 rxStatus = warpphy_pollRxStatus();
00657                         }
00658                         if(rxStatus == GOODPACKET) {
00659                                 pktCtr[RXGOOD][packet->header.pktType]--;
00660                                 pktCtr[RXUNEXP][packet->header.pktType]++;
00661                                 updateTimer(BACKOFF, 0);
00662                         }
00663                 }
00664          } else if(packet->header.pktType == BCD) {
00665                 // packet was broadcast, simply forward over ethernet and backoff
00666                 while(rxStatus == 0) {
00667                         rxStatus = warpphy_pollRxStatus();
00668                 }
00669                 if(rxStatus == GOODPACKET) {
00670                         //Starts the DMA transfer of the payload into the EMAC
00671                         warpmac_prepEmacForXmit(packet);
00672                         //Waits until the DMA transfer is complete, then starts the EMAC
00673                         warpmac_startEmacXmit(packet);
00674                         updateTimer(BACKOFF, 0);
00675                 }
00676         } else {
00677                 // packet addressed to someone else, set/update NAV timer to reserve channel
00678                 UTime time;
00679                 time.uint8[0] = packet->header.reserved1;
00680                 time.uint8[1] = packet->header.reserved2;
00681                 if(time.uint16 > 0) {
00682                         updateTimer(NAV,time.uint16);
00683                 }
00684         }
00685         
00686         if(rxStatus == GOODPACKET) {
00687                 pktCtr[RXGOOD][packet->header.pktType]++;
00688                 warpmac_incrementLEDHigh();
00689         } else if(rxStatus == BADPACKET) {
00690                 pktCtr[RXBAD][packet->header.pktType]++;
00691                 rtsmac_phyRx_badHeader_callback();
00692         }
00693         //warpmac_setDebugGPIO(state.GPIOval &= ~1);
00694         return 0;
00695 }
00696 
00697 
00698 
00699 
00703 int main() {
00704         xil_printf("\r\nInitializing RTS/CTS MAC...\r\n");
00705         
00706         //Initialize the framework
00707         warpmac_init();
00708         
00709         initDelays();
00710         initAddresses();
00711         initHeaders();
00712         
00713         state.mac = IDLE;
00714         clearPktCtr();
00715         
00716         // setup timer modes
00717         warp_timer_setMode(TIMEOUT, DISABLECSMA);
00718         warp_timer_setMode(BACKOFF, ENABLECSMA);
00719         warp_timer_setMode(NAV, DISABLECSMA);
00720         
00721         //Rx buffer is where the EMAC will DMA Wireless payloads from
00722         warpmac_setRxBuffer(&pkt.rx,0);
00723         //Tx buffer is where the EMAC will DMA Ethernet payloads to
00724         warpmac_setTxBuffer(1);
00725         
00726         warpmac_setBadHeaderCallback((void *)rtsmac_phyRx_badHeader_callback);
00727         warpmac_setGoodHeaderCallback((void *)rtsmac_phyRx_goodHeader_callback);
00728         warpmac_setTimerCallback((void *)rtsmac_timer_callback);
00729         warpmac_setEmacCallback((void *)rtsmac_emacRx_callback);
00730         warpmac_setUpButtonCallback((void *)rtsmac_up);
00731         warpmac_setMiddleButtonCallback((void *)rtsmac_middle);
00732         warpmac_setLeftButtonCallback((void *)rtsmac_left);
00733         warpmac_setRightButtonCallback((void *)rtsmac_right);
00734         
00735         //Set the default center frequency
00736         warpphy_setChannel(GHZ_2, state.chan);
00737         
00738         warpmac_enableCSMA();
00739         warpmac_enableEthernet();
00740         
00741         //Set the modulation scheme use for base rate (header) symbols
00742         warpmac_setBaseRate(state.baseRate);
00743         
00744         //display 1 if RTS/CTS is forced on, 0 if not
00745         warpmac_leftHex((state.rtsThreshold) == 0 ? 1 : 0);
00746         
00747         csi.current = csi.antA;
00748         //initFeedback();
00749         
00750         //wtic;
00751         //setTXModMasks(csi.antA);
00752         //wtoc;
00753         //printTvars();
00754         
00755         xil_printf(" finished.");
00756         while(1)
00757         {
00758                 volatile unsigned char uartByte = 0;
00759                 
00760                 warpmac_pollEthernet();
00761 
00762 /*              //does not work with ethernet polling
00763                 if(uartByte = XUartLite_RecvByte(STDIN_BASEADDRESS));
00764                         if(uartByte==ASCII_j) { xil_printf("\b \nSetting antenna A modulation masks"); csi.current = csi.antA; }
00765                         if(uartByte==ASCII_h) { xil_printf("\b \nSetting antenna B modulation masks"); csi.current = csi.antB; }
00766                         if(uartByte==ASCII_g) { xil_printf("\b \nSetting half A half B modulation masks"); csi.current = csi.half; }
00767                         if(uartByte==ASCII_k) { xil_printf("\b \nSetting half B half A modulation masks"); csi.current = csi.otherhalf; }
00768                         if(uartByte==ASCII_l) { xil_printf("\b \nSetting alternating modulation masks"); csi.current = csi.alternating; }
00769                         
00770                         if(uartByte==ASCII_f) { printRXGains(); }
00771                         if(uartByte==ASCII_i) { xil_printf("\b \nTurning CSI %s", ((state.feedback_en ^= 1) ? "on" : "off")); }
00772                         if(uartByte==ASCII_u) { xil_printf("\b \nEnabling MIMO mode"); warpphy_enableMimoMode(); }
00773                         if(uartByte==ASCII_y) { xil_printf("\b \nEnabling SISO mode"); warpphy_enableSisoMode(); }
00774                         if(uartByte==ASCII_b) { warpphy_setSISOAntenna(state.currentAnt ^= 1); xil_printf("\b \nSwitching SISO to antenna %c", ((state.currentAnt == 1) ? 'B' : 'A')); }
00775                         if(uartByte==ASCII_v) { xil_printf("\b "); printState(); printTvars(); }
00776                         if(uartByte==ASCII_t) { xil_printf("\b "); printStatistics(); }
00777                         if(uartByte==ASCII_c) { xil_printf("\b \nClearing packet count"); clearPktCtr(); }
00778                         if(uartByte==ASCII_r) { dropPacket(); warpphy_clearRxInterrupts(); }
00779                         
00780                         if(uartByte==ASCII_3) warpphy_setGainPlus(1);
00781                         if(uartByte==ASCII_e) warpphy_setGainMinus(1);
00782 */
00783         }
00784 
00785         return 0;
00786 }
00787 
00788 
00789 
00790 
00791 
00792 
00793 
00794 
00795 
00796 
00797 /***************** Initialization functions ************************/
00801 void initFeedback() {
00802         //toggle second radio on to activate it, but switch back to first
00803         warpphy_setSISOAntenna(state.currentAnt ^= 1);
00804         warpphy_setSISOAntenna(state.currentAnt ^= 1);
00805         //state.feedback_en = 1;
00806         unlockRXantenna();
00807         
00808         if(0 && state.myID == 2) {
00809                 state.feedback_en = 1;
00810         }
00811         //set TX masks 
00812         setTXModMasks(csi.antA);
00813 }
00814 
00815 
00817 void initDelays() {
00818         // times for sending various packets
00819         delay.header = 64;              // header only packet requires 64us
00820         delay.transmit[CTS] = delay.header
00821                 + ( (state.csiLength > 0) ? ceil_div_uint(state.csiLength + 4, 6*(state.fullRate & 0xF))*8 : 0 );
00822         delay.transmit[ACK] = delay.header;
00823         
00824         // delay times (in microseconds)
00825         delay.slot = 9;
00826         delay.SIFS = 46;
00827         delay.DIFS = delay.SIFS + 2*delay.slot;
00828         delay.EIFS = delay.SIFS + delay.DIFS + delay.transmit[ACK];
00829         
00830         // timeouts for receiving response packets
00831         delay.timeout[CTS] = delay.slot + delay.transmit[CTS] + 46;             // 46us turnaround between RTS and CTS
00832         delay.timeout[ACK] = delay.slot + delay.transmit[ACK] + 24;             // 24us turnaround between data and ACK
00833         
00834         // set DIFS time in PHY
00835         setCSMAIdleTime(delay.DIFS);
00836         
00837         warpmac_setMaxCW(5);
00838 }
00839 
00840 
00842 void initAddresses() {
00843         unsigned char i;
00844         
00845         //Read Dip Switch value from FPGA board.
00846         //This value will be used as an index into the routing table for other nodes
00847         state.myID = warpmac_getMyId();
00848         
00849         //Create an arbitrary address for this node (16-24-63-53-e2-(c2+state.myID))
00850         state.addr.my[0] = 0x16; state.addr.my[1] = 0x24; state.addr.my[2] = 0x63;
00851         state.addr.my[3] = 0x53; state.addr.my[4] = 0xe2; state.addr.my[5] = 0xc2+state.myID;
00852         
00853         //Fill an arbitrary routing table so that nodes know each others' addresses
00854         for(i=0;i<16;i++) {
00855                 state.routeTable[i].addr[0] = state.addr.my[0];
00856                 state.routeTable[i].addr[1] = state.addr.my[1];
00857                 state.routeTable[i].addr[2] = state.addr.my[2];
00858                 state.routeTable[i].addr[3] = state.addr.my[3];
00859                 state.routeTable[i].addr[4] = state.addr.my[4];
00860                 state.routeTable[i].addr[5] = state.addr.my[5]+i-state.myID;
00861         }
00862         
00863         warpmac_setMacAddr((unsigned char *)(&state.addr.my));
00864 }
00865 
00866 
00868 void initHeaders() {
00869         UTime time;
00870         
00871         // set up RTS packet
00872         pkt.rts.header.fullRate = state.fullRate;
00873         pkt.rts.header.reserved4 = 0;
00874         pkt.rts.header.length = 0;
00875         pkt.rts.header.pktType = RTS;
00876         memcpy(pkt.rts.header.srcAddr,(unsigned char *)state.addr.my,6);
00877         pkt.rts.header.currReSend = 0;
00878         
00879         // set up CTS packet
00880         pkt.cts.header.fullRate = state.fullRate;
00881         pkt.cts.header.reserved4 = 0;
00882         pkt.cts.header.length = state.csiLength;        // 8 bytes for CSI on each of the 64 OFDM subchannels
00883         pkt.cts.header.pktType = CTS;
00884         memcpy(pkt.cts.header.srcAddr,(unsigned char *)state.addr.my,6);
00885         pkt.cts.header.currReSend = 0;
00886         
00887         // set up data packet
00888         pkt.dat.header.fullRate = state.fullRate;
00889         pkt.dat.header.pktType = DAT;
00890         memcpy(pkt.dat.header.srcAddr,(unsigned char *)state.addr.my,6);
00891         time.uint16 = delay.timeout[ACK];       // set NAV of other nodes
00892         pkt.dat.header.currReSend = 0;
00893         pkt.dat.header.reserved1 = time.uint8[0];
00894         pkt.dat.header.reserved2 = time.uint8[1];
00895         
00896         // set up ACK packet
00897         pkt.ack.header.fullRate = state.fullRate;
00898         pkt.ack.header.reserved4 = 0;
00899         pkt.ack.header.length = 0;
00900         pkt.ack.header.pktType = ACK;
00901         pkt.ack.header.currReSend = 0;
00902         pkt.ack.header.reserved1 = 0;   // set NAV to 0 for ACK (do not reserve channel)
00903         pkt.ack.header.reserved2 = 0;
00904         
00905         // set up broadcast data packet
00906         pkt.bcd.header.fullRate = state.fullRate;
00907         pkt.bcd.header.reserved4 = 0;
00908         pkt.bcd.header.pktType = BCD;
00909         memcpy(pkt.bcd.header.destAddr,(unsigned char *)state.addr.bc,6);
00910         memcpy(pkt.bcd.header.srcAddr,(unsigned char *)state.addr.my,6);
00911         pkt.bcd.header.currReSend = 0;
00912         pkt.bcd.header.reserved1 = 0;   // set NAV to 0 (don't expect any reply)
00913         pkt.bcd.header.reserved2 = 0;
00914 }
00915 
00916 
00917 
00918 
00919 /***************** Button Handlers *********************************/
00922 void rtsmac_left() {
00923         extern unsigned char txGain;
00924         warpphy_setGainMinus(ceil_div_uint(txGain,8));
00925         // static unsigned char i = 0;
00926         // i++;
00927         // i %= 6;
00928         // switch(i) {
00929         // case 0:
00930                 // state.feedback_en = 0;
00931                 // csi.current = csi.antA;
00932                 // xil_printf("\nfeedback disabled");
00933                 // break;
00934         // case 1:
00935                 // state.feedback_en = 1;
00936                 // csi.current = csi.antA;
00937                 // xil_printf("\nantA");
00938                 // break;
00939         // case 2:
00940                 // state.feedback_en = 1;
00941                 // csi.current = csi.antB;
00942                 // xil_printf("\nantB");
00943                 // break;
00944         // case 3:
00945                 // state.feedback_en = 1;
00946                 // csi.current = csi.half;
00947                 // xil_printf("\nhalf");
00948                 // break;
00949         // case 4:
00950                 // state.feedback_en = 1;
00951                 // csi.current = csi.otherhalf;
00952                 // xil_printf("\notherhalf");
00953                 // break;
00954         // case 5:
00955                 // state.feedback_en = 1;
00956                 // csi.current = csi.alternating;
00957                 // xil_printf("\nalternating");
00958                 // break;
00959         // }
00960 }
00961 
00962 
00965 void rtsmac_middle() {
00966         printState();
00967         printTvars();
00968         printStatistics();
00969 }
00970 
00971 
00974 void rtsmac_right() {
00975         extern unsigned char txGain;
00976         warpphy_setGainPlus(ceil_div_uint(txGain,8));
00977 }
00978 
00979 
00982 void rtsmac_up() {
00983         state.rtsThreshold = (state.rtsThreshold == 0) ? 65535 : 0;
00984         warpmac_leftHex((state.rtsThreshold) == 0 ? 1 : 0);
00985 }
00986 
00987 
00988 
00989 
00990 /***************** Status Display Functions ************************/
00992 void printState() {
00993         extern Maccontrol controlStruct;
00994         xil_printf("\nMAC=%d,NAV=%d,dat.isNew=%d,bcd.isNew=%d,currentAnt=%d,"
00995                 "timeLeft_0=%d,timeLeft_1=%d,timeLeft_2=%d,timeLeft_3=%d,tstatus=%x",
00996                 state.mac,
00997                 warp_timer_isActive(NAV),
00998                 pkt.dat.isNew,
00999                 pkt.bcd.isNew,
01000                 state.currentAnt,
01001                 warp_timer_timeLeft(0),
01002                 warp_timer_timeLeft(1),
01003                 warp_timer_timeLeft(2),
01004                 warp_timer_timeLeft(3),
01005                 warp_timer_getStatuses());
01006 }
01007 
01008 
01010 void clearPktCtr() {
01011         unsigned char i, j;
01012         for(i = 0; i < 4; i++){
01013                 for(j = 0; j < 7; j++){
01014                         pktCtr[i][j] = 0;
01015                 }
01016         }
01017 }
01018 
01019 
01025 void printStatistics() {
01026         unsigned char i = 0;
01027         char pktType[7][8] = {"TOTAL","RTS","CTS","DAT","ACK","BCD","ETH"};
01028         xil_printf("\n        |   TX    | RX_good |RX_unexp | RX_bad  |\n");
01029         pktCtr[TX][0] = 0;
01030         pktCtr[RXGOOD][0] = 0;
01031         pktCtr[RXUNEXP][0] = 0;
01032         pktCtr[RXBAD][0] = 0;
01033         for(i = 1; i < 5; i++) {
01034                 pktCtr[TX][0] += pktCtr[TX][i];
01035                 pktCtr[RXGOOD][0] += pktCtr[RXGOOD][i];
01036                 pktCtr[RXUNEXP][0] += pktCtr[RXUNEXP][i];
01037                 pktCtr[RXBAD][0] += pktCtr[RXBAD][i];
01038                 xil_printf("%8s|%9d|%9d|%9d|%9d|\n",
01039                         (unsigned char *)pktType[i],
01040                         pktCtr[TX][i],
01041                         pktCtr[RXGOOD][i],
01042                         pktCtr[RXUNEXP][i],
01043                         pktCtr[RXBAD][i]);
01044         }
01045         xil_printf("%8s|%9d|%9d|%9d|%9d|\n",
01046                 (unsigned char *)pktType[0],
01047                 pktCtr[TX][0],
01048                 pktCtr[RXGOOD][0],
01049                 pktCtr[RXUNEXP][0],
01050                 pktCtr[RXBAD][0]);
01051         xil_printf("-------------------------------------------------\n");
01052         xil_printf("        |   TX    |   RX    |\n");
01053         xil_printf("%8s|%9d|%9d|\n",
01054                 (unsigned char *)pktType[BCD],
01055                 pktCtr[TX][BCD],
01056                 pktCtr[RXGOOD][BCD]);
01057         xil_printf("-------------------------------------------------\n");
01058         xil_printf("        |   TX    |   RX    |  DROP   |\n");
01059         xil_printf("%8s|%9d|%9d|%9d|\n",
01060                 (unsigned char *)pktType[ETH],
01061                 pktCtr[TX][ETH],
01062                 pktCtr[RXGOOD][ETH],
01063                 pktCtr[DROP][ETH]);
01064 }

Updated on Sat Oct 11 00:50:52 2008 WARP