OFDMReferenceDesign/Applications/Characterization: csmaMac.c

File csmaMac.c, 37.2 KB (added by rpl1, 15 years ago)
Line 
1/*! \file csmaMac.c
2 \brief Carrier-Sensing Random Access MAC.
3 
4 @version 13
5 @author Chris Hunter and Patrick Murphy
6 
7
8 The csmaMac is a modified ALOHA MAC that
9 serves as an example for novel MAC
10 development. Nodes transmit whenever
11 they have information to transmit, and only
12 move on to the next packet once the original
13 transmit is acknowledged (ACKed). If no ACK
14 is received, a collision is inferred and the
15 packet is re-transmitted.
16 
17 
18 By default, the MAC also implements carrier-
19 sensing multiple-access with collision-
20 avoidance (CSMA-CA). This functionality is
21 built into hardware peripherals in the project
22 so very little software state is affected.
23 
24 In its current state, the project acts as
25 a true ethernet MAC-level wireless bridge.
26 Any ethernet activity that appears on one
27 WARP will be sent to another via the custom
28 wireless link.
29 
30 Also, the current versions supports hardware-triggered
31 ACK transmissions. This reduces the turn-around time
32 as well as reduces the jitter on the start time of the ACK
33 relative to the start time of the preceeding DATA.
34
35 */
36#include "warpmac.h"
37#include "warpphy.h"
38#include "csmaMac.h"
39#include "xparameters.h"
40#include "string.h"
41#include "errno.h"
42#include "stdlib.h"
43#include "stdio.h"
44#include "ascii_characters.h"
45#include "warp_userioboard_util.h"
46#include "radio_controller_ext.h"
47#include "warpnet_node2.h"
48#include "xtime_l.h"
49
50
51#define htons(A) ((((Xuint16)(A) & 0xff00) >> 8) | (((Xuint16)(A) & 0x00ff) << 8))
52
53Macframe templatePkt;
54
55unsigned int autoResp_matchCond;
56unsigned int autoResp_action;
57unsigned int autoResp_delay;
58unsigned char pktBuf_tx_ACK;
59unsigned char pktBuf_tx_DATA;
60unsigned char pktBuf_rx;
61
62//Global variables to for user I/O board outputs
63unsigned char userIOBoard_LEDs;
64unsigned char charsToPrint[16];
65unsigned int pktCount_good, pktCount_bad;
66
67//Arrays to track pkt sequence numbers for each partner node
68unsigned char rxSequences[16];
69unsigned char txSequences[16];
70
71unsigned char maximumReSend;
72
73///MAC address table with agreed upon mapping between dipswitches and physical addresses
74typedef struct {
75    unsigned char addr[6];
76} nodeAddr;
77
78
79///Byte array containing physical MAC address of this node
80unsigned char myAddr[6];
81///Index to the routing table that identifies this node
82unsigned short int myID;
83
84///Full rate modulation selection; QPSK by default
85unsigned int pktFullRate;
86
87//Payload code rate selection; must be CODE_RATE_NONE for uncoded PHY
88unsigned int pktCodeRate;
89
90///Buffer for holding a packet-to-xmit across multiple retransmissions
91Macframe txBuffer;
92///Buffer to hold received packet
93Macframe rxBuffer;
94
95///Current antenna selection
96unsigned char currentAnt;
97///Current 802.11 channel
98unsigned char chan;
99
100//Define handy macros for CSMA MAC packet types
101///Data packet with payload meant for Ethernet transmission
102#define DATAPACKET 1
103///Acknowledgement packet meant for halting retransmissions
104#define ACKPACKET 0
105
106// Aid for Debugging Purposes, if 1 print from Teraterm
107#define PrintDebug 0
108
109
110
111//warpnodeChanEst chanEst_AA[WARPNET_NUMNODES-1];
112
113
114//Arrays to track pkt sequence numbers for each partner node
115unsigned char rxSequences[16];
116unsigned char txSequences[16];
117
118//Variables used by other commands
119unsigned char sendStats;
120char sendcallbackpacket;
121
122
123///Global Structs
124warpnetEthernetPktHeader txEthPktHeader;
125warpnodeID myNodeID;
126warpnodeCommand myNodeCmd;
127
128///Global Stat Struct
129warpnodeStats myStats[WARPNET_NUMNODES];
130
131///Place holder for TRANSMIT or RECEIVE state
132unsigned char Mode;
133
134///Measures time for beginning and end of transmission
135XTime start_timer, end_timer;
136
137unsigned int pktCount_good, pktCount_bad;
138
139///Parameters used for warpmac_startPacketGeneration
140unsigned int Time;
141unsigned short packetlength;
142
143///@brief Send ackCommand Packet over the Ethernet
144///
145///This function is when certain node commands request acks. This packages
146///the ack package as a specific type of command struct, with the current rxSeqNum
147///It then sends this ackCommand Packet over the Ethernet
148///@param rxSeqNum, sequence number of packet ethernet header
149void sendAck(char rxSeqNum)
150{
151    //xil_printf("sent ack packet w sequence number: %d\r\n",rxSeqNum);
152   
153    //Initialize Payload Address
154    int pktBuf_payloadAddr;
155   
156    //Fill in a node command reply pkt
157    myNodeCmd.structType = STRUCTID_NODECOMMAND;
158    myNodeCmd.nodeID = myID;
159    myNodeCmd.cmdID = NODECMD_NODEACK;
160    myNodeCmd.cmdParam = rxSeqNum;
161                           
162    //Fill in the ethernet packet's header info
163    txEthPktHeader.ethType = WARPNET_ETHTYPE_NODE2SVR;
164    memset(&(txEthPktHeader.srcAddr), (unsigned char)myID, 6); //Generic source address; ignored throughout
165    memset(&(txEthPktHeader.dstAddr), (unsigned char)0xFF, 6); //Broadcast destination address
166                       
167    //Fill in the ethernet packet's header info
168    txEthPktHeader.pktLength = sizeof(warpnetEthernetPktHeader) + sizeof(warpnodeCommand);
169    txEthPktHeader.numStructs = 1;
170    txEthPktHeader.seqNum = rxSeqNum;
171   
172    //Copy over data for transmission over wire
173    pktBuf_payloadAddr = warpphy_getBuffAddr(WARPNET_PKTBUFFINDEX);
174    memcpy((void *)pktBuf_payloadAddr, &(txEthPktHeader), sizeof(warpnetEthernetPktHeader));
175    memcpy((void *)pktBuf_payloadAddr+sizeof(warpnetEthernetPktHeader), &(myNodeCmd), sizeof(warpnodeCommand));
176   
177    //Send the packet over the wire
178    warpmac_sendRawEthernetPacket((void *)pktBuf_payloadAddr, txEthPktHeader.pktLength);
179    return;
180}
181
182
183///@brief Send the current Stat Packet over the Ethernet
184///
185///This function is when certain node commands request stat packets to be send over the ethernet.
186///The stat package ethernet header increases the seqNum sent over wire
187///@param rxSeqNum, sequence number of packet ethernet header
188void sendStatsPacket(char rxSeqNum)
189{
190    //xil_printf("\r\nSent Stats PACKET \r\n");
191    //Send a new stats packet over the wire
192
193    //Initialize Payload Address
194    unsigned int pktBuf_payloadAddr;
195   
196    //De-assert the flag (it will be re-asserted in the main while loop later)
197// sendStats = 0;
198   
199    //Fill in the ethernet packet's header info
200    txEthPktHeader.pktLength = sizeof(warpnetEthernetPktHeader) + (WARPNET_NUMNODES*sizeof(warpnodeStats));
201    txEthPktHeader.numStructs = WARPNET_NUMNODES;
202    txEthPktHeader.seqNum = rxSeqNum;
203   
204//  xil_printf("\r\nSent pktLength: %d \r\n", txEthPktHeader.pktLength);
205//  xil_printf("\r\nSent numStructs: %d \r\n", txEthPktHeader.numStructs);
206//  xil_printf("\r\nSent seqNum: %d \r\n", txEthPktHeader.seqNum);
207
208   
209    //Copy the ethernet header and stats payload to a memroy buffer
210    pktBuf_payloadAddr = warpphy_getBuffAddr(WARPNET_PKTBUFFINDEX);
211    memcpy((void *)pktBuf_payloadAddr, &(txEthPktHeader), sizeof(warpnetEthernetPktHeader));
212   
213    //Copy each stats struct (one per partner)
214    memcpy((void *)pktBuf_payloadAddr+sizeof(warpnetEthernetPktHeader), &myStats, WARPNET_NUMNODES*sizeof(warpnodeStats));
215   
216//  for(int i=0; i<(sizeof(warpnetEthernetPktHeader)+sizeof(warpnodeStats)); i++)
217//  {
218//      xil_printf("[%d] 0x%x\r\n", i, *((char *)pktBuf_payloadAddr+i));
219//  }
220    //xil_printf("Size of ethernetpktheader %d\r\n",  sizeof(warpnetEthernetPktHeader));
221   
222    //Send the packet over the wire
223    warpmac_sendRawEthernetPacket((void *)pktBuf_payloadAddr, txEthPktHeader.pktLength);
224   
225    sendStats = 0;
226    return;
227}
228
229///@brief Update node parameters with warpnodeControl Struct values
230///
231///This function process the warpnodeControl struct by taking the specific
232///paramters and modifying the current board configuration
233///@param packet Pointer to warpnodeControl
234void processControlStruct(warpnodeControl* ctrlStruct)
235{
236    //xil_printf("Processing Control Struct\r\n");
237    //Interpret the control struct's modulation rate value
238    switch(ctrlStruct->modOrder)
239    {
240            /*** Non-autorate version ***/
241        case 0x1: //BPSK
242            pktFullRate = HDR_FULLRATE_BPSK;
243            warp_userio_lcd_printline("Mod order: BPSK ", 16, 8, 1);
244            break;
245        case 0x2: //QPSK
246            pktFullRate = HDR_FULLRATE_QPSK;
247            warp_userio_lcd_printline("Mod order: QPSK ", 16, 8, 1);
248            break;
249        case 0x4: //16-QAM
250            pktFullRate = HDR_FULLRATE_QAM_16;
251            warp_userio_lcd_printline("Mod order: 16QAM", 16, 8, 1);
252            break;
253        case 0x6: //64-QAM
254            pktFullRate = HDR_FULLRATE_QAM_64;
255            warp_userio_lcd_printline("Mod order: 64QAM", 16, 8, 1);
256            break;
257            /*******************/
258        default:
259            //xil_printf("Invalid Mod order - Recieved: %x\r\n", ctrlStruct->modOrder);
260            //Invalid value, so ignore it and leave txFulrate as-is
261            break;
262    }
263   
264    //Set the transmit power for both radios
265    warpphy_setTxPower(ctrlStruct->txPower);
266    //xil_printf("Power changed to %d\r\n", ctrlStruct->txPower);
267   
268    //Use the circle of LEDs as a Tx power indicator
269    warp_userioboard_set_leds((1<<((8+(ctrlStruct->txPower))/8))-1);
270    unsigned char charsToPrint[16];
271    snprintf(charsToPrint, 16, "Tx Pwr: 0x%2x    ", (ctrlStruct->txPower));
272   
273    //xil_printf("Tx Power changed to: %x\r\n", ctrlStruct->txPower);
274   
275    warp_userio_lcd_printline(charsToPrint, 16, 6, 1);
276   
277    //Set the center frequency of both radios
278    // Values 1-14 are 2.4GHz channels
279    // Values 15-37 are 5GHz channels
280    // Any other value is invalid and ignored
281    if( ((ctrlStruct->channel) > 0) && ((ctrlStruct->channel) <= 37) )
282    {
283        if((ctrlStruct->channel) <= 14)
284            warpphy_setChannel(GHZ_2, ctrlStruct->channel);
285        else
286            warpphy_setChannel(GHZ_5, (ctrlStruct->channel) - 14);
287    }
288   
289    snprintf(charsToPrint, 16, "Channel: %2d     ", (ctrlStruct->channel));
290    warp_userio_lcd_printline(charsToPrint, 16, 7, 1);
291   
292    return;
293}
294
295///@brief Callback for the depression of the left push button
296///
297///This function is empty by default
298void left(){
299}
300
301///@brief Callback for the depression of the right push button
302///
303///This button switched between different fullrate modulation orders
304void right(){
305    switch(pktFullRate){
306        case HDR_FULLRATE_BPSK:
307            pktFullRate = HDR_FULLRATE_QPSK;
308            xil_printf("QPSK\r\n");
309            break;
310        case HDR_FULLRATE_QPSK:
311            pktFullRate = HDR_FULLRATE_QAM_16;
312            xil_printf("16-QAM\r\n");
313            break;
314        case HDR_FULLRATE_QAM_16:
315            pktFullRate = HDR_FULLRATE_QAM_64;
316            xil_printf("64-QAM\r\n");
317            break;
318        case HDR_FULLRATE_QAM_64:
319            pktFullRate = HDR_FULLRATE_BPSK;
320            xil_printf("BPSK\r\n");
321            break;
322    }
323}
324
325///@brief Callback for the depression of the up push button
326///
327///This button increments the 2.4GHz channel being used; only valid channels (in [1,14]) will be used
328void up(){
329    unsigned int newFreq;
330   
331    chan = (chan > 13) ? 14 : chan+1;
332    newFreq = warpphy_setChannel(GHZ_2, chan);
333    warpmac_leftHex(chan);
334   
335    xil_printf("New Frequency %d\r\n", newFreq);
336}
337
338///@brief Callback for the depression of the middle push button
339///
340///This button decrements the 2.4GHz channel being used; only valid channels (in [1,14]) will be used
341void middle(){
342    unsigned int newFreq;
343   
344    chan = (chan < 2) ? 1 : chan-1;
345    newFreq = warpphy_setChannel(GHZ_2, chan);
346    warpmac_leftHex(chan);
347   
348    xil_printf("New Frequency %d\r\n", newFreq);
349}
350
351
352///@brief Updates the LCD
353///
354///Updates the LCD. This is only for the User I/O daughtercard. If you do not have this card,
355///this function will do nothing. This operation takes some time, so it can only be called in a few places so as to
356///not adversely affect the performance of the MAC.
357void updateLCD()
358{
359
360    warp_userioboard_set_leds(userIOBoard_LEDs);
361   
362    snprintf(charsToPrint, 16, "Good: %09d ", pktCount_good);
363    warp_userio_lcd_printline(charsToPrint, 16, 4, 1);
364   
365    snprintf(charsToPrint, 16, "Bad:  %09d ", (pktCount_bad)>>1);//bad pkts get counted twice
366    warp_userio_lcd_printline(charsToPrint, 16, 5, 1);
367   
368    return;
369}
370
371///@brief Callback for the reception of UART bytes
372///@param uartByte ASCII byte received from UART
373///
374///Provides the user with the bytes that was received over the serial port. This is useful for configuring
375///PHY and MAC parameters in real time on a board.
376void uartRecv_callback(unsigned char uartByte)
377{
378    if(uartByte != 0x0)
379    {
380        xil_printf("(%c)\t", uartByte);
381       
382        switch(uartByte)
383        {
384            case ASCII_1:
385                pktFullRate = HDR_FULLRATE_BPSK;
386                xil_printf("Tx Full Rate = BPSK\r\n");
387                break;
388               
389            case ASCII_2:
390                pktFullRate = HDR_FULLRATE_QPSK;
391                xil_printf("Tx Full Rate = QPSK\r\n");
392                break;
393               
394            case ASCII_4:
395                pktFullRate = HDR_FULLRATE_QAM_16;
396                xil_printf("Tx Full Rate = 16-QAM\r\n");
397                break;
398               
399            case ASCII_6:
400                pktFullRate = HDR_FULLRATE_QAM_64;
401                xil_printf("Tx Full Rate = 64-QAM\r\n");
402                break;
403            case ASCII_D:
404                warpphy_setPktDetMinDurPlus(1);
405                break;
406            case ASCII_d:
407                warpphy_setPktDetMinDurMinus(1);
408                break;
409            case ASCII_P:
410                warpphy_setPktDetPlus(100);
411                break;
412            case ASCII_p:
413                warpphy_setPktDetMinus(100);
414                break;
415            case ASCII_F:
416                if(chan<14) chan++;
417                warpphy_setChannel(GHZ_2, chan);
418                xil_printf("Current channel: %d\r\n",chan);
419                break;
420            case ASCII_f:
421                if(chan>1) chan--;
422                warpphy_setChannel(GHZ_2, chan);
423                xil_printf("Current channel: %d\r\n",chan);
424                break;
425            case ASCII_C:
426                warpphy_setCSMAPlus(100);
427                break;
428            case ASCII_c:
429                warpphy_setCSMAMinus(100);
430                break;
431            case ASCII_A:
432                warpphy_setAntennaMode(TX_ANTMODE_SISO_ANTB, RX_ANTMODE_SISO_ANTB);
433                xil_printf("Radio 3 Selected\r\n");
434                break;
435            case ASCII_a:
436                warpphy_setAntennaMode(TX_ANTMODE_SISO_ANTA, RX_ANTMODE_SISO_ANTA);
437                xil_printf("Radio 2 Selected\r\n");
438                break;
439            case ASCII_G:
440                warpphy_setTargetPlus();
441                break;
442            case ASCII_g:
443                warpphy_setTargetMinus();
444                break;
445
446            case ASCII_W:
447                autoResp_delay++;
448                autoResp_action = PHY_AUTORESPONSE_TXACTION_CONFIG(pktBuf_tx_ACK, 1, (PHY_AUTORESPONSE_REQ_MATCH0 | PHY_AUTORESPONSE_REQ_MATCH1), autoResp_delay, 0, 0, 1, 0, 1);
449                mimo_ofdmTxRx_setAction0(autoResp_action);
450                xil_printf("ACK delay: %d\r\n", autoResp_delay);
451                break;
452               
453            case ASCII_w:
454                autoResp_delay--;
455                autoResp_action = PHY_AUTORESPONSE_TXACTION_CONFIG(pktBuf_tx_ACK, 1, (PHY_AUTORESPONSE_REQ_MATCH0 | PHY_AUTORESPONSE_REQ_MATCH1), autoResp_delay, 0, 0, 1, 0, 1);
456                mimo_ofdmTxRx_setAction0(autoResp_action);
457                xil_printf("ACK delay: %d\r\n", autoResp_delay);
458                break;
459               
460            default:
461                xil_printf("Undefined command\r\n");
462                break;
463        }
464    }
465   
466    return;
467}
468///@brief Callback for the expiration of timers
469///
470///This function is responsible for handling #TIMEOUT and #BACKOFF.
471///The job responsibilities of this function are to:
472///-increase the contention window upon the expiration of a #TIMEOUT
473///-initiate a #BACKOFF timer upon the expiration of a #TIMEOUT
474///-retransmit a packet upon the expiration of a #BACKOFF
475///@param timerType #TIMEOUT or #BACKOFF
476void timer_callback(unsigned char timerType){
477    int status;
478    switch(timerType){
479        case TIMEOUT_TIMER:
480            //warpmac_incrementLEDHigh();
481            warpmac_setTimer(BACKOFF_TIMER);
482            break;
483        case BACKOFF_TIMER:
484            //xil_printf("Remaining Retransmissions = %d\r\n",txBuffer.header.remainingReSend&0xF);
485            if(txBuffer.header.remainingReSend&0xF){
486                //Copy the header over to packet buffer 1
487                warpmac_prepPhyForXmit(&txBuffer, pktBuf_tx_DATA);
488                //warpmac_setDebugGPIO(0xF);
489                //Send packet buffer 1
490                warpmac_startPhyXmit(pktBuf_tx_DATA);
491                //Wait for it to finish and enable the receiver
492                warpmac_finishPhyXmit();
493                //warpmac_setDebugGPIO(0);
494                //Start a timeout timer
495                //xil_printf("----SET TIMEOUT\r\n");
496                warpmac_setTimer(TIMEOUT_TIMER);
497                warpmac_decrementRemainingReSend(&txBuffer);
498                //Copy the header over to packet buffer 1
499                //warpmac_prepPhyForXmit(&txBuffer,1);
500            }
501            else{
502            //warpmac_setDebugGPIO(0x0);
503            warpmac_enableDataFromNetwork();
504            }
505            break;
506    }
507}
508
509///@brief Callback for the reception of Ethernet packets
510///
511///This function is called by the ethernet MAC drivers
512///and process the packet to perform specific operations
513///depending on the packet struct
514///@param length Length, in bytes, of received Ethernet frame
515void mgmtFromNetworkLayer_callback(Xuint32 length, char* payload){
516   
517    #if PrintDebug >0
518    xil_printf("\r\nReceived A mgmt PACKET with following paramters: \r\n");
519    #endif
520   
521    //warpmac_disableDataFromNetwork();
522    unsigned char rxSeqNum=0;
523    unsigned char destNode;
524
525    warpmac_resetCurrentCW();
526    //warpmac_disableDataFromNetwork();
527
528    //Flag that will allow some WARPnet packets to be forwarded wirelessly in future revisions
529
530    //Bookkeeping variables
531    int pktBuf_payloadAddr;
532    unsigned char numRxStructs, thisStructType;
533    unsigned int rxPktOffset;
534    int i;
535
536    //Re-interpret the Rx packet as a WARPnet Ethernet frame
537    warpnetEthernetPktHeader* receivedPkt;
538   
539    //Pointers to each kind of possible received struct; used to re-interpret the packet below
540    warpnodeID* idStruct;
541    warpnodeControl* controlStruct;
542    warpnodeCommand* cmdStruct;
543    warpnodeTraffic* trafficStruct;
544   
545    receivedPkt = (warpnetEthernetPktHeader*) payload;
546
547    //xil_printf("Ethernet type is: %x but should be %x\r\n", receivedPkt->ethType,WARPNET_ETHTYPE_SVR2NODE);
548   
549    //Ack packet from the other nodes
550    if ((receivedPkt->ethType) == WARPNET_ETHTYPE_NODE2SVR)
551    {
552        //xil_printf("Ack packet size: %d\r\n", sizeof(payload));
553        return;
554    }
555   
556
557    //If this is a WARPnet Ethernet packet, process it immediately
558    if((receivedPkt->ethType) == WARPNET_ETHTYPE_SVR2NODE)
559    {
560        rxPktOffset = sizeof(warpnetEthernetPktHeader);
561        numRxStructs = receivedPkt->numStructs;
562        rxSeqNum = receivedPkt->seqNum;
563    //  xil_printf("Number of structs %d\r\n", numRxStructs);
564    // xil_printf("Number of rxSeqNum %d and my ID is %d\r\n", rxSeqNum, myID);
565   
566    /*
567    for(i=0; i<30; i++)
568    {
569        xil_printf("[%d] %x\r\n", i, payload[i]);
570    }*/
571   
572        for(i=0; i<numRxStructs; i++)
573        {
574            thisStructType = *(unsigned char*)(payload+rxPktOffset);
575            switch(thisStructType)
576            {
577                case STRUCTID_NODEID:
578                //  xil_printf("Got a node ID request\r\n");
579                   
580                    //Initialize my nodeID struct (to respond to server inquiries)
581                    myNodeID.structType = STRUCTID_NODEID;
582                    myNodeID.nodeID = myID;
583                   
584                    //Fill in the ethernet packet's header info
585                    txEthPktHeader.ethType = WARPNET_ETHTYPE_NODE2SVR;
586                    memset(&(txEthPktHeader.srcAddr), (unsigned char)myID, 6); //Generic source address; ignored throughout
587                    memset(&(txEthPktHeader.dstAddr), (unsigned char)0xFF, 6); //Broadcast destination address
588                   
589                    txEthPktHeader.pktLength = sizeof(warpnetEthernetPktHeader) + sizeof(warpnodeID);
590                    txEthPktHeader.numStructs = 1;
591                   
592                    pktBuf_payloadAddr = warpphy_getBuffAddr(WARPNET_PKTBUFFINDEX);
593                    memcpy((void *)pktBuf_payloadAddr, &(txEthPktHeader), sizeof(warpnetEthernetPktHeader));
594                    memcpy((void *)pktBuf_payloadAddr+sizeof(warpnetEthernetPktHeader), &(myNodeID), sizeof(warpnodeID));
595                   
596                    warpmac_sendRawEthernetPacket((void *)pktBuf_payloadAddr, txEthPktHeader.pktLength);
597                   
598                    rxPktOffset += sizeof(warpnodeID);
599                    break;
600                   
601                case STRUCTID_NODECONTROL:
602                    controlStruct = (warpnodeControl*)(payload+rxPktOffset);
603                   
604                    #if PrintDebug >0
605                    xil_printf("Got a node control pkt and the ID param is : %d \r\n", controlStruct->nodeID); 
606                    xil_printf("My nodeID: %d\r\n", controlStruct->nodeID);
607                    #endif
608                       
609                    if( (controlStruct->nodeID) == myID)
610                    {
611//                      xil_printf("Got a node control: structType: %d\r\n", controlStruct->structType);
612//                      xil_printf("Got a node control: nodeID: %d\r\n", controlStruct->nodeID);
613//                      xil_printf("Got a node control: modOrder: %d\r\n", controlStruct->modOrder);
614//                      xil_printf("Got a node control: txPower: %d\r\n", controlStruct->txPower);
615//                      xil_printf("Got a node control: coding: %d\r\n", controlStruct->coding);
616//                      xil_printf("Got a node control: channel: %d\r\n", controlStruct->channel);
617                       
618//                      for(i=0; i<(sizeof(warpnodeControl)); i++)
619//                      {
620//                      xil_printf("[%d] 0x%x\r\n", i, *((char *)controlStruct+i));
621//                      }   
622//     
623                        processControlStruct((warpnodeControl*)(payload+rxPktOffset));
624                       
625                        //xil_printf("Number of Control rxSeqNum %d and received %d\r\n", rxSeqNum, receivedPkt->seqNum);
626                       
627                        //Send Ack Packet
628                        if(rxSeqNum > 0) sendAck(rxSeqNum);
629                    }
630                   
631                    rxPktOffset += sizeof(warpnodeControl);
632                    break;
633                   
634                case STRUCTID_NODECOMMAND:
635                    cmdStruct = (warpnodeCommand*)(payload+rxPktOffset);
636                //xil_printf("Got a node command pkt and ID param is %d\r\n", cmdStruct->nodeID);
637       
638                    switch(cmdStruct->cmdID)
639                    {
640                    case NODECMD_RESETSTATS:
641                   
642                        if( (cmdStruct->nodeID) == myID)
643                        {   
644                            //xil_printf("NODECMC_RESETSTATS \r\n");
645                            //Reset the good/bad pkt counts and Rx/Tx byte counts
646                            for(i=0; i<WARPNET_NUMNODES; i++)
647                            {
648                                myStats[i].goodPackets = 0;
649                                myStats[i].partnerBadPackets = 0;
650                                myStats[i].otherBadPackets = 0;
651                                myStats[i].txBytes = 0;
652                                myStats[i].rxBytes = 0;
653                                myStats[i].time = 0;
654                            }
655                           
656                            //Send Ack Packet
657                            if(rxSeqNum > 0) sendAck(rxSeqNum);
658
659                    }
660                        break;
661                       
662                    case NODECMD_REBOOT:
663                        //Restart the software from scratch
664                        main();
665                        break;
666                       
667                    case NODECMD_SENDPACKET:
668                        sendcallbackpacket=1;
669                        break;
670                       
671                    case NODECMD_SENDSTATS:
672                        sendStats = 1;
673                        break;
674                       
675                    case NODECMD_START:
676                   
677                        XTime_GetTime(&start_timer);
678                        //xil_printf("NODECMC_Start mode is: %x \r\n", Mode);
679                       
680                        //warpmac_enableDummyPacketMode();
681                        if (Mode==TRANSMIT){
682                       
683                        warpmac_startPacketGeneration(packetlength,Time); //second argument is interval in usec
684   
685                        }
686                       
687                        break;
688                       
689                    case NODECMD_STOP:
690               
691                        //xil_printf("NODECMC_STOP \r\n");
692                        warpmac_stopPacketGeneration();
693                        //warpmac_disableDummyPacketMode();
694                   
695                        XTime_GetTime(&end_timer);
696                        long long xtime=0;
697                        xtime=end_timer-start_timer;
698                           
699                        for(i=0; i<WARPNET_NUMNODES; i++)
700                        {
701                            myStats[i].time = xtime;
702                               
703                        }
704                       
705                        if((cmdStruct->nodeID) == myID)
706                        {   
707                            //Send Ack Packet
708                            if(rxSeqNum > 0) sendAck(rxSeqNum);
709                        }
710                   
711                        break;
712                       
713                    case NODECMC_REQUESTSTATS:
714                   
715                        if( (cmdStruct->nodeID) == myID)
716                        {   
717                            //xil_printf("NODECMC_REQUESTSTATS \r\n"); 
718                            sendStatsPacket(rxSeqNum);
719                           
720                            //Send Ack Packet
721                            if(rxSeqNum > 0) sendAck(rxSeqNum);
722                        }
723                        break;
724                       
725                    default:
726       
727                        for(i=0; i<sizeof(warpnodeCommand); i++)
728                        {
729                            xil_printf("%x ", *(unsigned char*)(payload+rxPktOffset+i));
730                        }
731                   
732                        break;
733                    }
734           
735                    rxPktOffset += sizeof(warpnodeCommand);
736                    break;
737                   
738                   
739                case STRUCTID_NODETRAFFIC: //This is for a traffic struct
740                    trafficStruct = (warpnodeTraffic*)(payload+rxPktOffset);
741                   
742                    //xil_printf("Got a node traffic pkt with ID param as : %d \r\n",trafficStruct->nodeID);
743                    if((trafficStruct->nodeID) == myID)
744                    {
745                        //xil_printf("MY ID: %x \r\n", myID);
746
747                        //Send Ack Packet
748                        if(rxSeqNum > 0) sendAck(rxSeqNum);
749                       
750                        Time=trafficStruct->txInterval;
751                        Mode=trafficStruct->trafficMode;
752                        packetlength=trafficStruct->txPacketLen;
753               
754                    }
755                   
756                    rxPktOffset += sizeof(warpnodeTraffic);
757                   
758                    //xil_printf("The mode is : %x\r\n", Mode);
759                   
760                break;
761                           
762                default:
763                    //Didn't understand the WARPnet packet; discard it
764                    //xil_printf("Got unknown WARPnet pkt - type: %d\r\n", thisStructType);
765                    break;
766            }
767       
768        }
769    }
770   
771
772     //xil_printf("Unknown packet size: %d\r\n", sizeof(payload));
773    // warpmac_enableDataFromNetwork();
774    return;
775}
776
777///@brief Callback for the reception of data packets
778///
779///This function is called by the MAC drivers
780///when a data packet is received and an ack packet is available to send.
781///This function fills the Macframe transmit buffer with the packet and sends
782///it over the OFDM link
783///@param length Length, in bytes, of received Ethernet frame
784void dataFromNetworkLayer_callback(Xuint32 length, char* payload){
785   
786    unsigned char rxSeqNum;
787    unsigned char destNode;
788   
789    warpmac_resetCurrentCW();
790//  warpmac_setDebugGPIO(0xF);
791    warpmac_disableDataFromNetwork();
792    txBuffer.header.length = length;
793    txBuffer.header.pktType = DATAPACKET;
794   
795    //Set the modulation scheme for the packet's full-rate symbols
796    txBuffer.header.fullRate = pktFullRate;
797   
798    //Set the code rate for the packet's payload
799    txBuffer.header.codeRate = pktCodeRate;
800   
801    //For now, assume our destination is our opposite ID (all traffic is 0 <-> 1)
802    destNode = (myID+1)%2;
803   
804    //Use the next sequence number for this node (top four bits) and resend count of 0 (bottom four bits)
805    txSequences[destNode] = txSequences[destNode]+0x10;
806    txBuffer.header.remainingReSend = (((txSequences[destNode])&0xF0)|((maximumReSend+1)&0x0F));
807   
808    //Copy in the packet's destination MAC address
809    //Hard-coded as this node's partner node
810    //memcpy(txBuffer.header.destAddr,nodeTable[destNode].addr,6);
811    txBuffer.header.destAddr = ((destNode + 2)<<8 | destNode);
812   
813    //If the medium is idle
814    if(warpmac_carrierSense()){
815       
816        //Copy the header over to packet buffer 1
817        warpmac_prepPhyForXmit(&txBuffer, pktBuf_tx_DATA);
818        //Send packet buffer 1
819       
820        warpmac_startPhyXmit(pktBuf_tx_DATA);
821        //Wait for it to finish and enable the receiver
822        warpmac_finishPhyXmit();
823        //warpmac_setDebugGPIO(0x0);
824        //Start a timeout timer
825        warpmac_setTimer(TIMEOUT_TIMER);
826        warpmac_decrementRemainingReSend(&txBuffer);
827        //Copy the header over to packet buffer 1
828        //warpmac_prepPhyForXmit(&txBuffer,1);
829    }
830    else{
831        //Start a backoff timer
832        warpmac_setTimer(BACKOFF_TIMER);
833    }
834   
835    return;
836}
837
838///@brief Callback for the reception of bad wireless headers
839///
840///@param packet Pointer to received Macframe
841void phyRx_badHeader_callback() {
842    //warpmac_incrementLEDLow();
843   
844    userIOBoard_LEDs = userIOBoard_LEDs==0x80 ? 0x01 : (userIOBoard_LEDs << 1);
845
846    pktCount_bad++;
847   
848    int i;
849    //Update every stats struct, since we don't know where this bad pkt came from
850    for(i=0; i<WARPNET_NUMNODES; i++)
851    {
852        myStats[i].otherBadPackets++;
853    }
854   
855    return;
856}
857
858///@brief Callback for the reception of good wireless headers
859///
860///This function then polls the PHY to determine if the entire packet passes checksum
861///thereby triggering the transmission of the ACK and the transmission of the received
862///data over Ethernet.
863///@param packet Pointer to received Macframe
864void phyRx_goodHeader_callback(Macframe* packet){
865   
866    unsigned char state=INCOMPLETE;
867    unsigned char srcNode;
868    unsigned char shouldSend = 0;
869    int i;
870   
871//  xil_printf("Destination: %d\r\n",packet->header.destAddr);
872//  xil_printf("Type: %d\r\n",packet->header.pktType);
873   
874   
875    //Exploit the fact that our MAC addresses use our ID as the last octet
876    // This should be replaced by something more sophisticated at some point
877    srcNode = packet->header.srcAddr;
878   
879    //Rotate the ring of LEDs clockwise
880    userIOBoard_LEDs = userIOBoard_LEDs==0x1 ? 0x80 : (userIOBoard_LEDs >> 1);
881   
882    //Print the header (debug only- completely ruins actual performance)
883#if 0
884    for(i=0; i<24; i++)
885    {
886        xil_printf("%d.",*((unsigned char*)&(packet->header) + i));
887    }
888    xil_printf("\r\n");
889#endif
890   
891    //If the packet is addressed to this node
892    if(packet->header.destAddr == ( ((myID+2)<<8) | myID) ){
893       
894       
895        switch(packet->header.pktType){
896                //If received packet is data
897            case DATAPACKET:
898                //Acknowledge the reception of the data
899               
900
901                //At this point, we have pre-loaded the PHY transmitter with the ACK in hoping that
902                //the packet passes checksum. Now we wait for the state of the received to packet
903                //to move from INCOMPLETE to either GOODPACKET or BADPACKET
904
905                //Copy the header over to packet buffer 2
906                //warpmac_prepPhyForXmit(&ackPacket,2);
907
908                if((packet->header.length)>1400){
909                    updateLCD();
910                }
911               
912                state = warpmac_finishPhyRecv();
913               
914                //warpmac_setDebugGPIO(0x0);
915                if(state&GOOD){
916                   
917                    //Send packet buffer 2 containing the ACK
918                   
919                    //warpmac_startPhyXmit(2);
920                    warpmac_incrementLEDHigh();
921                   
922                    //Update the right-hex display with the current resend count for the received pkt
923                    warpmac_leftHex(0xF & (packet->header.remainingReSend));
924                   
925                    //Check if the last received seq number for this partner node matches this received pkt
926                    // If not, record the new number and allow the pkt to be forwarded over the wire
927                    if(srcNode<16 && rxSequences[srcNode] != ((packet->header.remainingReSend)&0xF0)){
928                        rxSequences[srcNode] = (packet->header.remainingReSend)&0xF0;
929                        shouldSend = 1; 
930                    } 
931                   
932                    //Starts the DMA transfer of the payload into the EMAC
933                    if(shouldSend) warpmac_prepDataToNetwork(packet);
934                   
935                    //Blocks until the PHY is finished sending and enables the receiver
936                    warpmac_finishPhyXmit();
937                   
938                    //Waits until the DMA transfer is complete, then starts the EMAC
939                    if(shouldSend) warpmac_startDataToNetwork(packet);
940                   
941                    pktCount_good++;
942               
943               
944                myStats[srcNode].goodPackets++;
945                myStats[srcNode].rxBytes += (packet->header.length + NUM_HEADER_BYTES + NUM_PAYLOAD_CRC_BYTES + NUM_PAYLOAD_TAIL_BYTES);
946                myStats[srcNode].txBytes += NUM_HEADER_BYTES; 
947                }
948               
949                if(state&BAD){
950                    //warpmac_incrementLEDLow();
951                    pktCount_bad++;
952                   
953                    //Rotate the ring of LEDs counter-clockwise
954                    userIOBoard_LEDs = userIOBoard_LEDs==0x80 ? 0x01 : (userIOBoard_LEDs << 1);
955
956
957                myStats[srcNode].partnerBadPackets++;
958                }
959               
960                break;
961               
962            case ACKPACKET:
963                //Clear the TIMEOUT and enable Ethernet
964                //if(warpmac_inTimeout()){
965                    warpmac_incrementLEDHigh();
966
967                    warpmac_clearTimer(TIMEOUT_TIMER);
968                    txBuffer.header.remainingReSend = 0;
969                    warpmac_resetCurrentCW();
970                    warpmac_setTimer(BACKOFF_TIMER);
971            //  }
972               
973                pktCount_good++;
974               
975                break;
976        }
977    }
978}
979
980///@brief Main function
981///
982///This function configures MAC parameters, enables the underlying frameworks, and then loops forever.
983int main(){     
984
985   
986   
987    //Initialize global variables
988    currentAnt = 0;
989    chan = 9;
990   
991    pktCount_good = 0;
992    pktCount_bad = 0;
993   
994    pktBuf_rx = 0;
995    pktBuf_tx_DATA = 1;
996    pktBuf_tx_ACK = 2;
997    autoResp_delay = 0;
998
999    //Set the full-rate modulation to QPSK by default
1000    pktFullRate = HDR_FULLRATE_QPSK;
1001   
1002    //Set the payload coding rate to NONE by default
1003    //Note: Reference Design 12 PHY does not provide channel coding
1004    pktCodeRate = CODE_RATE_NONE;
1005   
1006    //Initialize the framework
1007    warpmac_init();
1008    maximumReSend = 8;
1009    warpmac_setMaxResend(maximumReSend);
1010    warpmac_setMaxCW(5);
1011
1012    warpphy_setAntennaMode(TX_ANTMODE_SISO_ANTA, RX_ANTMODE_SISO_ANTA);
1013//  warpphy_setAntennaMode(TX_ANTMODE_ALAMOUTI, RX_ANTMODE_ALAMOUTI_ANTA);
1014
1015    warpmac_setTimeout(100); //400
1016    warpmac_setSlotTime(22); //9 20
1017   
1018    //Read Dip Switch value from FPGA board.
1019    //This value will be used as an index into the routing table for other nodes
1020    myID = (unsigned short int)warpmac_getMyId();
1021           
1022    //Rx buffer is where the EMAC will DMA Wireless payloads from
1023    warpmac_setRxBuffer(&rxBuffer, pktBuf_rx);
1024    //Tx buffer is where the EMAC will DMA Ethernet payloads to
1025    warpmac_setTxBuffer(pktBuf_tx_DATA);
1026   
1027    //Copy this node's MAC address into the Tx buffer's source address field
1028    txBuffer.header.srcAddr = (unsigned short int)( ((myID + 2)<<8) | myID);
1029   
1030    //Register callbacks
1031    warpmac_setBadHeaderCallback((void *)phyRx_badHeader_callback);
1032    warpmac_setGoodHeaderCallback((void *)phyRx_goodHeader_callback);
1033    warpmac_setTimerCallback((void *)timer_callback);
1034    warpmac_setDataFromNetworkCallback((void *)dataFromNetworkLayer_callback);
1035    warpmac_setMgmtFromNetworkCallback((void *)mgmtFromNetworkLayer_callback);
1036    warpmac_setUpButtonCallback((void *)up);
1037    warpmac_setMiddleButtonCallback((void *)middle);
1038    warpmac_setLeftButtonCallback((void *)left);
1039    warpmac_setRightButtonCallback((void *)right);
1040    warpmac_setUartRecvCallback((void *)uartRecv_callback);
1041   
1042
1043    userIOBoard_LEDs = 1;
1044    //Initialize the LCD for slot 1 (i.e. don't flip the image) and non-inverted colors
1045    warp_userioboard_lcd_init(1, 0);
1046    warp_userioboard_set_lcd_charbuf(1);
1047   
1048    //Print some static lines to the user I/O board LCD
1049    //snprintf(charsToPrint, 16, " Ref Design v12 ", pktCount_bad);
1050    warp_userio_lcd_printline("RefDesign v13.10", 16, 1, 1);
1051    //snprintf(charsToPrint, 16, "  Rx Pkt Counts", pktCount_bad);
1052    warp_userio_lcd_printline("  Rx Pkt Counts ", 16, 3, 1);
1053   
1054    //Set the user I/O board LEDs
1055    warp_userioboard_set_leds(userIOBoard_LEDs);
1056   
1057    //Set the default center frequency
1058    warpphy_setChannel(GHZ_2, chan);
1059   
1060    //Enable carrier sensing
1061    warpmac_enableCSMA();
1062   
1063    /******** START autoResponse setup *******/
1064    //Setup the PHY's autoResponse system
1065    // For CSMA, it is configured to send pktBuf 2 when a good DATA packet
1066    //  is received with myID as the destination address
1067   
1068    //Match condition 0: received header's destination address is myID
1069    autoResp_matchCond = PHY_AUTORESPONSE_MATCH_CONFIG(PKTHEADER_INDX_DSTADDR, 2, htons( ((myID+2)<<8 | myID)) );
1070    mimo_ofdmTxRx_setMatch0(autoResp_matchCond);
1071
1072    //Match condition 1: received header's type is DATA
1073    autoResp_matchCond = PHY_AUTORESPONSE_MATCH_CONFIG(PKTHEADER_INDX_TYPE, 1, DATAPACKET);
1074    mimo_ofdmTxRx_setMatch1(autoResp_matchCond);
1075   
1076    //Configure the header translator to use the Rx pkt's src address as the outgoing pkt's dst address
1077    // Addresses are two bytes, so two entries in the header translator need to be overridden
1078    // Except for these bytes, the ACK pktBuf's contents will be sent unaltered
1079    // PHY_HEADERTRANSLATE_SET(templatePktBuf, byteAddrToOverwrite, srcPktBuf, srcByteAddr)
1080    PHY_HEADERTRANSLATE_SET(pktBuf_tx_ACK, (PKTHEADER_INDX_DSTADDR+0), pktBuf_rx, (PKTHEADER_INDX_SRCADDR+0));
1081    PHY_HEADERTRANSLATE_SET(pktBuf_tx_ACK, (PKTHEADER_INDX_DSTADDR+1), pktBuf_rx, (PKTHEADER_INDX_SRCADDR+1));
1082
1083    //Create a template ACK packet
1084    templatePkt.header.fullRate = pktFullRate;
1085    templatePkt.header.codeRate = pktCodeRate;
1086    templatePkt.header.length = 0;
1087    templatePkt.header.srcAddr = (unsigned short)(((myID+2)<<8) | myID);
1088    templatePkt.header.pktType = ACKPACKET;
1089   
1090    //Copy the header down to the PHY's packet buffer
1091    // This doesn't actually send anything; the autoResponse system will use this template when sending ACKs
1092    warpmac_prepPhyForXmit(&templatePkt, pktBuf_tx_ACK);
1093
1094    //Action defitions come last; bad things might happen if an action is enabled before the template pkt is ready
1095
1096    //Action 0: send pkt from buf 2 when match0 & match1 & goodPkt, using header translation
1097    autoResp_action = PHY_AUTORESPONSE_TXACTION_CONFIG(pktBuf_tx_ACK, 1, (PHY_AUTORESPONSE_REQ_MATCH0 | PHY_AUTORESPONSE_REQ_MATCH1), autoResp_delay, 0, 0, 1, 0, 1);
1098    mimo_ofdmTxRx_setAction0(autoResp_action);
1099   
1100    /******* END autoResponse setup ******/
1101   
1102    //Listen for new packets to send (either from Ethernet or local dummy packets)
1103    //warpmac_setDebugGPIO(0);
1104    warpmac_enableDataFromNetwork();
1105   
1106    //Set the modulation scheme use for base rate (header) symbols
1107    warpmac_setBaseRate(QPSK);
1108   
1109    //Enable local packet generation (ignoring Ethernet)
1110    warpmac_enableDummyPacketMode();
1111   
1112   
1113   
1114   
1115    warpmac_stopPacketGeneration(); //second argument is interval in usec
1116   
1117    //Intialize Global variables for csmaMac extension
1118    Mode=0;
1119    sendStats=0;
1120    Time=0;
1121   packetlength=1470;
1122   
1123    int i; 
1124    //Initialize the Stats Structs
1125    for(i=0; i<WARPNET_NUMNODES; i++)
1126    {
1127        txSequences[i] = 1;
1128        rxSequences[i] = 0;
1129        myStats[i].structType = STRUCTID_NODESTATS;
1130        myStats[i].nodeID = myID;
1131        myStats[i].partnerID = i;
1132        myStats[i].goodPackets = 0;
1133        myStats[i].otherBadPackets = 0;
1134        myStats[i].partnerBadPackets = 0;
1135        myStats[i].rxBytes = 0;
1136        myStats[i].txBytes = 0;
1137        myStats[i].reserved0 = 0;
1138    }
1139   
1140    //CRH
1141//  if(myID==1) warpmac_startPacketGeneration(1470,0);
1142//  warpphy_setTxPower(63);
1143    //CRH
1144   
1145#define PKTHEADER_INDX_DSTADDR  6//6
1146#define PKTHEADER_INDX_SRCADDR  4
1147#define PKTHEADER_INDX_TYPE     10
1148/* 
1149    //Setting up auto ACK responder
1150    unsigned int matchCond_toMe     = PHY_AUTORESPONSE_MATCH_CONFIG(PKTHEADER_INDX_DSTADDR, 1, myID);
1151    unsigned int matchCond_dataType = PHY_AUTORESPONSE_MATCH_CONFIG(PKTHEADER_INDX_TYPE, 1, DATAPACKET);
1152    //  unsigned int action_ackPktBuf   = PHY_AUTORESPONSE_TXACTION_CONFIG(2, 0, (PHY_AUTORESPONSE_REQ_MATCH0 | PHY_AUTORESPONSE_REQ_MATCH1), 50, 0, 0, 1, 0, 0);
1153    unsigned int action_ackPktBuf   = PHY_AUTORESPONSE_TXACTION_CONFIG(2, 1, (PHY_AUTORESPONSE_REQ_MATCH0 | PHY_AUTORESPONSE_REQ_MATCH1), 0, 0, 0, 1, 0, 1);
1154    mimo_ofdmTxRx_setMatch0(matchCond_toMe);
1155    mimo_ofdmTxRx_setMatch1(matchCond_dataType);
1156    mimo_ofdmTxRx_setAction0(action_ackPktBuf);
1157   
1158    xil_printf("Set match0=%x, match1=%x, act0=%x\r\n", mimo_ofdmTxRx_getMatch0(), mimo_ofdmTxRx_getMatch1(), mimo_ofdmTxRx_getAction0());
1159   
1160    unsigned char ack_template = 2;
1161    unsigned char pktBuf_HdrSrc = 0;
1162   
1163    //Fill in the header translator with non-translating values by default
1164    // This will "overwrite" the header with the same pktbuf/byte combos as the template buffer
1165    unsigned char i;
1166    for(i=0; i<32; i++)
1167    {
1168        XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXHEADERTRANSLATE+i*sizeof(int), ( (ack_template<<5) | i));
1169    }
1170   
1171    XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXHEADERTRANSLATE+PKTHEADER_INDX_DSTADDR*sizeof(int), ( (1<<5) | PKTHEADER_INDX_SRCADDR));
1172    XIo_Out32(XPAR_OFDM_TXRX_MIMO_PLBW_0_MEMMAP_TXHEADERTRANSLATE+(PKTHEADER_INDX_DSTADDR+1)*sizeof(int), ( (1<<5) | (PKTHEADER_INDX_SRCADDR+1)));
1173    */
1174   
1175    //WarpRadio_v1_TxEnSoftControlDisable(RADIO2_ADDR);
1176   
1177    //Get Clock input
1178    XTime rand_time;
1179    XTime_GetTime(&end_timer);
1180   
1181    //Seed Random Number Generator
1182    srand(myID ^ ((int) rand_time) ^ WarpRadio_v1_RSSIData(RADIO2_ADDR));
1183   
1184    //Initialize Ethernet Packet Header
1185    txEthPktHeader.ethType = WARPNET_ETHTYPE_NODE2SVR;
1186    memset(&(txEthPktHeader.srcAddr), (unsigned char)myID, 6); //Generic source address; ignored throughout
1187    memset(&(txEthPktHeader.dstAddr), (unsigned char)0xFF, 6); //Broadcast destination address
1188       
1189    /*
1190    unsigned int pktBuf_payloadAddr;
1191    pktBuf_payloadAddr = warpphy_getBuffAddr(WARPNET_CHANEST_PKTBUFFINDEX);
1192   
1193    chanEst_AA[0].structType = STRUCTID_CHANEST;
1194    chanEst_AA[0].nodeID = myID;
1195    chanEst_AA[0].partnerID = 0;
1196    chanEst_AA[0].antennaID = 0;
1197    chanEst_AA[0].agc_RF = 0;
1198    chanEst_AA[0].agc_BB = 0;
1199    chanEst_AA[0].pktStatus = 0;
1200    chanEst_AA[0].reserved0 = 0;
1201
1202    memcpy((void *)(pktBuf_payloadAddr+sizeof(txEthPktHeader) ),
1203            (void *)&(chanEst_AA[0]), sizeof(warpnodeChanEst));
1204    */
1205
1206    xil_printf("Reference Design v12.1\r\n");
1207    xil_printf("Beginning main loop\r\n");
1208   
1209    while(1){
1210        warpmac_pollPeripherals();
1211    }
1212   
1213    return;
1214}