root/ResearchApps/MAC/HOPMAC/hopMacServer.c

Revision 998, 9.8 kB (checked in by chunter, 3 months ago)

clean hopmac

Line 
1 /*! \file hopMacServer.c
2 \brief Hop MAC Workshop Exercise.
3 
4 @version 10
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 0;
164                        }
165                       
166                        warpmac_setTimer(BACKOFF);
167                        return 0;
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 0;
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 = warpphy_getBuffAddr(1)+NUM_HEADER_BYTES;
196       
197        unsigned short int* pkttype = &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 = QPSK;
222       
223        //Copy in the packet's destination MAC address
224        //Hard-coded as this node's partner node
225        memcpy(txBuffer.header.destAddr,routeTable[*destNode].addr,6);
226       
227       
228        if(warpmac_carrierSense()){
229                //Copy the header over to packet buffer 1
230                warpmac_prepPhyForXmit(&txBuffer,1);
231                //Send packet buffer 1
232                warpmac_startPhyXmit(1);
233                //Wait for it to finish and enable the receiver
234                warpmac_finishPhyXmit();
235                //Start a timeout timer
236                warpmac_setTimer(TIMEOUT);
237        }
238        else{
239                //Start a backoff timer
240                warpmac_setTimer(BACKOFF);
241        }
242       
243        //}
244        return;
245}
246
247///@brief Callback for the reception of bad wireless headers
248///
249///@param packet Pointer to received Macframe
250void phyRx_badHeader_callback() {
251        warpmac_incrementLEDLow();
252}
253
254///@brief Callback for the reception of good wireless headers
255///
256///This function then polls the PHY to determine if the entire packet passes checksum
257///thereby triggering the transmission of the ACK and the transmission of the received
258///data over Ethernet.
259///@param packet Pointer to received Macframe
260void phyRx_goodHeader_callback(Macframe* packet){
261        warpmac_incrementLEDHigh();
262        Macframe ackPacket;
263        unsigned char state=INCOMPLETE;
264       
265        if(warpmac_addressedToMe(packet)){
266               
267                switch(packet->header.pktType){
268                        case DATAPACKET:
269                               
270                               
271                               
272                                while(state==INCOMPLETE){
273                                        //Blocks until the PHY reports the received packet as either good or bad
274                                        state = warpphy_pollRxStatus();
275                                }
276                               
277                                if(state==GOODPACKET){
278                                        warpmac_prepEmacForXmit(packet);
279                                        //Blocks until the PHY is finished sending and enables the receiver
280                                        warpmac_startEmacXmit(packet);
281                                }
282                               
283                                if(state==BADPACKET){
284                                        //xil_printf("BAD Packet, good header\r\n");
285                                        warpmac_incrementLEDLow();
286                                }
287                               
288                                break;
289                               
290                                case ACKPACKET:
291                               
292                                if(warpmac_inTimeout()){
293                                        txBuffer.isNew = 0;
294                                        warpmac_incrementLEDHigh();
295                                        warpmac_clearTimer(TIMEOUT);
296                                        warpmac_enableEthernet();
297                                }
298                               
299                                break;
300                               
301                               
302                }
303               
304               
305        }
306}
307
308///@brief Main function
309///
310///This function configures MAC parameters, enables the underlying frameworks, and then loops forever.
311int main(){             
312        xil_printf("Hopmac Server\r\n");
313        //Initialize the framework
314        warpmac_init();
315       
316        chan = 1;
317       
318        warpmac_setMaxResend(2);
319        warpmac_setMaxCW(2);
320        warpmac_setTimeout(160);
321        warpmac_setSlotTime(9);
322       
323       
324       
325        //Read Dip Switch value from FPGA board.
326        //This value will be used as an index into the routing table for other nodes
327        myID = warpmac_getMyId();
328       
329        //Create an arbitrary address for this node
330        unsigned char tmpAddr[6] = {0x16,0x24,0x63,0x53,0xe2,0xc2+myID};
331       
332       
333        memcpy((unsigned char *)myAddr,(unsigned char *)tmpAddr,6);
334       
335        //Fill an arbitrary routing table so that nodes know each others' addresses
336        unsigned char i;
337        for(i=0;i<16;i++){
338                routeTable[i].addr[0] = myAddr[0];
339                routeTable[i].addr[1] = myAddr[1];
340                routeTable[i].addr[2] = myAddr[2];
341                routeTable[i].addr[3] = myAddr[3];
342                routeTable[i].addr[4] = myAddr[4];
343                routeTable[i].addr[5] = myAddr[5]+i-myID;
344        }
345       
346        warpmac_setMacAddr((unsigned char *)(&myAddr));
347       
348       
349        warpmac_setRxBuffer(&rxBuffer,0);
350        //Tx buffer is where the EMAC will DMA payloads to
351        warpmac_setTxBuffer(1);
352       
353        //Copy this node's MAC address into the Tx buffer's source address field
354        memcpy(txBuffer.header.srcAddr,(unsigned char *)myAddr,6);
355       
356        warpmac_setBadHeaderCallback((void *)phyRx_badHeader_callback);
357        warpmac_setGoodHeaderCallback((void *)phyRx_goodHeader_callback);
358        warpmac_setTimerCallback((void *)timer_callback);
359        warpmac_setEmacCallback((void *)emacRx_callback);
360       
361       
362        warpmac_setUpButtonCallback((void *)up);
363        warpmac_setMiddleButtonCallback((void *)middle);
364       
365       
366        //Set the default center frequency
367        warpphy_setChannel(GHZ_2, chan);
368       
369        warpmac_enableCSMA();
370        warpmac_enableEthernet();
371       
372        //Set the modulation scheme use for base rate (header) symbols
373        warpmac_setBaseRate(QPSK);
374       
375        XTime tEnd, tCur;
376        unsigned int seconds = 5;
377        unsigned char startCount = 1;
378       
379        xil_printf("Mask version 1\r\n");
380        while(1){
381                warpmac_pollEthernet();
382               
383                XTime_GetTime(&tCur);
384                //usleep(1000);
385                if (startCount){
386                        tEnd  = tCur + ((XTime) seconds) * 160000000;
387                        startCount=0;
388                }
389               
390                //      if(tCur>tEnd){
391                //              switchChannels();
392                //              startCount=1;
393                //              seconds = 1;
394                //
395                //      }
396                if(tCur>tEnd){
397                        if(txBuffer.isNew==0){
398                                warpmac_disableEthernet();
399                                usleep(1000);
400                                switchChannels();
401                                startCount=1;
402                                seconds = 5;
403                                warpmac_enableEthernet();
404                        }
405                }
406               
407        }
408        return;
409}
Note: See TracBrowser for help on using the browser.