]> oss.titaniummirror.com Git - tinyos-2.x.git/blobdiff - tos/lib/mac/tkn154/DispatchSlottedCsmaP.nc
- reduced RAM usage of the beacon sync component
[tinyos-2.x.git] / tos / lib / mac / tkn154 / DispatchSlottedCsmaP.nc
index 9d551042bb4e16dacaea188d9988a73304600a48..3a173d69c63ec614973de1b59e14cd97bad1f6b3 100644 (file)
  * typically switch the radio off unless it has a frame to transmit.
  */
 
-#ifndef IEEE154_BEACON_ENABLED_PAN
-#error "The IEEE154_BEACON_ENABLED_PAN macro MUST be defined when using this component!"
-#endif
-
 generic module DispatchSlottedCsmaP(uint8_t sfDirection)
 {
   provides
@@ -75,15 +71,16 @@ generic module DispatchSlottedCsmaP(uint8_t sfDirection)
   {
     interface Alarm<TSymbolIEEE802154,uint32_t> as CapEndAlarm;
     interface Alarm<TSymbolIEEE802154,uint32_t> as BLEAlarm;
-    interface Alarm<TSymbolIEEE802154,uint32_t> as IndirectTxWaitAlarm;
-    interface Alarm<TSymbolIEEE802154,uint32_t> as BroadcastAlarm;
+    interface Alarm<TSymbolIEEE802154,uint32_t> as RxWaitAlarm;
     interface TransferableResource as RadioToken;
+    interface ResourceRequested as RadioTokenRequested;
     interface SuperframeStructure; 
     interface GetNow<token_requested_t> as IsRadioTokenRequested;
     interface GetNow<bool> as IsRxEnableActive; 
     interface Get<ieee154_txframe_t*> as GetIndirectTxFrame; 
     interface Notify<bool> as RxEnableStateChange;
     interface GetNow<bool> as IsTrackingBeacons;
+    interface Notify<const void*> as PIBUpdateMacRxOnWhenIdle;
     interface FrameUtility;
     interface SlottedCsmaCa;
     interface RadioRx;
@@ -94,7 +91,8 @@ generic module DispatchSlottedCsmaP(uint8_t sfDirection)
     interface Leds;
     interface SetNow<ieee154_cap_frame_backup_t*> as FrameBackup;
     interface GetNow<ieee154_cap_frame_backup_t*> as FrameRestore;
-    interface StdControl as TrackSingleBeacon;
+    interface SplitControl as TrackSingleBeacon;
+    interface MLME_SYNC_LOSS;
   }
 }
 implementation
@@ -125,6 +123,7 @@ implementation
   norace ieee154_txframe_t *m_bcastFrame;
   norace ieee154_txframe_t *m_lastFrame;
   norace uint16_t m_remainingBackoff;
+  ieee154_macRxOnWhenIdle_t macRxOnWhenIdle;
 
   /* variables for the slotted CSMA-CA */
   norace ieee154_csma_t m_csma;
@@ -140,7 +139,7 @@ implementation
 
   /* function / task prototypes */
   void stopAllAlarms();
-  next_state_t tryReceive(rx_alarm_t alarmType);
+  next_state_t tryReceive();
   next_state_t tryTransmit();
   next_state_t trySwitchOff();
   void backupCurrentFrame();
@@ -174,19 +173,39 @@ implementation
 #define dbg_flush_state()
 #endif
 
-  command error_t Reset.init()
+  error_t reset(error_t error)
   {
+    if (call RadioToken.isOwner()) // internal error! this must not happen!
+      return FAIL;
     if (m_currentFrame)
-      signal FrameTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW);
+      signal FrameTx.transmitDone(m_currentFrame, error);
     if (m_lastFrame)
-      signal FrameTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW);
+      signal FrameTx.transmitDone(m_lastFrame, error);
     if (m_bcastFrame)
-      signalTxBroadcastDone(m_bcastFrame, IEEE154_TRANSACTION_OVERFLOW);
+      signalTxBroadcastDone(m_bcastFrame, error);
     m_currentFrame = m_lastFrame = m_bcastFrame = NULL;
+    m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime();
     stopAllAlarms();
     return SUCCESS;
   }
 
+  command error_t Reset.init()
+  {
+    return reset(IEEE154_TRANSACTION_OVERFLOW);
+  }
+
+  event void MLME_SYNC_LOSS.indication (
+                          ieee154_status_t lossReason,
+                          uint16_t PANId,
+                          uint8_t LogicalChannel,
+                          uint8_t ChannelPage,
+                          ieee154_security_t *security
+                        )
+  {
+    // we lost sync to the coordinator -> spool out current packet
+    reset(IEEE154_NO_BEACON);
+  }
+
   async event void RadioToken.transferredFrom(uint8_t fromClient)
   {
     // we got the token, i.e. CAP has just started
@@ -196,20 +215,9 @@ implementation
 
     dbg_serial("DispatchSlottedCsmaP", "Got token, remaining CAP time: %lu\n", 
         call SuperframeStructure.sfStartTime() + capDuration - guardTime - call CapEndAlarm.getNow());
-    if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) {
-      // very rare case: 
-      // this can only happen, if we're on a beacon-enabled PAN, not tracking beacons,   
-      // and searched but didn't find a beacon for aBaseSuperframeDuration*(2n+1) symbols
-      // we'd actually have to transmit the current frame using unslotted CSMA-CA        
-      // but we don't have that functionality available... signal FAIL...                
-      m_lastFrame = m_currentFrame;
-      m_currentFrame = NULL;
-      m_txStatus = IEEE154_NO_BEACON;
-      dbg_serial("DispatchSlottedCsmaP", "CAP component got token, remaining time: %lu\n");
-      post signalTxDoneTask();
-      return;
-    } else if (capDuration < guardTime) {
-      // CAP is too short to do anything practical
+
+    if (capDuration < guardTime) {
+      // CAP is too short to do anything useful
       dbg_serial("DispatchSlottedCsmaP", "CAP too short!\n");
       call RadioToken.transferTo(RADIO_CLIENT_CFP);
       return;
@@ -226,7 +234,7 @@ implementation
           // in task context and then continue
           m_lock = TRUE;
           post setupTxBroadcastTask(); 
-          dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast.\n");
+          dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast...\n");
         }
       }
       call CapEndAlarm.startAt(call SuperframeStructure.sfStartTime(), capDuration);
@@ -249,14 +257,21 @@ implementation
       if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) {
         call TrackSingleBeacon.start();
         dbg_serial("DispatchSlottedCsmaP", "Tracking single beacon now\n");
-        // we'll receive the Token  after a beacon was found or after
-        // aBaseSuperframeDuration*(2n+1) symbols if none was found  
+        // we'll get the Token after a beacon was found or a SYNC_LOSS event
+        // if none was found during the next aBaseSuperframeDuration*(2n+1) symbols  
       }
       updateState();
       return IEEE154_SUCCESS;
     }
   }
 
+  event void TrackSingleBeacon.startDone(error_t error)
+  {
+    if (error != SUCCESS) // beacon could not be tracked
+      reset(IEEE154_NO_BEACON);
+    // else: we'll get the RadioToken and continue as usual ...
+  }
+
   task void setupTxBroadcastTask()
   {
     ieee154_macDSN_t tmp;
@@ -316,10 +331,8 @@ implementation
   void stopAllAlarms()
   {
     call CapEndAlarm.stop();
-    if (DEVICE_ROLE) {
-      call IndirectTxWaitAlarm.stop();
-      call BroadcastAlarm.stop();
-    }
+    if (DEVICE_ROLE)
+      call RxWaitAlarm.stop();
     call BLEAlarm.stop();
   }
 
@@ -349,15 +362,14 @@ implementation
                (uint32_t) call SuperframeStructure.sfSlotDuration();
 
       // Check 1: has the CAP finished?
-      if ((COORD_ROLE || call IsTrackingBeacons.getNow()) && 
-          (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), 
+      if ((call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), 
                 capDuration - call SuperframeStructure.guardTime()) ||
           !call CapEndAlarm.isRunning())) {
         dbg_push_state(1);
         if (call RadioOff.isOff()) {
           stopAllAlarms();  // may still fire, but is locked through isOwner()
           if (DEVICE_ROLE && m_indirectTxPending)
-            signal IndirectTxWaitAlarm.fired();
+            signal RxWaitAlarm.fired();
           m_broadcastRxPending = FALSE;
           if (COORD_ROLE && m_bcastFrame) {
             // didn't manage to transmit a broadcast
@@ -379,7 +391,7 @@ implementation
       else if (DEVICE_ROLE && m_broadcastRxPending) {
         // receive a broadcast from coordinator
         dbg_push_state(2);
-        next = tryReceive(BROADCAST_ALARM);
+        next = tryReceive();
       } else if (COORD_ROLE && m_bcastFrame) {
         dbg_push_state(2);
         next = tryTransmit();
@@ -389,7 +401,7 @@ implementation
       // and are we now waiting for a frame from the coordinator?
       else if (DEVICE_ROLE && m_indirectTxPending) {
         dbg_push_state(3);
-        next = tryReceive(INDIRECT_TX_ALARM);
+        next = tryReceive();
       }
 
       // Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending? 
@@ -411,7 +423,7 @@ implementation
       else if (call SuperframeStructure.battLifeExtDuration() > 0 &&
           call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), 
             call SuperframeStructure.battLifeExtDuration()) &&
-          !call IsRxEnableActive.getNow()) {
+          !call IsRxEnableActive.getNow() && !macRxOnWhenIdle) {
         dbg_push_state(5);
         next = trySwitchOff();
       }
@@ -423,13 +435,12 @@ implementation
       }
 
       // Check 7: should we be in receive mode?
-      else if (COORD_ROLE || call IsRxEnableActive.getNow()) {
+      else if (COORD_ROLE || call IsRxEnableActive.getNow() || macRxOnWhenIdle) {
         dbg_push_state(7);
-        next = tryReceive(NO_ALARM);
+        next = tryReceive();
         if (next == DO_NOTHING) {
-          // this means there is an active MLME_RX_ENABLE.request
-          // and the radio was just switched to Rx mode - signal
-          // a notify event to inform the respective component
+          // if there was an active MLME_RX_ENABLE.request then we'll
+          // inform the next higher layer that radio is now in Rx mode
           post wasRxEnabledTask();
         }
       }
@@ -489,7 +500,7 @@ implementation
     return next;
   }
 
-  next_state_t tryReceive(rx_alarm_t alarmType)
+  next_state_t tryReceive()
   {
     next_state_t next;
     if (call RadioRx.isReceiving())
@@ -498,12 +509,6 @@ implementation
       next = SWITCH_OFF;
     else {
       call RadioRx.enableRx(0, 0);
-      switch (alarmType)
-      {
-        case INDIRECT_TX_ALARM: call IndirectTxWaitAlarm.start(m_macMaxFrameTotalWaitTime); break;
-        case BROADCAST_ALARM: call BroadcastAlarm.start(m_macMaxFrameTotalWaitTime); break;
-        case NO_ALARM: break;
-      }
       next = WAIT_FOR_RXDONE;
     }
     return next;
@@ -519,8 +524,19 @@ implementation
     return next;
   }
 
-  async event void RadioOff.offDone() { m_lock = FALSE; updateState();}
-  async event void RadioRx.enableRxDone() { m_lock = FALSE; updateState();}
+  async event void RadioOff.offDone() 
+  { 
+    m_lock = FALSE; 
+    updateState();
+  }
+
+  async event void RadioRx.enableRxDone() 
+  { 
+    if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending))
+      call RxWaitAlarm.start(m_macMaxFrameTotalWaitTime);
+    m_lock = FALSE; 
+    updateState();
+  }
 
   async event void CapEndAlarm.fired() { 
     dbg_serial("DispatchSlottedCsmaP", "CapEndAlarm.fired()\n");
@@ -528,16 +544,23 @@ implementation
   }
   async event void BLEAlarm.fired() { updateState();}
   event void RxEnableStateChange.notify(bool whatever) { updateState();}
-  async event void BroadcastAlarm.fired() { m_broadcastRxPending = FALSE; updateState();}
+  event void PIBUpdateMacRxOnWhenIdle.notify( const void* val ) {
+    atomic macRxOnWhenIdle = *((ieee154_macRxOnWhenIdle_t*) val);
+    updateState();
+  }
 
-  async event void IndirectTxWaitAlarm.fired() 
+  async event void RxWaitAlarm.fired() 
   { 
-    atomic {
-      if (m_indirectTxPending) {
-        m_indirectTxPending = FALSE; 
-        post signalTxDoneTask(); 
+    if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending))
+      atomic {
+        if (m_indirectTxPending) {
+          m_indirectTxPending = FALSE; 
+          post signalTxDoneTask(); 
+        } else if (m_broadcastRxPending) {
+          m_broadcastRxPending = FALSE;
+          updateState();
+        }
       }
-    }
   }
 
   async event void SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma, 
@@ -644,21 +667,26 @@ implementation
     uint8_t *payload = (uint8_t *) frame->data;
     uint8_t *mhr = MHR(frame);
     uint8_t frameType = mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK;
+
     if (frameType == FC1_FRAMETYPE_CMD)
       frameType += payload[0];
+    dbg("DispatchSlottedCsmaP", "Received frame, DSN: %lu, type: 0x%lu\n", 
+        (uint32_t) mhr[MHR_INDEX_SEQNO], (uint32_t) frameType);
     atomic {
-      if (DEVICE_ROLE && m_indirectTxPending) {
+      if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending)) {
         message_t* frameBuf;
-        call IndirectTxWaitAlarm.stop();
-        // TODO: check!
-        //if (frame->payloadLen)
-          // is this frame from our coordinator? hmm... we cannot say/ with
-          // certainty, because we might only know either the  coordinator
-          // extended or short address (and the frame could/ have been sent
-          // with the other addressing mode) ??
+        call RxWaitAlarm.stop();
+        // TODO: check the following: 
+        // is this frame from our coordinator? hmm... we cannot say/ with
+        // certainty, because we might only know either the  coordinator
+        // extended or short address (and the frame could/ have been sent
+        // with the other addressing mode) ??
         m_txStatus = IEEE154_SUCCESS;
-        frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame);
-        signal IndirectTxWaitAlarm.fired();
+        if (m_indirectTxPending)
+          frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame); // indirect tx from coord
+        else
+          frameBuf = signal FrameRx.received[frameType](frame); // broadcast from coordinator
+        signal RxWaitAlarm.fired();
         return frameBuf;
       } else
         return signal FrameRx.received[frameType](frame);
@@ -717,21 +745,20 @@ implementation
   default event message_t* FrameRx.received[uint8_t client](message_t* data) {return data;}
   default async command bool IsRxEnableActive.getNow() {return FALSE;}
 
-  default async command void IndirectTxWaitAlarm.start(uint32_t dt) {ASSERT(0);}
-  default async command void IndirectTxWaitAlarm.stop() {ASSERT(0);}
-  default async command void IndirectTxWaitAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);}
+  default async command void RxWaitAlarm.start(uint32_t dt) {ASSERT(0);}
+  default async command void RxWaitAlarm.stop() {ASSERT(0);}
+  default async command void RxWaitAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);}
   
-  default async command void BroadcastAlarm.start(uint32_t dt) {ASSERT(0);}
-  default async command void BroadcastAlarm.stop() {ASSERT(0);}
-  default async command void BroadcastAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);}
-
   default async command bool SuperframeStructure.isBroadcastPending() { return FALSE;}
   default async event void BroadcastTx.transmitNowDone(ieee154_txframe_t *frame, ieee154_status_t status) {}
   default event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame) {return msg;}
   default async command error_t FrameBackup.setNow(ieee154_cap_frame_backup_t* val) {return FAIL;}
   default async command ieee154_cap_frame_backup_t* FrameRestore.getNow() {return NULL;}
-  default command error_t TrackSingleBeacon.start() {return FAIL;}
+  event void TrackSingleBeacon.stopDone(error_t error){}
+  default command error_t TrackSingleBeacon.start() {if (DEVICE_ROLE) ASSERT(0); return SUCCESS;}
 
   command error_t WasRxEnabled.enable() {return FAIL;}
   command error_t WasRxEnabled.disable() {return FAIL;}
+  async event void RadioTokenRequested.requested(){ updateState(); }
+  async event void RadioTokenRequested.immediateRequested(){ updateState(); }
 }