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 | |
---|
53 | Macframe templatePkt; |
---|
54 | |
---|
55 | unsigned int autoResp_matchCond; |
---|
56 | unsigned int autoResp_action; |
---|
57 | unsigned int autoResp_delay; |
---|
58 | unsigned char pktBuf_tx_ACK; |
---|
59 | unsigned char pktBuf_tx_DATA; |
---|
60 | unsigned char pktBuf_rx; |
---|
61 | |
---|
62 | //Global variables to for user I/O board outputs |
---|
63 | unsigned char userIOBoard_LEDs; |
---|
64 | unsigned char charsToPrint[16]; |
---|
65 | unsigned int pktCount_good, pktCount_bad; |
---|
66 | |
---|
67 | //Arrays to track pkt sequence numbers for each partner node |
---|
68 | unsigned char rxSequences[16]; |
---|
69 | unsigned char txSequences[16]; |
---|
70 | |
---|
71 | unsigned char maximumReSend; |
---|
72 | |
---|
73 | ///MAC address table with agreed upon mapping between dipswitches and physical addresses |
---|
74 | typedef struct { |
---|
75 | unsigned char addr[6]; |
---|
76 | } nodeAddr; |
---|
77 | |
---|
78 | |
---|
79 | ///Byte array containing physical MAC address of this node |
---|
80 | unsigned char myAddr[6]; |
---|
81 | ///Index to the routing table that identifies this node |
---|
82 | unsigned short int myID; |
---|
83 | |
---|
84 | ///Full rate modulation selection; QPSK by default |
---|
85 | unsigned int pktFullRate; |
---|
86 | |
---|
87 | //Payload code rate selection; must be CODE_RATE_NONE for uncoded PHY |
---|
88 | unsigned int pktCodeRate; |
---|
89 | |
---|
90 | ///Buffer for holding a packet-to-xmit across multiple retransmissions |
---|
91 | Macframe txBuffer; |
---|
92 | ///Buffer to hold received packet |
---|
93 | Macframe rxBuffer; |
---|
94 | |
---|
95 | ///Current antenna selection |
---|
96 | unsigned char currentAnt; |
---|
97 | ///Current 802.11 channel |
---|
98 | unsigned 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 |
---|
115 | unsigned char rxSequences[16]; |
---|
116 | unsigned char txSequences[16]; |
---|
117 | |
---|
118 | //Variables used by other commands |
---|
119 | unsigned char sendStats; |
---|
120 | char sendcallbackpacket; |
---|
121 | |
---|
122 | |
---|
123 | ///Global Structs |
---|
124 | warpnetEthernetPktHeader txEthPktHeader; |
---|
125 | warpnodeID myNodeID; |
---|
126 | warpnodeCommand myNodeCmd; |
---|
127 | |
---|
128 | ///Global Stat Struct |
---|
129 | warpnodeStats myStats[WARPNET_NUMNODES]; |
---|
130 | |
---|
131 | ///Place holder for TRANSMIT or RECEIVE state |
---|
132 | unsigned char Mode; |
---|
133 | |
---|
134 | ///Measures time for beginning and end of transmission |
---|
135 | XTime start_timer, end_timer; |
---|
136 | |
---|
137 | unsigned int pktCount_good, pktCount_bad; |
---|
138 | |
---|
139 | ///Parameters used for warpmac_startPacketGeneration |
---|
140 | unsigned int Time; |
---|
141 | unsigned 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 |
---|
149 | void 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 |
---|
188 | void 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 |
---|
234 | void 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 |
---|
298 | void left(){ |
---|
299 | } |
---|
300 | |
---|
301 | ///@brief Callback for the depression of the right push button |
---|
302 | /// |
---|
303 | ///This button switched between different fullrate modulation orders |
---|
304 | void 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 |
---|
328 | void 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 |
---|
341 | void 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. |
---|
357 | void 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. |
---|
376 | void 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 |
---|
476 | void 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 |
---|
515 | void 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 |
---|
784 | void 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 |
---|
841 | void 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 |
---|
864 | void 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. |
---|
983 | int 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 | } |
---|