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

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

Updated the Doxygen changelog

File size: 10.9 KB
Line 
1 /*! \file hopMacClient.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 "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 = HDR_FULLRATE_QPSK;
126    //Set the payload coding rate
127    txBuffer.header.codeRate = CODE_RATE_34;
128    //Copy in the packet's destination MAC address
129    //Hard-coded as the server (ID = 0)
130    memcpy(txBuffer.header.destAddr,routeTable[0].addr,6);
131    //Copy the header over to packet buffer 1
132    warpmac_prepPhyForXmit(&txBuffer,1);
133    //Send packet buffer 1
134    warpmac_startPhyXmit(1);
135    //Wait for it to finish and enable the receiver
136    warpmac_finishPhyXmit();
137   
138    return;
139}
140
141///@brief Callback for the reception of bad wireless headers
142///
143///@param packet Pointer to received Macframe
144void phyRx_badHeader_callback() {
145    warpmac_incrementLEDLow();
146}
147
148///@brief Callback for the reception of good wireless headers
149///
150///This function then polls the PHY to determine if the entire packet passes checksum
151///thereby triggering the transmission of the ACK and the transmission of the received
152///data over Ethernet.
153///@param packet Pointer to received Macframe
154void phyRx_goodHeader_callback(Macframe* packet){
155
156    /**********************DELETE FOR WORKSHOP***************************/         
157    /////////////////////SEEK MODE: OPTIONAL EXTENSION//////////////////////////
158    warpmac_stopTimer();
159    warpmac_setTimerVal(waitTime*40000);
160    warpmac_startTimer(DISABLECSMA);
161    /////////////////////////////////////////////////////////////////////////////
162    /**********************DELETE FOR WORKSHOP***************************/
163   
164//Pseudocode for workshop users:
165//1) Instantiate a "Macframe" that will be an acknowledgement packet
166//2) Instantiate a variable to keep track of the receiver's state. Default this state variable to "INCOMPLETE"
167//3) Check the "pktType" of the "phyHeader" of the received "Macframe"
168//If "HOPPACKET"
169//      4) Animate the top two LEDs using the "warpmac_incrementLEDHigh" function
170//      5) Switch to the channel located in "packet->header.reserved1" using the "warpphy_setChannel" function (make sure to stay in "GHZ_2")
171//If "DATAPACKET"
172//      4) Check and make sure it was addressed to me with "warpmac_addressedToMe"
173//      5) Set the acknowledgment "Macframe" to length 0 (Header only... no payload)
174//      6) Set the "pktType" of the "phyHeader" of the acknowledgment "Macframe" to "ACKPACKET"
175//      7) Set full rate modulation order to "QPSK"
176//      8) Set the coding rate to "CODE_RATE_34"
177//****Note: Header-only packets (like ACKs) will be QPSK with a rate 1/2 code. Thus, steps 7 and 8 aren't strictly necessary, they are just a safety measure to ensure the PHY
178//doesn't receive an unexpected value in this field
179//      9) memcpy the 6 bytes of "myAddr" into the "srcAddr" field of the acknowledgment
180//      10) 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)
181//      11) Copy the acknowledgement over to packet buffer 2 using the "warpmac_prepPhyForXmit" function
182//      12) Poll the state of the state of the receiver using "warpphy_pollRxStatus." Block until the state turns to either "GOODPACKET" or "BADPACKET"
183//      If "GOODPACKET"
184//          13) Send the acknowledgment sitting in packet buffer 2 using the "warpmac_startPhyXmit"
185//              Note: Since we have pre-loaded the acknowledgment into the PHY transmitter, the ACK will go over-the-air within 20 microseconds
186//                    after the source transmitter finished
187//          14) Animate the top two LEDs to visualize this behavior using the "warpmac_incrementLEDHigh" function
188//          15) Copy the received "Macframe" to Ethernet using "warpmac_prepEmacForXmit"   
189//          16) Start the Emac using "warpmac_startEmacXmit"
190//      If "BADPACKET"
191//          13) Animate the bottom two LEDs to visualize this behavior using the "warpmac_incrementLEDLow" function
192   
193    /**********************DELETE FOR WORKSHOP***************************/
194    Macframe ackPacket;
195    unsigned char state=INCOMPLETE;
196   
197    if(packet->header.pktType==HOPPACKET){
198        //If HOPPACKET is received, jump to the channel in reserved1 of header
199        warpmac_incrementLEDHigh();
200        warpphy_setChannel(GHZ_2,packet->header.reserved1);
201        chan = packet->header.reserved1;
202        warpmac_leftHex(chan);
203    }
204   
205   
206    if(packet->header.pktType==DATAPACKET){
207       
208        if(warpmac_addressedToMe(packet)){
209           
210           
211            ackPacket.header.length = 0;
212            ackPacket.header.pktType = ACKPACKET;
213            ackPacket.header.fullRate = HDR_FULLRATE_QPSK;
214            ackPacket.header.codeRate = CODE_RATE_34;
215            memcpy(ackPacket.header.srcAddr,(unsigned char *)myAddr,6);
216            memcpy(ackPacket.header.destAddr,packet->header.srcAddr,6);
217           
218            //Copy the header over to packet buffer 2
219            warpmac_prepPhyForXmit(&ackPacket,2);
220           
221           
222            while(state==INCOMPLETE){
223                //Blocks until the PHY reports the received packet as either good or bad
224                state = warpphy_pollRxStatus();
225            }
226           
227            if(state==GOODPACKET){
228                //Send packet buffer 2
229                warpmac_startPhyXmit(2);
230                warpmac_incrementLEDHigh();
231                //Starts the DMA transfer of the payload into the EMAC
232                warpmac_prepEmacForXmit(packet);
233                //Blocks until the PHY is finished sending and enables the receiver
234                warpmac_finishPhyXmit();
235                //Waits until the DMA transfer is complete, then starts the EMAC
236                warpmac_startEmacXmit(packet);
237               
238            }
239           
240            if(state==BADPACKET){
241                //xil_printf("BAD Packet, good header\r\n");
242                warpmac_incrementLEDLow();
243            }
244           
245        }
246       
247    }
248    /**********************DELETE FOR WORKSHOP***************************/
249}
250
251///@brief Main function
252///
253///This function configures MAC parameters, enables the underlying frameworks, and then loops forever.
254int main(){     
255    xil_printf("Hopmac Client\r\n");
256    //Initialize the framework
257    warpmac_init();
258   
259    chan = 1;
260   
261    //Read Dip Switch value from FPGA board.
262    //This value will be used as an index into the routing table for other nodes
263    myID = warpmac_getMyId();
264   
265    //Create an arbitrary address for this node
266    unsigned char tmpAddr[6] = {0x16,0x24,0x63,0x53,0xe2,0xc2+myID};
267   
268   
269    memcpy((unsigned char *)myAddr,(unsigned char *)tmpAddr,6);
270   
271    //Fill an arbitrary routing table so that nodes know each others' addresses
272    unsigned char i;
273    for(i=0;i<16;i++){
274        routeTable[i].addr[0] = myAddr[0];
275        routeTable[i].addr[1] = myAddr[1];
276        routeTable[i].addr[2] = myAddr[2];
277        routeTable[i].addr[3] = myAddr[3];
278        routeTable[i].addr[4] = myAddr[4];
279        routeTable[i].addr[5] = myAddr[5]+i-myID;
280    }
281   
282    warpmac_setMacAddr((unsigned char *)(&myAddr));
283   
284   
285    warpmac_setRxBuffer(&rxBuffer,0);
286    //Tx buffer is where the EMAC will DMA payloads to
287    warpmac_setTxBuffer(1);
288   
289    //Copy this node's MAC address into the Tx buffer's source address field
290    memcpy(txBuffer.header.srcAddr,(unsigned char *)myAddr,6);
291   
292    warpmac_setBadHeaderCallback((void *)phyRx_badHeader_callback);
293    warpmac_setGoodHeaderCallback((void *)phyRx_goodHeader_callback);
294    warpmac_setEmacCallback((void *)emacRx_callback);
295   
296   
297    /////////////////////SEEK MODE: OPTIONAL EXTENSION//////////////////////////
298    warpmac_setMiddleButtonCallback(middle);
299    warpmac_setUpButtonCallback(up);
300    warpmac_setLeftButtonCallback(left);
301    warpmac_setRightButtonCallback(right);
302    warpmac_setTimerCallback((void *)timerExpire);
303    warpmac_setTimerVal(waitTime*40000);
304    warpmac_startTimer(DISABLECSMA);
305    /////////////////////////////////////////////////////////////////////////////
306   
307   
308    //Set the default center frequency
309    warpphy_setChannel(GHZ_2, chan);
310   
311    warpmac_enableCSMA();
312    warpmac_enableEthernet();
313   
314    //Set the modulation scheme use for base rate (header) symbols
315    warpmac_setBaseRate(QPSK);
316   
317    while(1){
318        warpmac_pollEthernet();
319    }
320   
321    return;
322}
Note: See TracBrowser for help on using the repository browser.