source: firmware/openos/openwsn/02a-MAC/IEEE802154E.c @ 1164

Revision 1164, 50.3 KB checked in by thomas, 21 months ago (diff)

selecting the neighbor to sync with is done before calling the synchronize* functions. Partically fixes #92.

Line 
1#include "openwsn.h"
2#include "IEEE802154E.h"
3#include "radio.h"
4#include "ieee154etimer.h"
5#include "IEEE802154.h"
6#include "openqueue.h"
7#include "idmanager.h"
8#include "openserial.h"
9#include "schedule.h"
10#include "packetfunctions.h"
11#include "scheduler.h"
12#include "leds.h"
13#include "neighbors.h"
14
15//=========================== variables =======================================
16
17typedef struct {
18   // misc
19   asn_t              asn;                  // current absolute slot number
20   uint16_t           deSyncTimeout;        // how many slots left before looses sync
21   bool               isSync;               // TRUE iff mote is synchronized to network
22   // as shown on the chronogram
23   uint8_t            state;                // state of the FSM
24   OpenQueueEntry_t*  dataToSend;           // pointer to the data to send
25   OpenQueueEntry_t*  dataReceived;         // pointer to the data received
26   OpenQueueEntry_t*  ackToSend;            // pointer to the ack to send
27   OpenQueueEntry_t*  ackReceived;          // pointer to the ack received
28   uint16_t           lastCapturedTime;     // last captured time
29   uint16_t           syncCapturedTime;     // captured time used to sync
30} ieee154e_vars_t;
31
32ieee154e_vars_t ieee154e_vars;
33
34// these statistics are reset every time they are reported
35typedef struct {
36   uint8_t            syncCounter;          // how many times we synchronized
37   int16_t            minCorrection;        // minimum time correction
38   int16_t            maxCorrection;        // maximum time correction
39   uint8_t            numDeSync;            // number of times a desync happened
40} ieee154e_stats_t;
41
42ieee154e_stats_t ieee154e_stats;
43
44//=========================== prototypes ======================================
45
46// SYNCHRONIZING
47void     activity_synchronize_newSlot();
48void     activity_synchronize_startOfFrame(uint16_t capturedTime);
49void     activity_synchronize_endOfFrame(uint16_t capturedTime);
50// TX
51void     activity_ti1ORri1();
52void     activity_ti2();
53void     activity_tie1();
54void     activity_ti3();
55void     activity_tie2();
56void     activity_ti4(uint16_t capturedTime);
57void     activity_tie3();
58void     activity_ti5(uint16_t capturedTime);
59void     activity_ti6();
60void     activity_tie4();
61void     activity_ti7();
62void     activity_tie5();
63void     activity_ti8(uint16_t capturedTime);
64void     activity_tie6();
65void     activity_ti9(uint16_t capturedTime);
66// RX
67void     activity_ri2();
68void     activity_rie1();
69void     activity_ri3();
70void     activity_rie2();
71void     activity_ri4(uint16_t capturedTime);
72void     activity_rie3();
73void     activity_ri5(uint16_t capturedTime);
74void     activity_ri6();
75void     activity_rie4();
76void     activity_ri7();
77void     activity_rie5();
78void     activity_ri8(uint16_t capturedTime);
79void     activity_rie6();
80void     activity_ri9(uint16_t capturedTime);
81// frame validity check
82bool     isValidAdv(ieee802154_header_iht*     ieee802514_header);
83bool     isValidRxFrame(ieee802154_header_iht* ieee802514_header);
84bool     isValidAck(ieee802154_header_iht*     ieee802514_header,
85                    OpenQueueEntry_t*          packetSent);
86// ASN handling
87void     asnWrite(OpenQueueEntry_t* advFrame);
88uint16_t asnRead (OpenQueueEntry_t* advFrame);
89// synchronization
90void     synchronizePacket(uint16_t timeReceived);
91void     synchronizeAck(int16_t timeCorrection);
92void     changeIsSync(bool newIsSync);
93// notifying upper layer
94void     notif_sendDone(OpenQueueEntry_t* packetSent, error_t error);
95void     notif_receive(OpenQueueEntry_t* packetReceived);
96// statistics
97void     resetStats();
98void     updateStats(int16_t timeCorrection);
99// misc
100uint8_t  calculateFrequency(asn_t asn, uint8_t channelOffset);
101void     changeState(uint8_t newstate);
102void     endSlot();
103bool     debugPrint_asn();
104bool     debugPrint_isSync();
105
106//=========================== admin ===========================================
107
108/**
109\brief This function initializes this module.
110
111Call this function once before any other function in this module, possibly
112during boot-up.
113*/
114void mac_init() {   
115   // initialize debug pins
116   DEBUG_PIN_FRAME_INIT();
117   DEBUG_PIN_SLOT_INIT();
118   DEBUG_PIN_FSM_INIT();
119   
120   // initialize variables
121   ieee154e_vars.asn                        = 0;
122   ieee154e_vars.deSyncTimeout              = 0;
123   if (idmanager_getIsDAGroot()==TRUE) {
124      changeIsSync(TRUE);
125   } else {
126      changeIsSync(FALSE);
127   }
128   ieee154e_vars.state                      = S_SLEEP;
129   ieee154e_vars.dataToSend                 = NULL;
130   ieee154e_vars.dataReceived               = NULL;
131   ieee154e_vars.ackToSend                  = NULL;
132   ieee154e_vars.ackReceived                = NULL;
133   ieee154e_vars.lastCapturedTime           = 0;
134   ieee154e_vars.syncCapturedTime           = 0;
135   
136   resetStats();
137   ieee154e_stats.numDeSync                 = 0;
138   
139   // initialize (and start) IEEE802.15.4e timer
140   ieee154etimer_init();
141}
142
143//=========================== public ==========================================
144
145__monitor asn_t ieee154e_getAsn() {
146   return ieee154e_vars.asn;
147}
148
149//======= events
150
151/**
152\brief Indicates a new slot has just started.
153
154This function executes in ISR mode, when the new slot timer fires.
155*/
156void isr_ieee154e_newSlot() {
157   TACCR0 =  TsSlotDuration;
158   if (ieee154e_vars.isSync==FALSE) {
159      activity_synchronize_newSlot();
160   } else {
161      activity_ti1ORri1();
162   }
163}
164
165/**
166\brief Indicates the FSM timer has fired.
167
168This function executes in ISR mode, when the FSM timer fires.
169*/
170void isr_ieee154e_timer() {
171   switch (ieee154e_vars.state) {
172      case S_TXDATAOFFSET:
173         activity_ti2();
174         break;
175      case S_TXDATAPREPARE:
176         activity_tie1();
177         break;
178      case S_TXDATAREADY:
179         activity_ti3();
180         break;
181      case S_TXDATADELAY:
182         activity_tie2();
183         break;
184      case S_TXDATA:
185         activity_tie3();
186         break;
187      case S_RXACKOFFSET:
188         activity_ti6();
189         break;
190      case S_RXACKPREPARE:
191         activity_tie4();
192         break;
193      case S_RXACKREADY:
194         activity_ti7();
195         break;
196      case S_RXACKLISTEN:
197         activity_tie5();
198         break;
199      case S_RXACK:
200         activity_tie6();
201         break;
202      case S_RXDATAOFFSET:
203         activity_ri2();
204         break;
205      case S_RXDATAPREPARE:
206         activity_rie1();
207         break;
208      case S_RXDATAREADY:
209         activity_ri3();
210         break;
211      case S_RXDATALISTEN:
212         activity_rie2();
213         break;
214      case S_RXDATA:
215         activity_rie3();
216         break;
217      case S_TXACKOFFSET:
218         activity_ri6();
219         break;
220      case S_TXACKPREPARE:
221         activity_rie4();
222         break;
223      case S_TXACKREADY:
224         activity_ri7();
225         break;
226      case S_TXACKDELAY:
227         activity_rie5();
228         break;
229      case S_TXACK:
230         activity_rie6();
231         break;
232      default:
233         // log the error
234         openserial_printError(COMPONENT_IEEE802154E,
235                               ERR_WRONG_STATE_IN_TIMERFIRES,
236                               ieee154e_vars.state,
237                               ieee154e_vars.asn%SCHEDULELENGTH);
238         // abort
239         endSlot();
240         break;
241   }
242}
243
244/**
245\brief Indicates the radio just received the first byte of a packet.
246
247This function executes in ISR mode.
248*/
249void ieee154e_startOfFrame(uint16_t capturedTime) {
250   if (ieee154e_vars.isSync==FALSE) {
251      activity_synchronize_startOfFrame(capturedTime);
252   } else {
253      switch (ieee154e_vars.state) {
254         case S_TXDATADELAY:
255            activity_ti4(capturedTime);
256            break;
257         case S_RXACKLISTEN:
258            activity_ti8(capturedTime);
259            break;
260         case S_RXDATALISTEN:
261            activity_ri4(capturedTime);
262            break;
263         case S_TXACKDELAY:
264            activity_ri8(capturedTime);
265            break;
266         default:
267            // log the error
268            openserial_printError(COMPONENT_IEEE802154E,
269                                  ERR_WRONG_STATE_IN_NEWSLOT,
270                                  ieee154e_vars.state,
271                                  ieee154e_vars.asn%SCHEDULELENGTH);
272            // abort
273            endSlot();
274            break;
275      }
276   }
277}
278
279/**
280\brief Indicates the radio just received the last byte of a packet.
281
282This function executes in ISR mode.
283*/
284void ieee154e_endOfFrame(uint16_t capturedTime) {
285   if (ieee154e_vars.isSync==FALSE) {
286      activity_synchronize_endOfFrame(capturedTime);
287   } else {
288      switch (ieee154e_vars.state) {
289         case S_TXDATA:
290            activity_ti5(capturedTime);
291            break;
292         case S_RXACK:
293            activity_ti9(capturedTime);
294            break;
295         case S_RXDATA:
296            activity_ri5(capturedTime);
297            break;
298         case S_TXACK:
299            activity_ri9(capturedTime);
300            break;
301         default:
302            // log the error
303            openserial_printError(COMPONENT_IEEE802154E,
304                                  ERR_WRONG_STATE_IN_ENDOFFRAME,
305                                  ieee154e_vars.state,
306                                  ieee154e_vars.asn%SCHEDULELENGTH);
307            // abort
308            endSlot();
309            break;
310      }
311   }
312}
313
314//======= misc
315
316bool debugPrint_asn() {
317   uint16_t output=0;
318   output = ieee154e_vars.asn;
319   openserial_printStatus(STATUS_ASN,(uint8_t*)&output,sizeof(uint16_t));
320   return TRUE;
321}
322
323bool debugPrint_isSync() {
324   uint8_t output=0;
325   output = ieee154e_vars.isSync;
326   openserial_printStatus(STATUS_ISSYNC,(uint8_t*)&output,sizeof(uint8_t));
327   return TRUE;
328}
329
330bool debugPrint_macStats() {
331   // send current stats over serial
332   openserial_printStatus(STATUS_MACSTATS,(uint8_t*)&ieee154e_stats,sizeof(ieee154e_stats_t));
333   return TRUE;
334}
335
336//=========================== private =========================================
337
338//======= SYNCHRONIZING
339
340inline void activity_synchronize_newSlot() {
341   // I'm in the middle of receiving a packet
342   if (ieee154e_vars.state==S_SYNCRX) {
343      return;
344   }
345   
346   // if this is the first time I call this function while not synchronized,
347   // switch on the radio in Rx mode
348   if (ieee154e_vars.state!=S_SYNCLISTEN) {
349      // change state
350      changeState(S_SYNCLISTEN);
351     
352      // turn off the radio (in case it wasn't yet)
353      radio_rfOff();
354     
355      // configure the radio to listen to the default synchronizing channel
356      radio_setFrequency(SYNCHRONIZING_CHANNEL);
357     
358      // switch on the radio in Rx mode.
359      radio_rxEnable();
360      radio_rxNow();
361   }
362
363   // we want to be able to receive and transmist serial even when not synchronized
364   // take turns every other slot to send or receive
365   openserial_stop();
366   if (ieee154e_vars.asn%2==0) {
367      openserial_startOutput();
368   } else {
369      openserial_startInput();
370   }
371}
372
373inline void activity_synchronize_startOfFrame(uint16_t capturedTime) {
374   
375   // don't care about packet if I'm not listening
376   if (ieee154e_vars.state!=S_SYNCLISTEN) {
377      return;
378   }
379   
380   // change state
381   changeState(S_SYNCRX);
382   
383   // stop the serial
384   openserial_stop();
385   
386   // record the captured time
387   ieee154e_vars.lastCapturedTime = capturedTime;
388   
389   // record the captured time (for sync)
390   ieee154e_vars.syncCapturedTime = capturedTime;
391}
392
393inline void activity_synchronize_endOfFrame(uint16_t capturedTime) {
394   ieee802154_header_iht ieee802514_header;
395   
396   // check state
397   if (ieee154e_vars.state!=S_SYNCRX) {
398      // log the error
399      openserial_printError(COMPONENT_IEEE802154E,
400                            ERR_WRONG_STATE_IN_ENDFRAME_SYNC,
401                            ieee154e_vars.state,
402                            0);
403      // abort
404      endSlot();
405   }
406   
407   // change state
408   changeState(S_SYNCPROC);
409   
410   // get a buffer to put the (received) frame in
411   ieee154e_vars.dataReceived = openqueue_getFreePacketBuffer();
412   if (ieee154e_vars.dataReceived==NULL) {
413      // log the error
414      openserial_printError(COMPONENT_IEEE802154E,
415                            ERR_NO_FREE_PACKET_BUFFER,
416                            0,
417                            0);
418      // abort
419      endSlot();
420      return;
421   }
422   
423   // declare ownership over that packet
424   ieee154e_vars.dataReceived->creator = COMPONENT_IEEE802154E;
425   ieee154e_vars.dataReceived->owner   = COMPONENT_IEEE802154E;
426   
427   // retrieve the received data frame from the radio's Rx buffer
428   radio_getReceivedFrame(ieee154e_vars.dataReceived);
429   
430   /*
431   The do-while loop that follows is a little parsing trick.
432   Because it contains a while(0) condition, it gets executed only once.
433   The behavior is:
434   - if a break occurs inside the do{} body, the error code below the loop
435     gets executed. This indicates something is wrong with the packet being
436     parsed.
437   - if a return occurs inside the do{} body, the error code below the loop
438     does not get executed. This indicates the received packet is correct.
439   */
440   do { // this "loop" is only executed once
441     
442      // break if invalid CRC
443      if (ieee154e_vars.dataReceived->l1_crc==FALSE) {
444         // break from the do-while loop and execute abort code below
445         break;
446      }
447     
448      // parse the IEEE802.15.4 header
449      ieee802154_retrieveHeader(ieee154e_vars.dataReceived,&ieee802514_header);
450     
451      // store header details in packet buffer
452      ieee154e_vars.dataReceived->l2_frameType = ieee802514_header.frameType;
453      ieee154e_vars.dataReceived->l2_dsn       = ieee802514_header.dsn;
454      memcpy(&(ieee154e_vars.dataReceived->l2_nextORpreviousHop),&(ieee802514_header.src),sizeof(open_addr_t));
455     
456      // toss the IEEE802.15.4 header
457      packetfunctions_tossHeader(ieee154e_vars.dataReceived,ieee802514_header.headerLength);
458     
459      // if I just received a valid ADV, handle
460      if (isValidAdv(&ieee802514_header)==TRUE) {
461         
462         // turn off the radio
463         radio_rfOff();
464         
465         // record the ASN from the ADV payload
466         ieee154e_vars.asn = asnRead(ieee154e_vars.dataReceived);
467         
468         // toss the ADV payload
469         packetfunctions_tossHeader(ieee154e_vars.dataReceived,sizeof(asn_t));
470         
471         // synchronize (for the first time) to the sender's ADV
472         synchronizePacket(ieee154e_vars.syncCapturedTime);
473         
474         // declare synchronized
475         changeIsSync(TRUE);
476         
477         // log the "error"
478         openserial_printError(COMPONENT_IEEE802154E,
479                               ERR_SYNCHRONIZED,
480                               ieee154e_vars.asn,
481                               0);
482         
483         // send received ADV up the stack so RES can update statistics (synchronizing)
484         notif_receive(ieee154e_vars.dataReceived);
485         
486         // clear local variable
487         ieee154e_vars.dataReceived = NULL;
488         
489         // official end of synchronization
490         endSlot();
491         
492         // everything went well, return here not to execute the error code below
493         return;
494      }
495   } while (0);
496   
497   // free the (invalid) received data buffer so RAM memory can be recycled
498   openqueue_freePacketBuffer(ieee154e_vars.dataReceived);
499   
500   // clear local variable
501   ieee154e_vars.dataReceived = NULL;
502}
503
504//======= TX
505
506inline void activity_ti1ORri1() {
507   uint8_t cellType;
508   open_addr_t neighbor;
509   
510   // stop outputting serial data
511   openserial_stop();
512   
513   // increment ASN (do this first so debug pins are in sync)
514   ieee154e_vars.asn++;
515   
516   // wiggle debug pins
517   DEBUG_PIN_SLOT_TOGGLE();
518   if (ieee154e_vars.asn%SCHEDULELENGTH==0) {
519      DEBUG_PIN_FRAME_TOGGLE();
520   }
521   
522   // desynchronize if needed
523   if (idmanager_getIsDAGroot()==FALSE) {
524      ieee154e_vars.deSyncTimeout--;
525      if (ieee154e_vars.deSyncTimeout==0) {
526         // declare myself desynchronized
527         changeIsSync(FALSE);
528         
529         // log the error
530         openserial_printError(COMPONENT_IEEE802154E,
531                               ERR_DESYNCHRONIZED,
532                               ieee154e_vars.asn,
533                               0);
534           
535         // update the statistics
536         ieee154e_stats.numDeSync++;
537           
538         // abort
539         endSlot();
540         return;
541      }
542   }
543
544   // if the previous slot took too long, we will not be in the right state
545   if (ieee154e_vars.state!=S_SLEEP) {
546      // log the error
547      openserial_printError(COMPONENT_IEEE802154E,
548                            ERR_WRONG_STATE_IN_STARTSLOT,
549                            ieee154e_vars.state,
550                            ieee154e_vars.asn%SCHEDULELENGTH);
551      // abort
552      endSlot();
553      return;
554   }
555
556   // check the schedule to see what type of slot this is
557   cellType = schedule_getType(ieee154e_vars.asn);
558   switch (cellType) {
559      case CELLTYPE_OFF:
560         // I have nothing to do
561         // abort
562         endSlot();
563         //start outputing serial
564         openserial_startOutput();
565         break;
566      case CELLTYPE_ADV:
567         ieee154e_vars.dataToSend = openqueue_macGetAdvPacket();
568         if (ieee154e_vars.dataToSend==NULL) {   // I will be listening for an ADV
569            // change state
570            changeState(S_RXDATAOFFSET);
571            // arm rt1
572            ieee154etimer_schedule(DURATION_rt1);
573         } else {                                // I will be sending an ADV
574            // change state
575            changeState(S_TXDATAOFFSET);
576            // change owner
577            ieee154e_vars.dataToSend->owner = COMPONENT_IEEE802154E;
578            // fill in the ASN field of the ADV
579            asnWrite(ieee154e_vars.dataToSend);
580            // record that I attempt to transmit this packet
581            ieee154e_vars.dataToSend->l2_numTxAttempts++;
582            // arm tt1
583            ieee154etimer_schedule(DURATION_tt1);
584         }
585         break;
586      case CELLTYPE_TX:
587         schedule_getNeighbor(ieee154e_vars.asn,&neighbor);
588         ieee154e_vars.dataToSend = openqueue_macGetDataPacket(&neighbor);
589         if (ieee154e_vars.dataToSend!=NULL) {   // I have a packet to send
590            // change state
591            changeState(S_TXDATAOFFSET);
592            // change owner
593            ieee154e_vars.dataToSend->owner = COMPONENT_IEEE802154E;
594            // record that I attempt to transmit this packet
595            ieee154e_vars.dataToSend->l2_numTxAttempts++;
596            // arm tt1
597            ieee154etimer_schedule(DURATION_tt1);
598         } else {
599            // abort
600            endSlot();
601         }
602         break;
603      case CELLTYPE_RX:
604         // I need to listen for packet
605         // change state
606         changeState(S_RXDATAOFFSET);
607         // arm rt1
608         ieee154etimer_schedule(DURATION_rt1);
609         break;
610      case CELLTYPE_SERIALRX:
611         // TODO
612         break;
613      default:
614         // log the error
615         openserial_printError(COMPONENT_IEEE802154E,
616                               ERR_WRONG_CELLTYPE,
617                               cellType,
618                               ieee154e_vars.asn%SCHEDULELENGTH);
619         // abort
620         endSlot();
621         break;
622   }
623}
624
625inline void activity_ti2() {
626   uint8_t frequency;
627   
628   // change state
629   changeState(S_TXDATAPREPARE);
630
631   // calculate the frequency to transmit on
632   frequency = calculateFrequency(ieee154e_vars.asn, schedule_getChannelOffset(ieee154e_vars.asn) );
633
634   // configure the radio for that frequency
635   radio_setFrequency(frequency);
636
637   // load the packet in the radio's Tx buffer
638   radio_loadPacket(ieee154e_vars.dataToSend);
639
640   // enable the radio in Tx mode. This does not send the packet.
641   radio_txEnable();
642
643   // arm tt2
644   ieee154etimer_schedule(DURATION_tt2);
645
646   // change state
647   changeState(S_TXDATAREADY);
648}
649
650inline void activity_tie1() {
651   // log the error
652   openserial_printError(COMPONENT_IEEE802154E,
653                         ERR_MAXTXDATAPREPARE_OVERFLOW,
654                         ieee154e_vars.state,
655                         ieee154e_vars.asn%SCHEDULELENGTH);
656
657   // abort
658   endSlot();
659}
660
661inline void activity_ti3() {
662   // change state
663   changeState(S_TXDATADELAY);
664   
665   // arm tt3
666   ieee154etimer_schedule(DURATION_tt3);
667   
668   // give the 'go' to transmit
669   radio_txNow();
670}
671
672inline void activity_tie2() {
673   // log the error
674   openserial_printError(COMPONENT_IEEE802154E,
675                         ERR_WDRADIO_OVERFLOW,
676                         ieee154e_vars.state,
677                         ieee154e_vars.asn%SCHEDULELENGTH);
678
679   // abort
680   endSlot();
681}
682
683inline void activity_ti4(uint16_t capturedTime) {
684   // change state
685   changeState(S_TXDATA);
686
687   // cancel tt3
688   ieee154etimer_cancel();
689
690   // record the captured time
691   ieee154e_vars.lastCapturedTime = capturedTime;
692   
693   // arm tt4
694   ieee154etimer_schedule(DURATION_tt4);
695}
696
697inline void activity_tie3() {
698   // log the error
699   openserial_printError(COMPONENT_IEEE802154E,
700                         ERR_WDDATADURATION_OVERFLOWS,
701                         ieee154e_vars.state,
702                         ieee154e_vars.asn%SCHEDULELENGTH);
703
704   // abort
705   endSlot();
706}
707
708inline void activity_ti5(uint16_t capturedTime) {
709   bool listenForAck;
710   
711   // change state
712   changeState(S_RXACKOFFSET);
713   
714   // cancel tt4
715   ieee154etimer_cancel();
716   
717   // turn off the radio
718   radio_rfOff();
719
720   // record the captured time
721   ieee154e_vars.lastCapturedTime = capturedTime;
722
723   // decides whether to listen for an ACK
724   if (packetfunctions_isBroadcastMulticast(&ieee154e_vars.dataToSend->l2_nextORpreviousHop)==TRUE) {
725      listenForAck = FALSE;
726   } else {
727      listenForAck = TRUE;
728   }
729
730   if (listenForAck==TRUE) {
731      // arm tt5
732      ieee154etimer_schedule(DURATION_tt5);
733   } else {
734      // indicate that the packet was sent successfully
735      notif_sendDone(ieee154e_vars.dataToSend,E_SUCCESS);
736      // reset local variable
737      ieee154e_vars.dataToSend = NULL;
738      // abort
739      endSlot();
740   }
741}
742
743inline void activity_ti6() {
744   uint8_t frequency;
745   
746   // change state
747   changeState(S_RXACKPREPARE);
748
749   // calculate the frequency to transmit on
750   frequency = calculateFrequency(ieee154e_vars.asn, schedule_getChannelOffset(ieee154e_vars.asn));
751
752   // configure the radio for that frequency
753   radio_setFrequency(frequency);
754
755   // enable the radio in Rx mode. The radio is not actively listening yet.
756   radio_rxEnable();
757
758   // arm tt6
759   ieee154etimer_schedule(DURATION_tt6);
760   
761   // change state
762   changeState(S_RXACKREADY);
763}
764
765inline void activity_tie4() {
766   // log the error
767   openserial_printError(COMPONENT_IEEE802154E,
768                         ERR_MAXRXACKPREPARE_OVERFLOWS,
769                         ieee154e_vars.state,
770                         ieee154e_vars.asn%SCHEDULELENGTH);
771
772   // abort
773   endSlot();
774}
775
776inline void activity_ti7() {
777   // change state
778   changeState(S_RXACKLISTEN);
779
780   // start listening
781   radio_rxNow();
782
783   // arm tt7
784   ieee154etimer_schedule(DURATION_tt7);
785}
786
787inline void activity_tie5() {
788   // transmit failed, decrement transmits left counter
789   ieee154e_vars.dataToSend->l2_retriesLeft--;
790
791   if (ieee154e_vars.dataToSend->l2_retriesLeft==0) {
792      // indicate tx fail if no more retries left
793      notif_sendDone(ieee154e_vars.dataToSend,E_FAIL);
794   } else {
795      // return packet to the virtual COMPONENT_RES_TO_IEEE802154E component
796      ieee154e_vars.dataToSend->owner = COMPONENT_RES_TO_IEEE802154E;
797   }
798
799   // reset local variable
800   ieee154e_vars.dataToSend = NULL;
801
802   // abort
803   endSlot();
804}
805
806inline void activity_ti8(uint16_t capturedTime) {
807   // change state
808   changeState(S_RXACK);
809   
810   // cancel tt7
811   ieee154etimer_cancel();
812
813   // record the captured time
814   ieee154e_vars.lastCapturedTime = capturedTime;
815
816   // arm tt8
817   ieee154etimer_schedule(DURATION_tt8);
818}
819
820inline void activity_tie6() {
821   // abort
822   endSlot();
823}
824
825inline void activity_ti9(uint16_t capturedTime) {
826   ieee802154_header_iht ieee802514_header;
827   volatile int16_t  timeCorrection;
828   
829   // change state
830   changeState(S_TXPROC);
831   
832   // cancel tt8
833   ieee154etimer_cancel();
834   
835   // turn off the radio
836   radio_rfOff();
837
838   // record the captured time
839   ieee154e_vars.lastCapturedTime = capturedTime;
840   
841   // get a buffer to put the (received) ACK in
842   ieee154e_vars.ackReceived = openqueue_getFreePacketBuffer();
843   if (ieee154e_vars.ackReceived==NULL) {
844      // log the error
845      openserial_printError(COMPONENT_IEEE802154E,
846                            ERR_NO_FREE_PACKET_BUFFER,
847                            0,
848                            0);
849      // abort
850      endSlot();
851      return;
852   }
853   
854   // declare ownership over that packet
855   ieee154e_vars.ackReceived->creator = COMPONENT_IEEE802154E;
856   ieee154e_vars.ackReceived->owner   = COMPONENT_IEEE802154E;
857   
858   // retrieve the received ack frame from the radio's Rx buffer
859   radio_getReceivedFrame(ieee154e_vars.ackReceived);
860   
861   /*
862   The do-while loop that follows is a little parsing trick.
863   Because it contains a while(0) condition, it gets executed only once.
864   Below the do-while loop is some code to cleans up the ack variable.
865   Anywhere in the do-while loop, a break statement can be called to jump to
866   the clean up code early. If the loop ends without a break, the received
867   packet was correct. If it got aborted early (through a break), the packet
868   was faulty.
869   */
870   do { // this "loop" is only executed once
871     
872      // break if invalid CRC
873      if (ieee154e_vars.ackReceived->l1_crc==FALSE) {
874         // break from the do-while loop and execute the clean-up code below
875         break;
876      }
877     
878      // parse the IEEE802.15.4 header
879      ieee802154_retrieveHeader(ieee154e_vars.ackReceived,&ieee802514_header);
880     
881      // store header details in packet buffer
882      ieee154e_vars.ackReceived->l2_frameType  = ieee802514_header.frameType;
883      ieee154e_vars.ackReceived->l2_dsn        = ieee802514_header.dsn;
884      memcpy(&(ieee154e_vars.ackReceived->l2_nextORpreviousHop),&(ieee802514_header.src),sizeof(open_addr_t));
885     
886      // toss the IEEE802.15.4 header
887      packetfunctions_tossHeader(ieee154e_vars.ackReceived,ieee802514_header.headerLength);
888     
889      // if frame is a valid ACK, handle
890      if (isValidAck(&ieee802514_header,ieee154e_vars.dataToSend)==TRUE) {
891         
892         // resynchronize if I'm not a DAGroot and ACK from preferred parent
893         if (idmanager_getIsDAGroot()==FALSE &&
894             neighbors_isPreferredParent(&(ieee154e_vars.ackReceived->l2_nextORpreviousHop)) ) {
895            timeCorrection = (int16_t)(ieee154e_vars.ackReceived->payload[1]<<8 | ieee154e_vars.ackReceived->payload[0]);
896            synchronizeAck(timeCorrection);
897         }
898         
899         // inform upper layer
900         notif_sendDone(ieee154e_vars.dataToSend,E_SUCCESS);
901         ieee154e_vars.dataToSend = NULL;
902      }
903     
904      // in any case, execute the clean-up code below
905   } while (0);
906   
907   // free the received ack so corresponding RAM memory can be recycled
908   openqueue_freePacketBuffer(ieee154e_vars.ackReceived);
909   
910   // clear local variable
911   ieee154e_vars.ackReceived = NULL;
912
913   // official end of Tx slot
914   endSlot();
915}
916
917//======= RX
918
919inline void activity_ri2() {
920   uint8_t frequency;
921   
922   // change state
923   changeState(S_RXDATAPREPARE);
924
925   // calculate the frequency to transmit on
926   frequency = calculateFrequency(ieee154e_vars.asn, schedule_getChannelOffset(ieee154e_vars.asn) );
927
928   // configure the radio for that frequency
929   radio_setFrequency(frequency);
930
931   // enable the radio in Rx mode. The radio does not actively listen yet.
932   radio_rxEnable();
933
934   // arm rt2
935   ieee154etimer_schedule(DURATION_rt2);
936
937   // change state
938   changeState(S_RXDATAREADY);
939}
940
941inline void activity_rie1() {
942   // log the error
943   openserial_printError(COMPONENT_IEEE802154E,
944                         ERR_MAXRXDATAPREPARE_OVERFLOWS,
945                         ieee154e_vars.state,
946                         ieee154e_vars.asn%SCHEDULELENGTH);
947
948   // abort
949   endSlot();
950}
951
952inline void activity_ri3() {
953   // change state
954   changeState(S_RXDATALISTEN);
955
956   // give the 'go' to receive
957   radio_rxNow();
958
959   // arm rt3
960   ieee154etimer_schedule(DURATION_rt3);
961}
962
963inline void activity_rie2() {
964   // abort
965   endSlot();
966}
967
968inline void activity_ri4(uint16_t capturedTime) {
969   // change state
970   changeState(S_RXDATA);
971   
972   // cancel rt3
973   ieee154etimer_cancel();
974
975   // record the captured time
976   ieee154e_vars.lastCapturedTime = capturedTime;
977   
978   // record the captured time to sync
979   ieee154e_vars.syncCapturedTime = capturedTime;
980
981   // arm rt4
982   ieee154etimer_schedule(DURATION_rt4);
983}
984
985inline void activity_rie3() {
986   // log the error
987   openserial_printError(COMPONENT_IEEE802154E,
988                         ERR_WDDATADURATION_OVERFLOWS,
989                         ieee154e_vars.state,
990                         ieee154e_vars.asn%SCHEDULELENGTH);
991   
992   // abort
993   endSlot();
994}
995
996inline void activity_ri5(uint16_t capturedTime) {
997   ieee802154_header_iht ieee802514_header;
998   
999   // change state
1000   changeState(S_TXACKOFFSET);
1001   
1002   // cancel rt4
1003   ieee154etimer_cancel();
1004   
1005   // turn off the radio
1006   radio_rfOff();
1007   
1008   // get a buffer to put the (received) data in
1009   ieee154e_vars.dataReceived = openqueue_getFreePacketBuffer();
1010   if (ieee154e_vars.dataReceived==NULL) {
1011      // log the error
1012      openserial_printError(COMPONENT_IEEE802154E,
1013                            ERR_NO_FREE_PACKET_BUFFER,
1014                            0,
1015                            0);
1016      // abort
1017      endSlot();
1018      return;
1019   }
1020   
1021   // declare ownership over that packet
1022   ieee154e_vars.dataReceived->creator = COMPONENT_IEEE802154E;
1023   ieee154e_vars.dataReceived->owner   = COMPONENT_IEEE802154E;
1024   
1025   // retrieve the received data frame from the radio's Rx buffer
1026   radio_getReceivedFrame(ieee154e_vars.dataReceived);
1027
1028   /*
1029   The do-while loop that follows is a little parsing trick.
1030   Because it contains a while(0) condition, it gets executed only once.
1031   The behavior is:
1032   - if a break occurs inside the do{} body, the error code below the loop
1033     gets executed. This indicates something is wrong with the packet being
1034     parsed.
1035   - if a return occurs inside the do{} body, the error code below the loop
1036     does not get executed. This indicates the received packet is correct.
1037   */
1038   do { // this "loop" is only executed once
1039     
1040      // if CRC doesn't check, stop
1041      if (ieee154e_vars.dataReceived->l1_crc==FALSE) {
1042         // jump to the error code below this do-while loop
1043         break;
1044      }
1045     
1046      // parse the IEEE802.15.4 header
1047      ieee802154_retrieveHeader(ieee154e_vars.dataReceived,&ieee802514_header);
1048     
1049      // store header details in packet buffer
1050      ieee154e_vars.dataReceived->l2_frameType = ieee802514_header.frameType;
1051      ieee154e_vars.dataReceived->l2_dsn       = ieee802514_header.dsn;
1052      memcpy(&(ieee154e_vars.dataReceived->l2_nextORpreviousHop),&(ieee802514_header.src),sizeof(open_addr_t));
1053     
1054      // toss the IEEE802.15.4 header
1055      packetfunctions_tossHeader(ieee154e_vars.dataReceived,ieee802514_header.headerLength);
1056     
1057      // if I just received a valid ADV, record the ASN and toss the payload
1058      if (isValidAdv(&ieee802514_header)==TRUE) {
1059         if (idmanager_getIsDAGroot()==FALSE) {
1060            if (ieee154e_vars.asn != asnRead(ieee154e_vars.dataReceived)) {
1061               // log the error
1062               openserial_printError(COMPONENT_IEEE802154E,
1063                                     ERR_ASN_MISALIGNEMENT,
1064                                     0,
1065                                     0);
1066               // update the ASN to try to recover
1067               ieee154e_vars.asn = asnRead(ieee154e_vars.dataReceived);
1068            };
1069         }
1070         // toss the ADV payload
1071         packetfunctions_tossHeader(ieee154e_vars.dataReceived,sizeof(asn_t));
1072      }
1073     
1074      // record the captured time
1075      ieee154e_vars.lastCapturedTime = capturedTime;
1076     
1077      // if I just received an invalid frame, stop
1078      if (isValidRxFrame(&ieee802514_header)==FALSE) {
1079         // jump to the error code below this do-while loop
1080         break;
1081      }
1082     
1083      // check if ack requested
1084      if (ieee802514_header.ackRequested==1) {
1085         // arm rt5
1086         ieee154etimer_schedule(DURATION_rt5);
1087      } else {
1088         // synchronize to the received packet iif I'm not a DAGroot and this is my preferred parent
1089         if (idmanager_getIsDAGroot()==FALSE && neighbors_isPreferredParent(&(ieee154e_vars.dataReceived->l2_nextORpreviousHop))) {
1090            synchronizePacket(ieee154e_vars.syncCapturedTime);
1091         }
1092         // indicate reception to upper layer (no ACK asked)
1093         notif_receive(ieee154e_vars.dataReceived);
1094         // reset local variable
1095         ieee154e_vars.dataReceived = NULL;
1096         // abort
1097         endSlot();
1098      }
1099     
1100      // everything went well, return here not to execute the error code below
1101      return;
1102     
1103   } while(0);
1104   
1105   // free the (invalid) received data so RAM memory can be recycled
1106   openqueue_freePacketBuffer(ieee154e_vars.dataReceived);
1107   
1108   // clear local variable
1109   ieee154e_vars.dataReceived = NULL;
1110   
1111   // abort
1112   endSlot();
1113}
1114
1115inline void activity_ri6() {
1116   int16_t timeCorrection;
1117   uint8_t frequency;
1118   
1119   // change state
1120   changeState(S_TXACKPREPARE);
1121   
1122   // get a buffer to put the ack to send in
1123   ieee154e_vars.ackToSend = openqueue_getFreePacketBuffer();
1124   if (ieee154e_vars.ackToSend==NULL) {
1125      // log the error
1126      openserial_printError(COMPONENT_IEEE802154E,
1127                            ERR_NO_FREE_PACKET_BUFFER,
1128                            0,
1129                            0);
1130      // indicate we received a packet anyway (we don't want to loose any)
1131      notif_receive(ieee154e_vars.dataReceived);
1132      // free local variable
1133      ieee154e_vars.dataReceived = NULL;
1134      // abort
1135      endSlot();
1136      return;
1137   }
1138   
1139   // declare ownership over that packet
1140   ieee154e_vars.ackToSend->creator = COMPONENT_IEEE802154E;
1141   ieee154e_vars.ackToSend->owner   = COMPONENT_IEEE802154E;
1142   
1143   // calculate the time timeCorrection
1144   timeCorrection = (int16_t)((int16_t)ieee154e_vars.syncCapturedTime-(int16_t)TsTxOffset);
1145   
1146   // add the payload to the ACK (i.e. the timeCorrection)
1147   packetfunctions_reserveHeaderSize(ieee154e_vars.ackToSend,sizeof(IEEE802154E_ACK_ht));
1148   ((IEEE802154E_ACK_ht*)(ieee154e_vars.ackToSend->payload))->timeCorrection[0] = (timeCorrection >> 0) & 0xff;
1149   ((IEEE802154E_ACK_ht*)(ieee154e_vars.ackToSend->payload))->timeCorrection[1] = (timeCorrection >> 8) & 0xff;
1150   
1151   // prepend the IEEE802.15.4 header to the ACK
1152   ieee154e_vars.ackToSend->l2_frameType = IEEE154_TYPE_ACK;
1153   ieee154e_vars.ackToSend->l2_dsn       = ieee154e_vars.dataReceived->l2_dsn;
1154   ieee802154_prependHeader(ieee154e_vars.ackToSend,
1155                            ieee154e_vars.ackToSend->l2_frameType,
1156                            IEEE154_SEC_NO_SECURITY,
1157                            ieee154e_vars.dataReceived->l2_dsn,
1158                            &(ieee154e_vars.dataReceived->l2_nextORpreviousHop)
1159                            );
1160   
1161   // space for 2-byte CRC
1162   packetfunctions_reserveFooterSize(ieee154e_vars.ackToSend,2);
1163   
1164   // calculate the frequency to transmit on
1165   frequency = calculateFrequency(ieee154e_vars.asn, schedule_getChannelOffset(ieee154e_vars.asn) );
1166   
1167   // configure the radio for that frequency
1168   radio_setFrequency(frequency);
1169   
1170   // load the packet in the radio's Tx buffer
1171   radio_loadPacket(ieee154e_vars.ackToSend);
1172   
1173   // enable the radio in Tx mode. This does not send that packet.
1174   radio_txEnable();
1175   
1176   // arm rt6
1177   ieee154etimer_schedule(DURATION_rt6);
1178   
1179   // change state
1180   changeState(S_TXACKREADY);
1181}
1182
1183inline void activity_rie4() {
1184   // log the error
1185   openserial_printError(COMPONENT_IEEE802154E,
1186                         ERR_MAXTXACKPREPARE_OVERFLOWS,
1187                         ieee154e_vars.state,
1188                         ieee154e_vars.asn%SCHEDULELENGTH);
1189   
1190   // abort
1191   endSlot();
1192}
1193
1194inline void activity_ri7() {
1195   // change state
1196   changeState(S_TXACKDELAY);
1197   
1198   // arm rt7
1199   ieee154etimer_schedule(DURATION_rt7);
1200   
1201   // give the 'go' to transmit
1202   radio_txNow();
1203}
1204
1205inline void activity_rie5() {
1206   // log the error
1207   openserial_printError(COMPONENT_IEEE802154E,
1208                         ERR_WDRADIOTX_OVERFLOWS,
1209                         ieee154e_vars.state,
1210                         ieee154e_vars.asn%SCHEDULELENGTH);
1211   
1212   // abort
1213   endSlot();
1214}
1215
1216inline void activity_ri8(uint16_t capturedTime) {
1217   // change state
1218   changeState(S_TXACK);
1219   
1220   // cancel rt7
1221   ieee154etimer_cancel();
1222   
1223   // record the captured time
1224   ieee154e_vars.lastCapturedTime = capturedTime;
1225   
1226   // arm rt8
1227   ieee154etimer_schedule(DURATION_rt8);
1228}
1229
1230inline void activity_rie6() {
1231   // log the error
1232   openserial_printError(COMPONENT_IEEE802154E,
1233                         ERR_WDACKDURATION_OVERFLOWS,
1234                         ieee154e_vars.state,
1235                         ieee154e_vars.asn%SCHEDULELENGTH);
1236   
1237   // abort
1238   endSlot();
1239}
1240
1241inline void activity_ri9(uint16_t capturedTime) {
1242   // change state
1243   changeState(S_RXPROC);
1244   
1245   // cancel rt8
1246   ieee154etimer_cancel();
1247   
1248   // record the captured time
1249   ieee154e_vars.lastCapturedTime = capturedTime;
1250   
1251   // free the ack we just sent so corresponding RAM memory can be recycled
1252   openqueue_freePacketBuffer(ieee154e_vars.ackToSend);
1253   
1254   // clear local variable
1255   ieee154e_vars.ackToSend = NULL;
1256   
1257   // synchronize to the received packet
1258   if (idmanager_getIsDAGroot()==FALSE && neighbors_isPreferredParent(&(ieee154e_vars.dataReceived->l2_nextORpreviousHop))) {
1259      synchronizePacket(ieee154e_vars.syncCapturedTime);
1260   }
1261   
1262   // inform upper layer of reception (after ACK sent)
1263   notif_receive(ieee154e_vars.dataReceived);
1264   
1265   // clear local variable
1266   ieee154e_vars.dataReceived = NULL;
1267   
1268   // official end of Rx slot
1269   endSlot();
1270}
1271
1272//======= frame validity check
1273
1274/**
1275\brief Decides whether the packet I just received is a valid ADV
1276
1277\param [in] ieee802514_header IEEE802.15.4 header of the packet I just received
1278
1279\returns TRUE if packet is a valid ADV, FALSE otherwise
1280*/
1281inline bool isValidAdv(ieee802154_header_iht* ieee802514_header) {
1282   return ieee802514_header->valid==TRUE                                                              && \
1283          ieee802514_header->frameType==IEEE154_TYPE_BEACON                                           && \
1284          packetfunctions_sameAddress(&ieee802514_header->panid,idmanager_getMyID(ADDR_PANID))        && \
1285          ieee154e_vars.dataReceived->length==sizeof(IEEE802154E_ADV_ht);
1286}
1287
1288/**
1289\brief Decides whether the packet I just received is valid received frame.
1290
1291A valid Rx frame satisfies the following constraints:
1292- its IEEE802.15.4 header is well formatted
1293- its a DATA of BEACON frame (i.e. not ACK and not COMMAND)
1294- its sent on the same PANid as mine
1295- its for me (unicast or broadcast)
1296-
1297
1298\param [in] ieee802514_header IEEE802.15.4 header of the packet I just received
1299
1300\returns TRUE if packet is valid received frame, FALSE otherwise
1301*/
1302inline bool isValidRxFrame(ieee802154_header_iht* ieee802514_header) {
1303   return ieee802514_header->valid==TRUE                                                           && \
1304          (
1305             ieee802514_header->frameType==IEEE154_TYPE_DATA                   ||
1306             ieee802514_header->frameType==IEEE154_TYPE_BEACON
1307          )                                                                                        && \
1308          packetfunctions_sameAddress(&ieee802514_header->panid,idmanager_getMyID(ADDR_PANID))     && \
1309          (
1310             idmanager_isMyAddress(&ieee802514_header->dest)                   ||
1311             packetfunctions_isBroadcastMulticast(&ieee802514_header->dest)
1312          );
1313}
1314
1315/**
1316\brief Decides whether the packet I just received is a valid ACK
1317
1318A packet is a valid ACK if it satisfies the following conditions:
1319- the IEEE802.15.4 header is valid
1320- the frame type is 'ACK'
1321- the sequence number in the ACK matches the sequence number of the packet sent
1322- the ACK contains my PANid
1323- the packet is unicast to me
1324- the packet comes from the neighbor I sent the data to
1325
1326\param [in] ieee802514_header IEEE802.15.4 header of the packet I just received
1327\param [in] packetSent points to the packet I just sent
1328
1329\returns TRUE if packet is a valid ACK, FALSE otherwise
1330*/
1331inline bool isValidAck(ieee802154_header_iht* ieee802514_header,
1332                       OpenQueueEntry_t*      packetSent) {
1333   return ieee802514_header->valid==TRUE                                                           && \
1334          ieee802514_header->frameType==IEEE154_TYPE_ACK                                           && \
1335          ieee802514_header->dsn==packetSent->l2_dsn                                               && \
1336          packetfunctions_sameAddress(&ieee802514_header->panid,idmanager_getMyID(ADDR_PANID))     && \
1337          idmanager_isMyAddress(&ieee802514_header->dest)                                          && \
1338          packetfunctions_sameAddress(&ieee802514_header->src,&packetSent->l2_nextORpreviousHop);
1339}
1340
1341//======= ASN handling
1342
1343inline void asnWrite(OpenQueueEntry_t* advFrame) {
1344   ((IEEE802154E_ADV_ht*)(advFrame->l2_payload))->asn[0] = ieee154e_vars.asn/256;
1345   ((IEEE802154E_ADV_ht*)(advFrame->l2_payload))->asn[1] = ieee154e_vars.asn%256;
1346}
1347
1348inline uint16_t asnRead(OpenQueueEntry_t* advFrame) {
1349   uint16_t returnVal;
1350   returnVal  = 0;
1351   returnVal += 256*((IEEE802154E_ADV_ht*)(ieee154e_vars.dataReceived->payload))->asn[0];
1352   returnVal +=     ((IEEE802154E_ADV_ht*)(ieee154e_vars.dataReceived->payload))->asn[1];
1353   return returnVal;
1354}
1355
1356//======= synchronization
1357
1358void synchronizePacket(uint16_t timeReceived) {
1359   int16_t  timeCorrection;
1360   uint16_t newTaccr0;
1361   uint16_t currentTar;
1362   uint16_t currentTaccr0;
1363   // record the current states of the TAR and TACCR0 registers
1364   currentTar           =  TAR;
1365   currentTaccr0        =  TACCR0;
1366   // calculate new value for TACCR0
1367   timeCorrection    =  (int16_t)((int16_t)timeReceived-(int16_t)TsTxOffset);
1368   newTaccr0         =  TsSlotDuration;
1369   // detect whether I'm too close to the edge of the slot, in that case,
1370   // skip a slot and increase the temporary slot length to be 2 slots long
1371   if (currentTar<timeReceived ||
1372       currentTaccr0-currentTar<RESYNCHRONIZATIONGUARD) {
1373      DEBUG_PIN_SLOT_TOGGLE();
1374      TACTL         &= ~TAIFG;
1375      newTaccr0     +=  TsSlotDuration;
1376      ieee154e_vars.asn++;
1377      DEBUG_PIN_SLOT_TOGGLE();
1378   }
1379   newTaccr0         =  (uint16_t)((int16_t)newTaccr0+timeCorrection);
1380   TACCR0            =  newTaccr0;
1381   ieee154e_vars.deSyncTimeout = DESYNCTIMEOUT;
1382   // update statistics
1383   updateStats(timeCorrection);
1384}
1385
1386void synchronizeAck(int16_t timeCorrection) {
1387   uint16_t newTaccr0;
1388   uint16_t currentTaccr0;
1389   // resynchronize
1390   currentTaccr0        =  TACCR0;
1391   newTaccr0         =  (uint16_t)((int16_t)currentTaccr0-timeCorrection);
1392   TACCR0            =  newTaccr0;
1393   ieee154e_vars.deSyncTimeout = DESYNCTIMEOUT;
1394   // update statistics
1395   updateStats(timeCorrection);
1396}
1397
1398void changeIsSync(bool newIsSync) {
1399   ieee154e_vars.isSync = newIsSync;
1400   if (ieee154e_vars.isSync==TRUE) {
1401      LED_SYNC_ON();
1402      resetStats();
1403   } else {
1404      LED_SYNC_OFF();
1405   }
1406}
1407
1408//======= notifying upper layer
1409
1410void notif_sendDone(OpenQueueEntry_t* packetSent, error_t error) {
1411   // record the outcome of the trasmission attempt
1412   packetSent->l2_sendDoneError    = error;
1413   // record the current ASN
1414   packetSent->l2_TxRxAsnTimestamp = ieee154e_vars.asn;
1415   // associate this packet with the virtual component
1416   // COMPONENT_IEEE802154E_TO_RES so RES can knows it's for it
1417   packetSent->owner              = COMPONENT_IEEE802154E_TO_RES;
1418   // post RES's sendDone task
1419   scheduler_push_task(TASKID_RESNOTIF_TXDONE);
1420   // wake up the scheduler
1421   SCHEDULER_WAKEUP();
1422}
1423
1424void notif_receive(OpenQueueEntry_t* packetReceived) {
1425   // record the current ASN
1426   packetReceived->l2_TxRxAsnTimestamp = ieee154e_vars.asn;
1427   // associate this packet with the virtual component
1428   // COMPONENT_IEEE802154E_TO_RES so RES can knows it's for it
1429   packetReceived->owner          = COMPONENT_IEEE802154E_TO_RES;
1430   // post RES's Receive task
1431   scheduler_push_task(TASKID_RESNOTIF_RX);
1432   // wake up the scheduler
1433   SCHEDULER_WAKEUP();
1434}
1435
1436//======= stats
1437
1438inline void resetStats() {
1439   ieee154e_stats.syncCounter     =    0;
1440   ieee154e_stats.minCorrection   =  127;
1441   ieee154e_stats.maxCorrection   = -127;
1442   // do not reset the number of de-synchronizations
1443}
1444
1445void updateStats(int16_t timeCorrection) {
1446   
1447   ieee154e_stats.syncCounter++;
1448   
1449   if (timeCorrection<ieee154e_stats.minCorrection) {
1450     ieee154e_stats.minCorrection = timeCorrection;
1451   }
1452   
1453   if(timeCorrection>ieee154e_stats.maxCorrection) {
1454     ieee154e_stats.maxCorrection = timeCorrection;
1455   }
1456}
1457
1458//======= misc
1459
1460/**
1461\brief Calculates the frequency to transmit on, based on the
1462absolute slot number and the channel offset of the requested slot.
1463
1464During normal operation, the frequency used is a function of the
1465channelOffset indicating in the schedule, and of the ASN of the
1466slot. This ensures channel hopping, consecutive packets sent in the same slot
1467in the schedule are done on a difference frequency channel.
1468
1469During development, you can force single channel operation by having this
1470function return a constant channel number (between 11 and 26). This allows you
1471to use a single-channel sniffer; but you can not schedule two links on two
1472different channel offsets in the same slot.
1473
1474\param [in] asn Absolute Slot Number
1475\param [in] channelOffset channel offset for the current slot
1476
1477\returns The calculated frequency channel, an integer between 11 and 26.
1478*/
1479inline uint8_t calculateFrequency(asn_t asn, uint8_t channelOffset) {
1480   //return 11+(asn+channelOffset)%16;
1481   //poipoi: no channel hopping
1482   return 26;
1483}
1484
1485/**
1486\brief Changes the state of the IEEE802.15.4e FSM.
1487
1488Besides simply updating the state global variable,
1489this function toggles the FSM debug pin.
1490
1491\param [in] newstate The state the IEEE802.15.4e FSM is now in.
1492*/
1493void changeState(uint8_t newstate) {
1494   // update the state
1495   ieee154e_vars.state = newstate;
1496   // wiggle the FSM debug pin
1497   switch (ieee154e_vars.state) {
1498      case S_SYNCLISTEN:
1499      case S_TXDATAOFFSET:
1500         DEBUG_PIN_FSM_SET();
1501         break;
1502      case S_SLEEP:
1503      case S_RXDATAOFFSET:
1504         DEBUG_PIN_FSM_CLR();
1505         break;
1506      case S_SYNCRX:
1507      case S_SYNCPROC:
1508      case S_TXDATAPREPARE:
1509      case S_TXDATAREADY:
1510      case S_TXDATADELAY:
1511      case S_TXDATA:
1512      case S_RXACKOFFSET:
1513      case S_RXACKPREPARE:
1514      case S_RXACKREADY:
1515      case S_RXACKLISTEN:
1516      case S_RXACK:
1517      case S_TXPROC:
1518      case S_RXDATAPREPARE:
1519      case S_RXDATAREADY:
1520      case S_RXDATALISTEN:
1521      case S_RXDATA:
1522      case S_TXACKOFFSET:
1523      case S_TXACKPREPARE:
1524      case S_TXACKREADY:
1525      case S_TXACKDELAY:
1526      case S_TXACK:
1527      case S_RXPROC:
1528         DEBUG_PIN_FSM_TOGGLE();
1529         break;
1530   }
1531}
1532
1533/**
1534\brief Housekeeping tasks to do at the end of each slot.
1535
1536This functions is called once in each slot, when there is nothing more
1537to do. This might be when an error occured, or when everything went well.
1538This function resets the state of the FSM so it is ready for the next slot.
1539
1540Note that by the time this function is called, any received packet should already
1541have been sent to the upper layer. Similarly, in a Tx slot, the sendDone
1542function should already have been done. If this is not the case, this function
1543will do that for you, but assume that something went wrong.
1544*/
1545void endSlot() {
1546   // turn off the radio
1547   radio_rfOff();
1548   
1549   // clear any pending timer
1550   ieee154etimer_cancel();
1551   
1552   // reset capturedTimes
1553   ieee154e_vars.lastCapturedTime = 0;
1554   ieee154e_vars.syncCapturedTime = 0;
1555   
1556   // clean up dataToSend
1557   if (ieee154e_vars.dataToSend!=NULL) {
1558      // if everything went well, dataToSend was set to NULL in ti9
1559      // transmit failed, decrement transmits left counter
1560      ieee154e_vars.dataToSend->l2_retriesLeft--;
1561      if (ieee154e_vars.dataToSend->l2_retriesLeft==0) {
1562         // indicate tx fail if no more retries left
1563         notif_sendDone(ieee154e_vars.dataToSend,E_FAIL);
1564      } else {
1565         // return packet to the virtual COMPONENT_RES_TO_IEEE802154E component
1566         ieee154e_vars.dataToSend->owner = COMPONENT_RES_TO_IEEE802154E;
1567      }
1568      // reset local variable
1569      ieee154e_vars.dataToSend = NULL;
1570   }
1571   
1572   // clean up dataReceived
1573   if (ieee154e_vars.dataReceived!=NULL) {
1574      // assume something went wrong. If everything went well, dataReceived
1575      // would have been set to NULL in ri9.
1576      // indicate  "received packet" to upper layer since we don't want to loose packets
1577      notif_receive(ieee154e_vars.dataReceived);
1578      // reset local variable
1579      ieee154e_vars.dataReceived = NULL;
1580   }
1581   
1582   // clean up ackToSend
1583   if (ieee154e_vars.ackToSend!=NULL) {
1584      // free ackToSend so corresponding RAM memory can be recycled
1585      openqueue_freePacketBuffer(ieee154e_vars.ackToSend);
1586      // reset local variable
1587      ieee154e_vars.ackToSend = NULL;
1588   }
1589   
1590   // clean up ackReceived
1591   if (ieee154e_vars.ackReceived!=NULL) {
1592      // free ackReceived so corresponding RAM memory can be recycled
1593      openqueue_freePacketBuffer(ieee154e_vars.ackReceived);
1594      // reset local variable
1595      ieee154e_vars.ackReceived = NULL;
1596   }
1597   
1598   // change state
1599   changeState(S_SLEEP);
1600}
Note: See TracBrowser for help on using the repository browser.