root/ResearchApps/MAC/HOPMAC/hopMacClient.c

Revision 997, 10.4 kB (checked in by chunter, 6 weeks ago)

clean hopmac

Line 
1 /*! \file hopMacClient.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 "hopMacClient.h"
33#include "xparameters.h"
34#include "string.h"
35#include "errno.h"
36#include "stdlib.h"
37#include "stdio.h"
38#include "xutil.h"
39#include "ofdm_timer_regMacros.h"
40
41///Routing table with agreed upon mapping between dipswitches and physical addresses
42typedef struct {
43        unsigned char addr[6];
44} route;
45
46///Instance of the routing table
47route routeTable[16];
48
49///Byte array containing physical MAC address of this node
50unsigned char myAddr[6];
51///Index to the routing table that identifies this node
52unsigned char myID;
53
54///Buffer for holding a packet-to-xmit across multiple retransmissions
55Macframe txBuffer;
56///Buffer to hold received packet
57Macframe rxBuffer;
58
59unsigned char chan;
60
61///Data packet with payload meant for Ethernet transmission
62#define DATAPACKET 1
63///Acknowledgement packet meant for halting retransmissions
64#define ACKPACKET 0
65///Control packet containing destination frequency band
66#define HOPPACKET 2
67
68/**********************DELETE FOR WORKSHOP***************************/
69/////////////////////SEEK MODE: OPTIONAL EXTENSION//////////////////////////
70unsigned int waitTime = 200;    //If a packet hasn't been received in the last 200 ms, exhaustively search the spectrum
71unsigned char scanMode=0; //By default, the optional scan mode is disabled
72void middle(){
73        /*Disables the optional scan mode*/
74        scanMode=0;
75}
76
77void up(){
78        /*Enables the optional scan mode*/
79        scanMode=1;
80        warpmac_stopTimer();
81        warpmac_setTimerVal(waitTime*40000);
82        warpmac_startTimer(DISABLECSMA);
83}
84
85void left(){
86        /*Increases the timeout to begin exhaustive scan*/
87        waitTime=waitTime-10;
88}
89
90void right(){
91        /*Decreases the timeout to begin exhaustive scan*/
92        waitTime=waitTime+10;
93}
94
95unsigned char dispIndex = 0;
96int timerExpire(){
97        if(scanMode){
98                chan = ((chan+1)%15);
99                if(chan==0) chan=1;
100                warpphy_setChannel(GHZ_2,chan);
101                warpmac_leftHex(chan);
102                warpmac_stopTimer();
103                warpmac_setTimerVal(waitTime*40000);
104                warpmac_startTimer(DISABLECSMA);
105        }
106}
107/////////////////////////////////////////////////////////////////////////////
108/**********************DELETE FOR WORKSHOP***************************/
109
110///@brief Callback for the reception of Ethernet packets
111///
112///This function is called by the ethernet MAC drivers
113///when a packet is available to send. This function fills
114///the Macframe transmit buffer with the packet and sends
115///it over the OFDM link
116///@param length Length, in bytes, of received Ethernet frame
117///@param payload address of first byte in Ethernet payload.
118void emacRx_callback(Xuint32 length, char* payload){
119       
120        //Set the length of the Macfram
121        txBuffer.header.length = length;
122        //Define the type to be data
123        txBuffer.header.pktType = DATAPACKET;
124        //Set the modulation scheme for the packet's full-rate symbols
125        txBuffer.header.fullRate = QPSK;
126        //Copy in the packet's destination MAC address
127        //Hard-coded as the server (ID = 0)
128        memcpy(txBuffer.header.destAddr,routeTable[0].addr,6);
129        //Copy the header over to packet buffer 1
130        warpmac_prepPhyForXmit(&txBuffer,1);
131        //Send packet buffer 1
132        warpmac_startPhyXmit(1);
133        //Wait for it to finish and enable the receiver
134        warpmac_finishPhyXmit();
135       
136        return 0;
137}
138
139///@brief Callback for the reception of bad wireless headers
140///
141///@param packet Pointer to received Macframe
142void phyRx_badHeader_callback() {
143        warpmac_incrementLEDLow();
144}
145
146///@brief Callback for the reception of good wireless headers
147///
148///This function then polls the PHY to determine if the entire packet passes checksum
149///thereby triggering the transmission of the ACK and the transmission of the received
150///data over Ethernet.
151///@param packet Pointer to received Macframe
152void phyRx_goodHeader_callback(Macframe* packet){
153
154        /**********************DELETE FOR WORKSHOP***************************/                 
155        /////////////////////SEEK MODE: OPTIONAL EXTENSION//////////////////////////
156        warpmac_stopTimer();
157        warpmac_setTimerVal(waitTime*40000);
158        warpmac_startTimer(DISABLECSMA);
159        /////////////////////////////////////////////////////////////////////////////
160        /**********************DELETE FOR WORKSHOP***************************/
161       
162//Pseudocode for workshop users:
163//1) Instantiate a "Macframe" that will be an acknowledgement packet
164//2) Instantiate a variable to keep track of the receiver's state. Default this state variable to "INCOMPLETE"
165//3) Check the "pktType" of the "phyHeader" of the received "Macframe"
166//If "HOPPACKET"
167//              4) Animate the top two LEDs using the "warpmac_incrementLEDHigh" function
168//              5) Switch to the channel located in "packet->header.reserved1" using the "warpphy_setChannel" function (make sure to stay in "GHZ_2")
169//If "DATAPACKET"
170//              4) Set the acknowledgment "Macframe" to length 0 (Header only... no payload)
171//              5) Set the "pktType" of the "phyHeader" of the acknowledgment "Macframe" to "ACKPACKET"
172//              6) Set full rate modulation order to "QPSK"
173//              7) memcpy the 6 bytes of "myAddr" into the "srcAddr" field of the acknowledgment
174//              8) memcpy the 6 bytes of "packet->header.srcAddr" into the "destAddr" field of the acknowledgment (to send it back to the source of the data)
175//              9) Copy the acknowledgement over to packet buffer 2 using the "warpmac_prepPhyForXmit" function
176//              10) Poll the state of the state of the receiver using "warpphy_pollRxStatus." Block until the state turns to either "GOODPACKET" or "BADPACKET"
177//              If "GOODPACKET"
178//                      11) Send the acknowledgment sitting in packet buffer 2 using the "warpmac_startPhyXmit"
179//                              Note: Since we have pre-loaded the acknowledgment into the PHY transmitter, the ACK will go over-the-air within 20 microseconds
180//                                        after the source transmitter finished
181//                      12) Animate the top two LEDs to visualize this behavior using the "warpmac_incrementLEDHigh" function
182//                      13) Copy the received "Macframe" to Ethernet using "warpmac_prepEmacForXmit"   
183//                      14) Start the Emac using "warpmac_startEmacXmit"
184//              If "BADPACKET"
185//                      11) Animate the bottom two LEDs to visualize this behavior using the "warpmac_incrementLEDLow" function
186       
187        /**********************DELETE FOR WORKSHOP***************************/
188        Macframe ackPacket;
189        unsigned char state=INCOMPLETE;
190       
191        if(packet->header.pktType==HOPPACKET){
192                //If HOPPACKET is received, jump to the channel in reserved1 of header
193                warpmac_incrementLEDHigh();
194                warpphy_setChannel(GHZ_2,packet->header.reserved1);
195                chan = packet->header.reserved1;
196                warpmac_leftHex(chan);
197        }
198       
199       
200        if(packet->header.pktType==DATAPACKET){
201               
202                if(warpmac_addressedToMe(packet)){
203                       
204                       
205                        ackPacket.header.length = 0;
206                        ackPacket.header.pktType = ACKPACKET;
207                        ackPacket.header.fullRate = QPSK;
208                        memcpy(ackPacket.header.srcAddr,(unsigned char *)myAddr,6);
209                        memcpy(ackPacket.header.destAddr,packet->header.srcAddr,6);
210                       
211                        //Copy the header over to packet buffer 2
212                        warpmac_prepPhyForXmit(&ackPacket,2);
213                       
214                       
215                        while(state==INCOMPLETE){
216                                //Blocks until the PHY reports the received packet as either good or bad
217                                state = warpphy_pollRxStatus();
218                        }
219                       
220                        if(state==GOODPACKET){
221                                //Send packet buffer 2
222                                warpmac_startPhyXmit(2);
223                                warpmac_incrementLEDHigh();
224                                //Starts the DMA transfer of the payload into the EMAC
225                                warpmac_prepEmacForXmit(packet);
226                                //Blocks until the PHY is finished sending and enables the receiver
227                                warpmac_finishPhyXmit();
228                                //Waits until the DMA transfer is complete, then starts the EMAC
229                                warpmac_startEmacXmit(packet);
230                               
231                        }
232                       
233                        if(state==BADPACKET){
234                                //xil_printf("BAD Packet, good header\r\n");
235                                warpmac_incrementLEDLow();
236                        }
237                       
238                }
239               
240        }
241        /**********************DELETE FOR WORKSHOP***************************/
242}
243
244///@brief Main function
245///
246///This function configures MAC parameters, enables the underlying frameworks, and then loops forever.
247int main(){             
248        xil_printf("Hopmac Client\r\n");
249        //Initialize the framework
250        warpmac_init();
251       
252        chan = 1;
253       
254        //Read Dip Switch value from FPGA board.
255        //This value will be used as an index into the routing table for other nodes
256        myID = warpmac_getMyId();
257       
258        //Create an arbitrary address for this node
259        unsigned char tmpAddr[6] = {0x16,0x24,0x63,0x53,0xe2,0xc2+myID};
260       
261       
262        memcpy((unsigned char *)myAddr,(unsigned char *)tmpAddr,6);
263       
264        //Fill an arbitrary routing table so that nodes know each others' addresses
265        unsigned char i;
266        for(i=0;i<16;i++){
267                routeTable[i].addr[0] = myAddr[0];
268                routeTable[i].addr[1] = myAddr[1];
269                routeTable[i].addr[2] = myAddr[2];
270                routeTable[i].addr[3] = myAddr[3];
271                routeTable[i].addr[4] = myAddr[4];
272                routeTable[i].addr[5] = myAddr[5]+i-myID;
273        }
274       
275        warpmac_setMacAddr((unsigned char *)(&myAddr));
276       
277       
278        warpmac_setRxBuffer(&rxBuffer,0);
279        //Tx buffer is where the EMAC will DMA payloads to
280        warpmac_setTxBuffer(1);
281       
282        //Copy this node's MAC address into the Tx buffer's source address field
283        memcpy(txBuffer.header.srcAddr,(unsigned char *)myAddr,6);
284       
285        warpmac_setBadHeaderCallback((void *)phyRx_badHeader_callback);
286        warpmac_setGoodHeaderCallback((void *)phyRx_goodHeader_callback);
287        warpmac_setEmacCallback((void *)emacRx_callback);
288       
289       
290        /////////////////////SEEK MODE: OPTIONAL EXTENSION//////////////////////////
291        warpmac_setMiddleButtonCallback(middle);
292        warpmac_setUpButtonCallback(up);
293        warpmac_setLeftButtonCallback(left);
294        warpmac_setRightButtonCallback(right);
295        warpmac_setTimerCallback(timerExpire);
296        warpmac_setTimerVal(waitTime*40000);
297        warpmac_startTimer(DISABLECSMA);
298        /////////////////////////////////////////////////////////////////////////////
299       
300       
301        //Set the default center frequency
302        warpphy_setChannel(GHZ_2, chan);
303       
304        warpmac_enableCSMA();
305        warpmac_enableEthernet();
306       
307        //Set the modulation scheme use for base rate (header) symbols
308        warpmac_setBaseRate(QPSK);
309       
310        while(1){
311                warpmac_pollEthernet();
312        }
313       
314        return;
315}
Note: See TracBrowser for help on using the browser.