source: ResearchApps/MAC/Workshop_MACs/HOPMAC/hopMacServer.c

Last change on this file was 1121, checked in by chunter, 16 years ago

Updated the Doxygen changelog

File size: 10.0 KB
Line 
1 /*! \file hopMacServer.c
2 \brief Hop MAC Workshop Exercise.
3 
4 @version 12
5 @author Chris Hunter
6 
7 This exercise is an extension of the previous
8 HALFMAC exercise. In fact, you are welcome
9 top copy and paste the parts of the code you
10 completed in that exercise for the similar
11 tasks here.
12 
13 The twist in this lab is that the server
14 will periodically hop to a new part of the
15 spectrum. Before doing so, it will transmit
16 a special control packet (HOPPACKET) that
17 contains the destination frequency band.
18 
19 If the packet is missed, your receiver will
20 be stuck until the transmitter randomly hops
21 back onto the channel you were sitting at.
22 This can potentially be a very long time.
23 An advanced extension to this lab is to
24 scan for packets in various channels when
25 no good packet is received for a certain
26 amount of time. For our purposes, let this
27 timeout be around 200ms.
28 */
29
30#include "warpmac.h"
31#include "warpphy.h"
32#include "hopMacServer.h"
33#include "xparameters.h"
34#include <string.h>
35#include <errno.h>
36#include <stdlib.h>
37#include <stdio.h>
38#include "ofdm_txrx_mimo_regMacros.h"
39#include "xtime_l.h"
40
41
42
43
44///Routing table with agreed upon mapping between dipswitches and physical addresses
45typedef struct {
46    unsigned char addr[6];
47} route;
48
49///Instance of the routing table
50route routeTable[16];
51
52///Byte array containing physical MAC address of this node
53unsigned char myAddr[6];
54///Index to the routing table that identifies this node
55unsigned char myID;
56
57///Buffer for holding a packet-to-xmit across multiple retransmissions
58Macframe txBuffer;
59///Buffer to hold received packet
60Macframe rxBuffer;
61
62//Misc. Globals
63unsigned char currentAnt = 0;
64static volatile unsigned char uartByte = 0;
65unsigned char chan;
66
67unsigned char controlMode = 1;
68
69
70///Data packet with payload meant for Ethernet transmission
71#define DATAPACKET 1
72///Acknowledgement packet meant for halting retransmissions
73#define ACKPACKET 0
74///Hop packet to notify nodes ofchannel hopping event
75#define HOPPACKET 2
76
77#define ARPREQUEST 0x806
78
79
80///@brief Callback for the depression of the up push button
81///
82///This button increments the 2.4GHz channel being used
83void up(){
84    controlMode=1;
85}
86
87///@brief Callback for the depression of the middle push button
88///
89///This button decrements the 2.4GHz channel being used
90void middle(){
91    controlMode=0;
92}
93
94void switchChannels(){
95    Macframe followMe;
96   
97                            //   1, 2, 3, 4, 5, 6, 7, 8, 9, 10,11,12,13,14
98    unsigned char chanVec[14] = {1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 14};
99    //unsigned char chanVec[14] = {1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0};
100    //unsigned char chanVec[14] = {0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0};
101    chan = rand()%14;
102    while(chanVec[chan] != 1){//11
103        chan = rand()%14;
104    }
105    chan = chan+1;
106   
107   
108    unsigned char broadcast[6] = {255,255,255,255,255,255};
109    followMe.header.length = 0;
110    followMe.header.pktType = HOPPACKET;
111    memcpy(followMe.header.destAddr,broadcast,6);
112    followMe.header.reserved1 = chan;
113    char i=0;
114#define NUMCONTROL 32
115    if(controlMode){
116        while(i<NUMCONTROL){
117            if(warpmac_carrierSense()){
118                //Copy the header over to packet buffer 1
119                warpmac_prepPhyForXmit(&followMe,2);
120                //Send packet buffer 1
121                warpmac_startPhyXmit(2);
122                //Wait for it to finish and enable the receiver
123                warpmac_finishPhyXmit();
124               
125            }
126            i++;
127        }
128    }
129   
130    //  warpmac_sendOfdm(&txBuffer);
131    //  warpmac_sendOfdm(&txBuffer);
132    //  warpmac_sendOfdm(&txBuffer);
133    //  warpmac_freePayload(&txBuffer);
134   
135    warpphy_setChannel(GHZ_2,chan);
136    warpmac_leftHex(chan);
137    //xil_printf("Chan = %d\r\n",chan);
138   
139    //  usleep(500);
140   
141   
142}
143
144
145///@brief Callback for the expiration of timers
146///
147///This function is responsible for handling #TIMEOUT and #BACKOFF.
148///The job responsibilities of this function are to:
149///-increase the contention window upon the expiration of a #TIMEOUT
150///-initiate a #BACKOFF timer upon the expiration of a #TIMEOUT
151///-retransmit a packet upon the expiration of a #BACKOFF
152///@param timerType #TIMEOUT or #BACKOFF
153void timer_callback(unsigned char timerType){
154    int status;
155    switch(timerType){
156        case TIMEOUT:
157           
158            status = warpmac_incrementResend(&txBuffer);
159            if(status == 0){
160                txBuffer.isNew = 0;
161                //The packet has been resent too many times, so we are going to re-enable Ethernet and overwrite
162                warpmac_enableEthernet();
163                return;
164            }
165           
166            warpmac_setTimer(BACKOFF);
167            return;
168           
169            break;
170            case BACKOFF:
171           
172            //Copy the header over to packet buffer 1
173            warpmac_prepPhyForXmit(&txBuffer,1);
174            //Send packet buffer 1
175            warpmac_startPhyXmit(1);
176            //Wait for it to finish and enable the receiver
177            warpmac_finishPhyXmit();
178            //Start a timeout timer
179            warpmac_setTimer(TIMEOUT);
180            break;
181            return;
182    }
183}
184
185
186///@brief Callback for the reception of Ethernet packets
187///
188///This function is called by the ethernet MAC drivers
189///when a packet is available to send. This function fills
190///the Macframe transmit buffer with the packet and sends
191///it over the OFDM link
192///@param length Length, in bytes, of received Ethernet frame
193void emacRx_callback(Xuint32 length){
194    txBuffer.isNew = 1;
195    u8* payload = (u8*)(warpphy_getBuffAddr(1)+NUM_HEADER_BYTES);
196   
197    unsigned short int* pkttype = (unsigned short int*)(&payload[12]);
198    unsigned char* destNode;
199   
200   
201    if(*pkttype==ARPREQUEST){
202        destNode=&payload[41];
203    }
204    else{
205        destNode=&payload[33];
206    }
207   
208   
209    //if(*destIP>0xc0a80100 && *destIP<0xc0a8010F){
210   
211    //if(destNode>0 && destNode<0xc0a8010F){
212   
213   
214   
215    warpmac_disableEthernet();
216    txBuffer.header.currReSend = 0;
217    txBuffer.header.length = length;
218    txBuffer.header.pktType = DATAPACKET;
219   
220    //Set the modulation scheme for the packet's full-rate symbols
221    txBuffer.header.fullRate = HDR_FULLRATE_QPSK;
222    //Set the payload coding rate
223    txBuffer.header.codeRate = CODE_RATE_34;
224   
225    //Copy in the packet's destination MAC address
226    //Hard-coded as this node's partner node
227    memcpy(txBuffer.header.destAddr,routeTable[*destNode].addr,6);
228   
229   
230    if(warpmac_carrierSense()){
231        //Copy the header over to packet buffer 1
232        warpmac_prepPhyForXmit(&txBuffer,1);
233        //Send packet buffer 1
234        warpmac_startPhyXmit(1);
235        //Wait for it to finish and enable the receiver
236        warpmac_finishPhyXmit();
237        //Start a timeout timer
238        warpmac_setTimer(TIMEOUT);
239    }
240    else{
241        //Start a backoff timer
242        warpmac_setTimer(BACKOFF);
243    }
244   
245    //}
246    return;
247}
248
249///@brief Callback for the reception of bad wireless headers
250///
251///@param packet Pointer to received Macframe
252void phyRx_badHeader_callback() {
253    warpmac_incrementLEDLow();
254}
255
256///@brief Callback for the reception of good wireless headers
257///
258///This function then polls the PHY to determine if the entire packet passes checksum
259///thereby triggering the transmission of the ACK and the transmission of the received
260///data over Ethernet.
261///@param packet Pointer to received Macframe
262void phyRx_goodHeader_callback(Macframe* packet){
263    warpmac_incrementLEDHigh();
264    Macframe ackPacket;
265    unsigned char state=INCOMPLETE;
266   
267    if(warpmac_addressedToMe(packet)){
268       
269        switch(packet->header.pktType){
270            case DATAPACKET:
271               
272               
273               
274                while(state==INCOMPLETE){
275                    //Blocks until the PHY reports the received packet as either good or bad
276                    state = warpphy_pollRxStatus();
277                }
278               
279                if(state==GOODPACKET){
280                    warpmac_prepEmacForXmit(packet);
281                    //Blocks until the PHY is finished sending and enables the receiver
282                    warpmac_startEmacXmit(packet);
283                }
284               
285                if(state==BADPACKET){
286                    //xil_printf("BAD Packet, good header\r\n");
287                    warpmac_incrementLEDLow();
288                }
289               
290                break;
291               
292                case ACKPACKET:
293               
294                if(warpmac_inTimeout()){
295                    txBuffer.isNew = 0;
296                    warpmac_incrementLEDHigh();
297                    warpmac_clearTimer(TIMEOUT);
298                    warpmac_enableEthernet();
299                }
300               
301                break;
302               
303               
304        }
305       
306       
307    }
308}
309
310///@brief Main function
311///
312///This function configures MAC parameters, enables the underlying frameworks, and then loops forever.
313int main(){     
314    xil_printf("Hopmac Server\r\n");
315    //Initialize the framework
316    warpmac_init();
317   
318    chan = 1;
319   
320    warpmac_setMaxResend(2);
321    warpmac_setMaxCW(2);
322    warpmac_setTimeout(160);
323    warpmac_setSlotTime(9);
324   
325   
326   
327    //Read Dip Switch value from FPGA board.
328    //This value will be used as an index into the routing table for other nodes
329    myID = warpmac_getMyId();
330   
331    //Create an arbitrary address for this node
332    unsigned char tmpAddr[6] = {0x16,0x24,0x63,0x53,0xe2,0xc2+myID};
333   
334   
335    memcpy((unsigned char *)myAddr,(unsigned char *)tmpAddr,6);
336   
337    //Fill an arbitrary routing table so that nodes know each others' addresses
338    unsigned char i;
339    for(i=0;i<16;i++){
340        routeTable[i].addr[0] = myAddr[0];
341        routeTable[i].addr[1] = myAddr[1];
342        routeTable[i].addr[2] = myAddr[2];
343        routeTable[i].addr[3] = myAddr[3];
344        routeTable[i].addr[4] = myAddr[4];
345        routeTable[i].addr[5] = myAddr[5]+i-myID;
346    }
347   
348    warpmac_setMacAddr((unsigned char *)(&myAddr));
349   
350   
351    warpmac_setRxBuffer(&rxBuffer,0);
352    //Tx buffer is where the EMAC will DMA payloads to
353    warpmac_setTxBuffer(1);
354   
355    //Copy this node's MAC address into the Tx buffer's source address field
356    memcpy(txBuffer.header.srcAddr,(unsigned char *)myAddr,6);
357   
358    warpmac_setBadHeaderCallback((void *)phyRx_badHeader_callback);
359    warpmac_setGoodHeaderCallback((void *)phyRx_goodHeader_callback);
360    warpmac_setTimerCallback((void *)timer_callback);
361    warpmac_setEmacCallback((void *)emacRx_callback);
362   
363   
364    warpmac_setUpButtonCallback((void *)up);
365    warpmac_setMiddleButtonCallback((void *)middle);
366   
367   
368    //Set the default center frequency
369    warpphy_setChannel(GHZ_2, chan);
370   
371    warpmac_enableCSMA();
372    warpmac_enableEthernet();
373   
374    //Set the modulation scheme use for base rate (header) symbols
375    warpmac_setBaseRate(QPSK);
376   
377    XTime tEnd, tCur;
378    unsigned int seconds = 5;
379    unsigned char startCount = 1;
380   
381    xil_printf("Mask version 1\r\n");
382    while(1){
383        warpmac_pollEthernet();
384       
385        XTime_GetTime(&tCur);
386        //usleep(1000);
387        if (startCount){
388            tEnd  = tCur + ((XTime) seconds) * 160000000;
389            startCount=0;
390        }
391       
392        //  if(tCur>tEnd){
393        //      switchChannels();
394        //      startCount=1;
395        //      seconds = 1;
396        //
397        //  }
398        if(tCur>tEnd){
399            if(txBuffer.isNew==0){
400                warpmac_disableEthernet();
401                usleep(1000);
402                switchChannels();
403                startCount=1;
404                seconds = 5;
405                warpmac_enableEthernet();
406            }
407        }
408       
409    }
410    return;
411}
Note: See TracBrowser for help on using the repository browser.