[Tinyos-2-commits] CVS: tinyos-2.x/tos/lib/mac/tkn154 DispatchQueueP.nc, NONE, 1.1 DispatchSlottedCsmaP.nc, NONE, 1.1 DispatchUnslottedCsmaP.nc, NONE, 1.1 PibP.nc, 1.5, 1.6 TKN154BeaconEnabledP.nc, 1.1, 1.2 TKN154NonBeaconEnabledP.nc, 1.1, 1.2 FrameDispatchQueueP.nc, 1.2, NONE SlottedFrameDispatchP.nc, 1.1, NONE UnslottedFrameDispatchP.nc, 1.1, NONE

Jan-Hinrich Hauer janhauer at users.sourceforge.net
Thu Mar 5 02:07:16 PST 2009


Update of /cvsroot/tinyos/tinyos-2.x/tos/lib/mac/tkn154
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv2894/tos/lib/mac/tkn154

Modified Files:
	PibP.nc TKN154BeaconEnabledP.nc TKN154NonBeaconEnabledP.nc 
Added Files:
	DispatchQueueP.nc DispatchSlottedCsmaP.nc 
	DispatchUnslottedCsmaP.nc 
Removed Files:
	FrameDispatchQueueP.nc SlottedFrameDispatchP.nc 
	UnslottedFrameDispatchP.nc 
Log Message:
renaming

--- NEW FILE: DispatchQueueP.nc ---
/*
 * Copyright (c) 2008, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2009/03/05 10:07:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */
#include "TKN154_MAC.h"
generic module DispatchQueueP() {
  provides
  {
    interface Init as Reset;
    interface FrameTx[uint8_t client];
    interface FrameRx as FrameExtracted[uint8_t client];
    interface Purge;
  } uses {
    interface Queue<ieee154_txframe_t*>;
    interface FrameTx as FrameTxCsma;
    interface FrameRx as SubFrameExtracted;
  }
}
implementation
{
  task void txTask();
  bool m_busy;
  uint8_t m_client;

  command error_t Reset.init()
  {
    while (call Queue.size()) {
      ieee154_txframe_t *txFrame = call Queue.dequeue();
      signal FrameTx.transmitDone[txFrame->client](txFrame, IEEE154_TRANSACTION_OVERFLOW);
    }
    m_busy = FALSE;
    return SUCCESS;
  }

  command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame)
  {
    txFrame->client = client;
    if (call Queue.enqueue(txFrame) != SUCCESS)
      return IEEE154_TRANSACTION_OVERFLOW;
    else {
      post txTask();
      return IEEE154_SUCCESS;
    }
  }

  task void txTask()
  {
    if (!m_busy && call Queue.size()) {
      ieee154_txframe_t *txFrame = call Queue.head();
      if (txFrame->headerLen == 0) { 
        // was purged
        call Queue.dequeue();
        signal Purge.purgeDone(txFrame, IEEE154_SUCCESS);
        post txTask();
      }
      m_client = txFrame->client;
      if (call FrameTxCsma.transmit(txFrame) == IEEE154_SUCCESS) {
        m_busy = TRUE;
      }
    }
  }

  event void FrameTxCsma.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
  {
    call Queue.dequeue();
    m_busy = FALSE;
    signal FrameTx.transmitDone[txFrame->client](txFrame, status);
    post txTask();
  }

  event message_t* SubFrameExtracted.received(message_t* frame)
  {
    // this event is signalled when a frame has been received
    // in response to a data request command frame. The transmitDone 
    // event will be signalled later
    return signal FrameExtracted.received[m_client](frame);
  }

  default event void FrameTx.transmitDone[uint8_t client](ieee154_txframe_t *txFrame, ieee154_status_t status) {}

  command ieee154_status_t Purge.purge(uint8_t msduHandle)
  {
    uint8_t qSize = call Queue.size(), i;
    if (qSize > 1) {
      for (i=0; i<qSize-1; i++) {
        ieee154_txframe_t *txFrame = call Queue.element(i);
        if (((txFrame->header->mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_DATA) &&
          txFrame->handle == msduHandle) {
          txFrame->headerLen = 0; // mark as invalid
          return IEEE154_SUCCESS;
        }
      }
    }
    return IEEE154_INVALID_HANDLE;
  }
  
  default event void Purge.purgeDone(ieee154_txframe_t *txFrame, ieee154_status_t status) {}
}

--- NEW FILE: DispatchSlottedCsmaP.nc ---
/*
 * Copyright (c) 2008, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2009/03/05 10:07:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */

#include "TKN154_PHY.h"
#include "TKN154_MAC.h"


/** 
 * This module is responsible for the transmission/reception of DATA and
 * COMMAND frames in the CAP of beacon-enabled PANs. Its main tasks are
 * initialization of the parameters of the slotted CSMA-CA algorithm (NB, BE,
 * etc.), initiating retransmissions and dealing with broadcast transmissions.
 * It does not implement the actual CSMA-CA algorithm, because due to its
 * timing requirements the CSMA-CA algorithm is not part of the MAC
 * implementation but of the chip-specific radio driver.
 *
 * This module does slightly different things depending on whether it is the
 * CAP for an outgoing superframe (sfDirection = OUTGOING_SUPERFRAME), i.e. the
 * CAP from the perspective of a coordinator after it has transmitted its own
 * beacon; or for an incoming superframe (sfDirection = INCOMING_SUPERFRAME),
 * i.e.  the CAP from the perspective of a device after it has received a
 * beacon from its coordinator. For example, in the CAP a coordinator will
 * typically listen for incoming frames from the devices, and a device will
 * 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
  {
    interface Init as Reset;
    interface FrameTx as FrameTx;
    interface FrameRx as FrameRx[uint8_t frameType];
    interface FrameExtracted as FrameExtracted[uint8_t frameType];
    interface FrameTxNow as BroadcastTx;
    interface Notify<bool> as WasRxEnabled;
  }
  uses
  {
    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 Resource as Token;
    interface GetNow<bool> as IsTokenRequested;
    interface ResourceTransfer as TokenToCfp;
    interface ResourceTransferred as TokenTransferred;
    interface SuperframeStructure; 
    interface GetNow<bool> as IsRxEnableActive; 
    interface Get<ieee154_txframe_t*> as GetIndirectTxFrame; 
    interface Notify<bool> as RxEnableStateChange;
    interface GetNow<bool> as IsTrackingBeacons;
    interface FrameUtility;
    interface SlottedCsmaCa;
    interface RadioRx;
    interface RadioOff;
    interface MLME_GET;
    interface MLME_SET;
    interface TimeCalc;
    interface Leds;
    interface SetNow<ieee154_cap_frame_backup_t*> as FrameBackup;
    interface GetNow<ieee154_cap_frame_backup_t*> as FrameRestore;
    interface StdControl as TrackSingleBeacon;
  }
}
implementation
{
  typedef enum {
    SWITCH_OFF,       
    WAIT_FOR_RXDONE,  
    WAIT_FOR_TXDONE,  
    DO_NOTHING,       
  } next_state_t; 

  typedef enum {
    INDIRECT_TX_ALARM,
    BROADCAST_ALARM,
    NO_ALARM,
  } rx_alarm_t;

  enum {
    COORD_ROLE = (sfDirection == OUTGOING_SUPERFRAME),
    DEVICE_ROLE = !COORD_ROLE,
  };

  /* state / frame management */
  norace bool m_lock;
  norace bool m_resume;
  norace ieee154_txframe_t *m_currentFrame;
  norace ieee154_txframe_t *m_bcastFrame;
  norace ieee154_txframe_t *m_lastFrame;
  norace uint16_t m_remainingBackoff;

  /* variables for the slotted CSMA-CA */
  norace ieee154_csma_t m_csma;
  norace ieee154_macMaxBE_t m_BE;
  norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs;
  norace ieee154_macMaxBE_t m_macMaxBE;
  norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries;
  norace ieee154_status_t m_txStatus;
  norace uint32_t m_transactionTime;
  norace bool m_indirectTxPending = FALSE;
  norace bool m_broadcastRxPending;
  norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime;

  /* function / task prototypes */
  void stopAllAlarms();
  next_state_t tryReceive(rx_alarm_t alarmType);
  next_state_t tryTransmit();
  next_state_t trySwitchOff();
  void backupCurrentFrame();
  void restoreFrameFromBackup();  
  void updateState();
  void setCurrentFrame(ieee154_txframe_t *frame);
  void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error);
  task void signalTxDoneTask();
  task void setupTxBroadcastTask();
  task void wasRxEnabledTask();

#ifdef TKN154_DEBUG
  enum {
    HEADER_STR_LEN = 27,
    DBG_STR_SIZE = 250,
  };
  norace uint16_t m_dbgNumEntries;
  norace char m_dbgStr[HEADER_STR_LEN + DBG_STR_SIZE] = "updateState() transitions: ";
  void dbg_push_state(uint8_t state) {
    if (m_dbgNumEntries < DBG_STR_SIZE-3)
      m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = '0' + state; 
  }
  void dbg_flush_state() {
    m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = '\n'; 
    m_dbgStr[HEADER_STR_LEN + m_dbgNumEntries++] = 0; 
    dbg_serial("DispatchSlottedCsmaP",m_dbgStr);
    m_dbgNumEntries = 0;
  }
#else 
#define dbg_push_state(X)
#define dbg_flush_state()
#endif

  command error_t Reset.init()
  {
    if (m_currentFrame)
      signal FrameTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW);
    if (m_lastFrame)
      signal FrameTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW);
    if (m_bcastFrame)
      signalTxBroadcastDone(m_bcastFrame, IEEE154_TRANSACTION_OVERFLOW);
    m_currentFrame = m_lastFrame = m_bcastFrame = NULL;
    stopAllAlarms();
    return SUCCESS;
  }

  async event void TokenTransferred.transferred()
  {
    // we got the token, i.e. CAP has just started
    uint32_t capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * 
      (uint32_t) call SuperframeStructure.sfSlotDuration();
    uint16_t guardTime = call SuperframeStructure.guardTime();

    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
      dbg_serial("DispatchSlottedCsmaP", "CAP too short!\n");
      call TokenToCfp.transfer();
      return;
    } else {
      capDuration -= guardTime;
      if (DEVICE_ROLE)
        m_broadcastRxPending = call SuperframeStructure.isBroadcastPending();
      else { 
        // COORD_ROLE
        if (m_bcastFrame != NULL) {
          // we have to transmit a broadcast frame immediately; this
          // may require to a backup of the previously active frame 
          // and a reinitializing the CSMA parameters -> will do it 
          // in task context and then continue
          m_lock = TRUE;
          post setupTxBroadcastTask(); 
          dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast.\n");
        }
      }
      call CapEndAlarm.startAt(call SuperframeStructure.sfStartTime(), capDuration);
      if (call SuperframeStructure.battLifeExtDuration() > 0)
        call BLEAlarm.startAt(call SuperframeStructure.sfStartTime(), call SuperframeStructure.battLifeExtDuration());
    }
    updateState();
  }

  command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame)
  {
    if (m_currentFrame != NULL) {
      // we've not finished transmitting the current frame yet
      dbg_serial("DispatchSlottedCsmaP", "Overflow\n");
      return IEEE154_TRANSACTION_OVERFLOW;
    } else {
      setCurrentFrame(frame);
      dbg("DispatchSlottedCsmaP", "New frame to transmit, DSN: %lu\n", (uint32_t) MHR(frame)[MHR_INDEX_SEQNO]);
      // a beacon must be found before transmitting in a beacon-enabled PAN
      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  
      }
      updateState();
      return IEEE154_SUCCESS;
    }
  }

  task void setupTxBroadcastTask()
  {
    ieee154_macDSN_t tmp;
    ieee154_txframe_t *oldFrame = m_currentFrame;
    if (COORD_ROLE) {
      if (m_bcastFrame != NULL) {
        // broadcasts should be transmitted *immediately* after the beacon,  
        // which may interrupt a pending transmit operation from the previous
        // CAP; back up the last active frame configuration (may be none)    
        // and restore it after the broadcast frame has been transmitted;    
        // do this through interfaces and don't wire them for DEVICE_ROLE,   
        // so we don't waste the RAM of devices
        backupCurrentFrame();
        setCurrentFrame(m_bcastFrame);
        if (oldFrame) {
          // now the sequence number are out of order... swap them back
          tmp = m_bcastFrame->header->mhr[MHR_INDEX_SEQNO];
          m_bcastFrame->header->mhr[MHR_INDEX_SEQNO] = 
            oldFrame->header->mhr[MHR_INDEX_SEQNO];
          oldFrame->header->mhr[MHR_INDEX_SEQNO] = tmp;
        }
      }
    }
    m_lock = FALSE;
    updateState(); 
  }

  void setCurrentFrame(ieee154_txframe_t *frame)
  {
    ieee154_macDSN_t dsn = call MLME_GET.macDSN();
    frame->header->mhr[MHR_INDEX_SEQNO] = dsn++;
    call MLME_SET.macDSN(dsn);
    m_csma.NB = 0;
    m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs();
    m_csma.macMaxBE = m_macMaxBE = call MLME_GET.macMaxBE();
    m_csma.BE = call MLME_GET.macMinBE();
    if (call MLME_GET.macBattLifeExt() && m_csma.BE > 2)
      m_csma.BE = 2;
    m_BE = m_csma.BE;
    if (COORD_ROLE && call GetIndirectTxFrame.get() == frame)
      m_macMaxFrameRetries =  0; // this is an indirect transmissions (never retransmit)
    else
      m_macMaxFrameRetries =  call MLME_GET.macMaxFrameRetries();
    m_transactionTime = IEEE154_SHR_DURATION + 
      (frame->headerLen + frame->payloadLen + 2) * IEEE154_SYMBOLS_PER_OCTET; // extra 2 for CRC
    if (frame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST)
      m_transactionTime += (IEEE154_aTurnaroundTime + IEEE154_aUnitBackoffPeriod + 
          11 * IEEE154_SYMBOLS_PER_OCTET); // 11 byte for the ACK PPDU
    // if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize) 
    //  m_transactionTime += call MLME_GET.macMinLIFSPeriod(); 
    // else 
    //  m_transactionTime += call MLME_GET.macMinSIFSPeriod(); 
    m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime();
    m_currentFrame = frame;
  }
 
  void stopAllAlarms()
  {
    call CapEndAlarm.stop();
    if (DEVICE_ROLE) {
      call IndirectTxWaitAlarm.stop();
      call BroadcastAlarm.stop();
    }
    call BLEAlarm.stop();
  }

  /** 
   * The updateState() function is called whenever something happened that
   * might require a state transition; it implements a lock mechanism (m_lock)
   * to prevent race conditions. Whenever the lock is set a "done"-event (from
   * the SlottedCsmaCa/RadioRx/RadioOff interface) is pending and will "soon"
   * unset the lock (and then updateState() will called again).  The
   * updateState() function decides about the next state by checking a list of
   * possible current states ordered by priority, e.g. it first always checks
   * whether the CAP is still active. Calling this function more than necessary
   * can do no harm.
   */ 

  void updateState()
  {
    uint32_t capDuration; 
    next_state_t next;
    atomic {
      // long atomics are bad... but in this block, once the/ current state has
      // been determined only one branch will/ be taken (there are no loops)
      if (m_lock || !call Token.isOwner())
        return;
      m_lock = TRUE; // lock
      capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * 
               (uint32_t) call SuperframeStructure.sfSlotDuration();

      // Check 1: has the CAP finished?
      if ((COORD_ROLE || call IsTrackingBeacons.getNow()) && 
          (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();
          m_broadcastRxPending = FALSE;
          if (COORD_ROLE && m_bcastFrame) {
            // didn't manage to transmit a broadcast
            restoreFrameFromBackup();
            signalTxBroadcastDone(m_bcastFrame, IEEE154_CHANNEL_ACCESS_FAILURE);
            m_bcastFrame = NULL;
          }
          m_lock = FALSE; // unlock
          dbg_flush_state();
          dbg_serial("DispatchSlottedCsmaP", "Handing over to CFP.\n");
          call TokenToCfp.transfer();
          return;
        } else 
          next = SWITCH_OFF;
      }

      // Check 2: should a broadcast frame be received/transmitted
      // immediately at the start of CAP?
      else if (DEVICE_ROLE && m_broadcastRxPending) {
        // receive a broadcast from coordinator
        dbg_push_state(2);
        next = tryReceive(BROADCAST_ALARM);
      } else if (COORD_ROLE && m_bcastFrame) {
        dbg_push_state(2);
        next = tryTransmit();
      }

      // Check 3: was an indirect transmission successfully started 
      // 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);
      }

      // Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending? 
      else if (call IsTokenRequested.getNow()) {
        dbg_push_state(4);
        if (call RadioOff.isOff()) {
          stopAllAlarms();  // may still fire, but is locked through isOwner()
          // nothing more to do... just release the Token
          m_lock = FALSE; // unlock
          dbg_serial("DispatchSlottedCsmaP", "Token requested: Handing over to CFP.\n");
          call TokenToCfp.transfer();
          return;
        } else 
          next = SWITCH_OFF;
      }

      // Check 5: is battery life extension (BLE) active and 
      // has the BLE period expired?
      else if (call SuperframeStructure.battLifeExtDuration() > 0 &&
          call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), 
            call SuperframeStructure.battLifeExtDuration()) &&
          !call IsRxEnableActive.getNow()) {
        dbg_push_state(5);
        next = trySwitchOff();
      }

      // Check 6: is there a frame ready to transmit?
      else if (m_currentFrame != NULL) {
        dbg_push_state(6);
        next = tryTransmit();
      }

      // Check 7: should we be in receive mode?
      else if (COORD_ROLE || call IsRxEnableActive.getNow()) {
        dbg_push_state(7);
        next = tryReceive(NO_ALARM);
        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
          post wasRxEnabledTask();
        }
      }

      // Check 8: just make sure the radio is switched off  
      else {
        dbg_push_state(8);
        next = trySwitchOff();
        if (next == DO_NOTHING && (DEVICE_ROLE && capDuration == 0)) {
          // nothing more to do... just release the Token
          stopAllAlarms();  // may still fire, but is locked through isOwner()
          m_lock = FALSE; // unlock
          dbg_serial("DispatchSlottedCsmaP", "Releasing token\n");
          call Token.release();
          return;
        }
      }

      // if there is nothing to do, then we must clear the lock
      if (next == DO_NOTHING)
        m_lock = FALSE;
    } // atomic

    // put next state in operation (possibly keeping the lock)
    switch (next)
    {
      case SWITCH_OFF: ASSERT(call RadioOff.off() == SUCCESS); break;
      case WAIT_FOR_RXDONE: break;
      case WAIT_FOR_TXDONE: break;
      case DO_NOTHING: break;
    }
  }
  
  next_state_t tryTransmit()
  {
    // tries to transmit m_currentFrame
    uint32_t capDuration = (uint32_t) call SuperframeStructure.numCapSlots() * 
      (uint32_t) call SuperframeStructure.sfSlotDuration();
    next_state_t next;

    if (!call RadioOff.isOff())
      next = SWITCH_OFF;
    else {
      uint32_t dtMax = capDuration - call SuperframeStructure.guardTime() - m_transactionTime;
      // round to backoff boundary
      dtMax = dtMax + (IEEE154_aUnitBackoffPeriod - (dtMax % IEEE154_aUnitBackoffPeriod));
      if (dtMax > capDuration)
        dtMax = 0;
      if (call SuperframeStructure.battLifeExtDuration() > 0) {
        // battery life extension
        uint16_t bleLen = call SuperframeStructure.battLifeExtDuration();
        if (bleLen < dtMax)
          dtMax = bleLen;
      }
      if (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(), dtMax))
        next = DO_NOTHING; // frame doesn't fit in the remaining CAP
      else {
        error_t res;
        res = call SlottedCsmaCa.transmit(m_currentFrame, &m_csma, 
                   call SuperframeStructure.sfStartTimeRef(), dtMax, m_resume, m_remainingBackoff);
        dbg("DispatchSlottedCsmaP", "SlottedCsmaCa.transmit() -> %lu\n", (uint32_t) res);
        next = WAIT_FOR_TXDONE; // this will NOT clear the lock
      }
    }
    return next;
  }

  next_state_t tryReceive(rx_alarm_t alarmType)
  {
    next_state_t next;
    if (call RadioRx.isReceiving())
      next = DO_NOTHING;
    else if (!call RadioOff.isOff())
      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;
  }

  next_state_t trySwitchOff()
  {
    next_state_t next;
    if (call RadioOff.isOff())
      next = DO_NOTHING;
    else
      next = SWITCH_OFF;
    return next;
  }

  async event void RadioOff.offDone() { m_lock = FALSE; updateState();}
  async event void RadioRx.enableRxDone() { m_lock = FALSE; updateState();}

  async event void CapEndAlarm.fired() { 
    dbg_serial("DispatchSlottedCsmaP", "CapEndAlarm.fired()\n");
    updateState();
  }
  async event void BLEAlarm.fired() { updateState();}
  event void RxEnableStateChange.notify(bool whatever) { updateState();}
  async event void BroadcastAlarm.fired() { m_broadcastRxPending = FALSE; updateState();}

  async event void IndirectTxWaitAlarm.fired() 
  { 
    atomic {
      if (m_indirectTxPending) {
        m_indirectTxPending = FALSE; 
        post signalTxDoneTask(); 
      }
    }
  }

  async event void SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma, 
      bool ackPendingFlag,  uint16_t remainingBackoff, error_t result)
  {
    bool done = TRUE;
    dbg("DispatchSlottedCsmaP", "SlottedCsmaCa.transmitDone() -> %lu\n", (uint32_t) result);
    m_resume = FALSE;

    switch (result)
    {
      case SUCCESS:
        // frame was successfully transmitted, if ACK was requested
        // then a matching ACK was successfully received as well   
        m_txStatus = IEEE154_SUCCESS;
        if (DEVICE_ROLE && frame->payload[0] == CMD_FRAME_DATA_REQUEST &&
            ((frame->header->mhr[MHR_INDEX_FC1]) & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD) {
          // this was a data request frame
          m_txStatus = IEEE154_NO_DATA; // pessimistic 
          if (ackPendingFlag) {
            // the coordinator has data for us; switch to Rx 
            // to complete the indirect transmission         
            m_indirectTxPending = TRUE;
            m_lastFrame = m_currentFrame;
            m_currentFrame = NULL;
            ASSERT(call RadioRx.enableRx(0, 0) == SUCCESS);
            return;
          }
        }
        break;
      case FAIL:
        // The CSMA-CA algorithm failed: the frame was not transmitted,
        // because channel was never idle                              
        m_txStatus = IEEE154_CHANNEL_ACCESS_FAILURE;
        break;
      case ENOACK:
        // frame was transmitted, but we didn't receive an ACK (although
        // we requested an one). note: coordinator never retransmits an 
        // indirect transmission (see above) 
        if (m_macMaxFrameRetries > 0) {
          // retransmit: reinitialize CSMA-CA parameters
          done = FALSE;
          m_csma.NB = 0;
          m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs;
          m_csma.macMaxBE = m_macMaxBE;
          m_csma.BE = m_BE;
          m_macMaxFrameRetries -= 1;
        } else
          m_txStatus = IEEE154_NO_ACK;
        break;
      case EINVAL: // DEBUG!!!
        dbg_serial("DispatchSlottedCsmaP", "EINVAL returned by transmitDone()!\n");
        // fall through
      case ERETRY:
        // frame was not transmitted, because the transaction does not
        // fit in the remaining CAP (in beacon-enabled PANs only)
        dbg_serial("DispatchSlottedCsmaP", "Transaction didn't fit, current BE: %lu\n", (uint32_t) csma->BE);
        m_resume = TRUE;
        m_remainingBackoff = remainingBackoff;
        done = FALSE;
        m_lock = FALSE; // debug! problem: if CAP endalarm has fired it's a deadlock!
        if (!call CapEndAlarm.isRunning())
          updateState();
        return;
        break;
      default: 
        ASSERT(0);
        break;
    }

    if (COORD_ROLE && frame == m_bcastFrame) {
      // always signal result of broadcast transmissions immediately 
      restoreFrameFromBackup();
      signalTxBroadcastDone(m_bcastFrame, (!done) ? IEEE154_CHANNEL_ACCESS_FAILURE : m_txStatus);
      m_bcastFrame = NULL;
    } else if (done) {
      m_lastFrame = m_currentFrame;
      m_currentFrame = NULL;
      post signalTxDoneTask();
    }  

    m_lock = FALSE;
    updateState();
  }

  task void signalTxDoneTask()
  {
    ieee154_txframe_t *lastFrame = m_lastFrame;
    ieee154_status_t status = m_txStatus;
    m_indirectTxPending = FALSE;
    m_lastFrame = NULL; // only now can the next transmission can begin 
    if (lastFrame) {
      dbg("DispatchSlottedCsmaP", "Transmit done, DSN: %lu, result: 0x%lx\n", 
          (uint32_t) MHR(lastFrame)[MHR_INDEX_SEQNO], (uint32_t) status);
      signal FrameTx.transmitDone(lastFrame, status);
    }
    updateState();
  }

  event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp)
  {
    // received a frame -> find out frame type and
    // signal it to responsible client component
    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];
    atomic {
      if (DEVICE_ROLE && m_indirectTxPending) {
        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) ??
        m_txStatus = IEEE154_SUCCESS;
        frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame);
        signal IndirectTxWaitAlarm.fired();
        return frameBuf;
      } else
        return signal FrameRx.received[frameType](frame);
    }
  }

  void backupCurrentFrame()
  {
    ieee154_cap_frame_backup_t backup = {m_currentFrame, m_csma, m_transactionTime};
    call FrameBackup.setNow(&backup);
  }

  void restoreFrameFromBackup()
  {
    ieee154_cap_frame_backup_t *backup = call FrameRestore.getNow();
    if (backup != NULL) {
      m_currentFrame = backup->frame;
      memcpy(&m_csma, &backup->csma, sizeof(ieee154_csma_t));
      m_transactionTime = backup->transactionTime;
    }
  }

  async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame) 
  {
    // if this command is called then it is (MUST be) called only just before
    // the token is transferred to this component and it is then called
    // only once per CAP (max. one broadcast is allowed after a beacon
    // transmission)
    atomic {
      if (!call Token.isOwner() && m_bcastFrame == NULL) {
        m_bcastFrame = frame;
        return IEEE154_SUCCESS;
      } else {
        ASSERT(0);
        return IEEE154_TRANSACTION_OVERFLOW;
      }
    }
  }

  void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error)
  {
    signal BroadcastTx.transmitNowDone(frame, error);
  }

  task void wasRxEnabledTask()
  {
    signal WasRxEnabled.notify(TRUE);
  }

  event void Token.granted()
  {
    ASSERT(0); // should never happen
  }

  default event void FrameTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status) {}
  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 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;}

  command error_t WasRxEnabled.enable() {return FAIL;}
  command error_t WasRxEnabled.disable() {return FAIL;}
}

--- NEW FILE: DispatchUnslottedCsmaP.nc ---
/*
 * Copyright (c) 2008, Technische Universitaet Berlin
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without 
 * modification, are permitted provided that the following conditions 
 * are met:
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 * - Redistributions in binary form must reproduce the above copyright 
 *   notice, this list of conditions and the following disclaimer in the 
 *   documentation and/or other materials provided with the distribution.
 * - Neither the name of the Technische Universitaet Berlin nor the names 
 *   of its contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE 
 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * - Revision -------------------------------------------------------------
 * $Revision: 1.1 $
 * $Date: 2009/03/05 10:07:11 $
 * @author Jan Hauer <hauer at tkn.tu-berlin.de>
 * ========================================================================
 */

#include "TKN154_PHY.h"
#include "TKN154_MAC.h"

/** 
 * This module is responsible for the transmission/reception of DATA and
 * COMMAND frames in a nonbeacon-enabled PAN. Its main tasks are initialization
 * of the parameters of the unslotted CSMA-CA algorithm (NB, BE, etc.),
 * initiating retransmissions and managing requests for enabling the receiver
 * for a finite period of time. It does not implement the actual CSMA-CA
 * algorithm, because due to its timing requirements the CSMA-CA algorithm is
 * not part of the MAC implementation but of the chip-specific radio driver.
 */

#if IEEE154_BEACON_ENABLED_PAN
#error "The IEEE154_BEACON_ENABLED_PAN macro MUST NOT be set when using this component!"
#endif

module DispatchUnslottedCsmaP
{
  provides
  {
    interface Init as Reset;
    interface MLME_START;
    interface FrameTx as FrameTx;
    interface FrameRx as FrameRx[uint8_t frameType];
    interface FrameExtracted as FrameExtracted[uint8_t frameType];
    interface Notify<bool> as WasRxEnabled;
  }
  uses
  {
    interface Timer<TSymbolIEEE802154> as IndirectTxWaitTimer;
    interface Resource as Token;
    interface GetNow<bool> as IsTokenRequested;
    interface GetNow<bool> as IsRxEnableActive; 
    interface Set<ieee154_macSuperframeOrder_t> as SetMacSuperframeOrder;
    interface Set<ieee154_macPanCoordinator_t> as SetMacPanCoordinator;     
    interface Get<ieee154_txframe_t*> as GetIndirectTxFrame; 
    interface Notify<bool> as RxEnableStateChange;
    interface FrameUtility;
    interface UnslottedCsmaCa;
    interface RadioRx;
    interface RadioOff;
    interface MLME_GET;
    interface MLME_SET;
    interface TimeCalc;
    interface Leds;
  }
}
implementation
{
  typedef enum {
    SWITCH_OFF,       
    WAIT_FOR_RXDONE,  
    WAIT_FOR_TXDONE,  
    DO_NOTHING,       
  } next_state_t; 

  typedef enum {
    INDIRECT_TX_ALARM,
    NO_ALARM,
  } rx_alarm_t;

  /* state / frame management */
  norace bool m_lock;
  norace bool m_resume;
  norace ieee154_txframe_t *m_currentFrame;
  norace ieee154_txframe_t *m_lastFrame;

  /* variables for the unslotted CSMA-CA */
  norace ieee154_csma_t m_csma;
  norace ieee154_macMaxBE_t m_BE;
  norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs;
  norace ieee154_macMaxBE_t m_macMaxBE;
  norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries;
  norace ieee154_status_t m_txStatus;
  norace uint32_t m_transactionTime;
  norace bool m_indirectTxPending = FALSE;
  norace ieee154_macMaxFrameTotalWaitTime_t m_macMaxFrameTotalWaitTime;

  /* function / task prototypes */
  next_state_t tryReceive(bool startIndirectTxTimer);
  next_state_t tryTransmit();
  next_state_t trySwitchOff();
  void backupCurrentFrame();
  void restoreFrameFromBackup();  
  void updateState();
  void setCurrentFrame(ieee154_txframe_t *frame);
  void signalTxBroadcastDone(ieee154_txframe_t *frame, ieee154_status_t error);
  task void signalTxDoneTask();
  task void wasRxEnabledTask();
  task void startIndirectTxTimerTask();
  task void signalStartConfirmTask();

  command error_t Reset.init()
  {
    if (m_currentFrame)
      signal FrameTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW);
    if (m_lastFrame)
      signal FrameTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW);
    m_currentFrame = m_lastFrame = NULL;
    call IndirectTxWaitTimer.stop();
    return SUCCESS;
  }

  command ieee154_status_t MLME_START.request  (
                          uint16_t panID,
                          uint8_t logicalChannel,
                          uint8_t channelPage,
                          uint32_t startTime,
                          uint8_t beaconOrder,
                          uint8_t superframeOrder,
                          bool panCoordinator,
                          bool batteryLifeExtension,
                          bool coordRealignment,
                          ieee154_security_t *coordRealignSecurity,
                          ieee154_security_t *beaconSecurity)
  {
    ieee154_status_t status;
    ieee154_macShortAddress_t shortAddress = call MLME_GET.macShortAddress();

    // check parameters
    if ((coordRealignSecurity && coordRealignSecurity->SecurityLevel) ||
        (beaconSecurity && beaconSecurity->SecurityLevel))
      status = IEEE154_UNSUPPORTED_SECURITY;
    else if (shortAddress == 0xFFFF) 
      status = IEEE154_NO_SHORT_ADDRESS;
    else if (logicalChannel > 26 ||
        (channelPage != IEEE154_SUPPORTED_CHANNELPAGE) ||
        !(IEEE154_SUPPORTED_CHANNELS & ((uint32_t) 1 << logicalChannel)))
      status =  IEEE154_INVALID_PARAMETER;
    else if (beaconOrder != 15) 
      status = IEEE154_INVALID_PARAMETER;
    else {
      call MLME_SET.macPANId(panID);
      call MLME_SET.phyCurrentChannel(logicalChannel);
      call MLME_SET.macBeaconOrder(beaconOrder);
      call SetMacSuperframeOrder.set(superframeOrder);
      call SetMacPanCoordinator.set(panCoordinator);
      //TODO: check realignment
      post signalStartConfirmTask();
      status = IEEE154_SUCCESS;
    }      
    return status;
  }

  task void signalStartConfirmTask()
  {
    signal MLME_START.confirm(IEEE154_SUCCESS);
  }

  command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame)
  {
    if (m_currentFrame != NULL) {
      // we've not finished transmitting the current frame yet
      dbg_serial("DispatchUnslottedCsmaP", "Overflow\n");
      return IEEE154_TRANSACTION_OVERFLOW;
    } else {
      setCurrentFrame(frame);
      call Token.request();
      return IEEE154_SUCCESS;
    }
  }

  event void Token.granted()
  {
    updateState();
  }

  void setCurrentFrame(ieee154_txframe_t *frame)
  {
    ieee154_macDSN_t dsn = call MLME_GET.macDSN();
    frame->header->mhr[MHR_INDEX_SEQNO] = dsn++;
    call MLME_SET.macDSN(dsn);
    m_csma.NB = 0;
    m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs();
    m_csma.macMaxBE = m_macMaxBE = call MLME_GET.macMaxBE();
    m_csma.BE = call MLME_GET.macMinBE();
    if (call MLME_GET.macBattLifeExt() && m_csma.BE > 2)
      m_csma.BE = 2;
    m_BE = m_csma.BE;
    if (call GetIndirectTxFrame.get() == frame)
      m_macMaxFrameRetries =  0; // this is an indirect transmissions (never retransmit)
    else
      m_macMaxFrameRetries =  call MLME_GET.macMaxFrameRetries();
    m_transactionTime = IEEE154_SHR_DURATION + 
      (frame->headerLen + frame->payloadLen + 2) * IEEE154_SYMBOLS_PER_OCTET; // extra 2 for CRC
    if (frame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST)
      m_transactionTime += (IEEE154_aTurnaroundTime + IEEE154_aUnitBackoffPeriod + 
          11 * IEEE154_SYMBOLS_PER_OCTET); // 11 byte for the ACK PPDU
    // if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize) 
    //  m_transactionTime += call MLME_GET.macMinLIFSPeriod(); 
    // else 
    //  m_transactionTime += call MLME_GET.macMinSIFSPeriod(); 
    m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime();
    m_currentFrame = frame;
  }

  /** 
   * The updateState() function is called whenever some event happened that
   * might require a state transition; it implements a lock mechanism (m_lock)
   * to prevent race conditions. Whenever the lock is set a "done"-event (from
   * a RadioTx/RadioRx/RadioOff interface) is pending and will "soon" unset the
   * lock (and then updateState() will called again).  The updateState()
   * function decides about the next state by checking a list of possible
   * current states ordered by priority. Calling this function more than
   * necessary can do no harm.
   */ 

  void updateState()
  {
    next_state_t next;
    atomic {
      // long atomics are bad... but in this block, once the
      // current state has been determined only one branch will
      // be taken (there are no loops)
      if (m_lock || !call Token.isOwner())
        return;
      m_lock = TRUE; // lock

      // Check 1: was an indirect transmission successfully started 
      // and are we now waiting for a frame from the coordinator?
      if (m_indirectTxPending) {
        next = tryReceive(TRUE);
      }

      // Check 2: is some other operation (like MLME-SCAN or MLME-RESET) pending? 
      else if (call IsTokenRequested.getNow()) {
        if (call RadioOff.isOff()) {
          // nothing more to do... just release the Token
          m_lock = FALSE; // unlock
          dbg_serial("DispatchUnslottedCsmaP", "Token requested: releasing it.\n");
          call Token.release();
          return;
        } else 
          next = SWITCH_OFF;
      }

      // Check 3: is there a frame ready to transmit?
      else if (m_currentFrame != NULL) {
        next = tryTransmit();
      }

      // Check 4: should we be in receive mode?
      else if (call IsRxEnableActive.getNow()) {
        next = tryReceive(FALSE);
        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 next higher layer
          post wasRxEnabledTask();
        }
      }

      // Check 6: just make sure the radio is switched off  
      else {
        next = trySwitchOff();
        if (next == DO_NOTHING) {
          // nothing more to do... just release the Token
          m_lock = FALSE; // unlock
          dbg_serial("DispatchUnslottedCsmaP", "Releasing token\n");
          call Token.release();
          return;
        }
      }

      // if there is nothing to do, then we must clear the lock
      if (next == DO_NOTHING)
        m_lock = FALSE;
    } // atomic

    // put next state in operation (possibly keeping the lock)
    switch (next)
    {
      case SWITCH_OFF: ASSERT(call RadioOff.off() == SUCCESS); break;
      case WAIT_FOR_RXDONE: break;
      case WAIT_FOR_TXDONE: break;
      case DO_NOTHING: break;
    }
  }
  
  next_state_t tryTransmit()
  {
    // tries to transmit m_currentFrame
    next_state_t next;

    if (!call RadioOff.isOff())
      next = SWITCH_OFF;
    else {
      error_t res;
      res = call UnslottedCsmaCa.transmit(m_currentFrame, &m_csma);
      dbg("DispatchUnslottedCsmaP", "UnslottedCsmaCa.transmit() -> %lu\n", (uint32_t) res);
      next = WAIT_FOR_TXDONE; // this will NOT clear the lock
    }
    return next;
  }

  next_state_t tryReceive(bool startIndirectTxTimer)
  {
    next_state_t next;
    if (call RadioRx.isReceiving())
      next = DO_NOTHING;
    else if (!call RadioOff.isOff())
      next = SWITCH_OFF;
    else {
      call RadioRx.enableRx(0, 0);
      if (startIndirectTxTimer)
        post startIndirectTxTimerTask();
      next = WAIT_FOR_RXDONE;
    }
    return next;
  }

  next_state_t trySwitchOff()
  {
    next_state_t next;
    if (call RadioOff.isOff())
      next = DO_NOTHING;
    else
      next = SWITCH_OFF;
    return next;
  }

  async event void RadioOff.offDone() { m_lock = FALSE; updateState();}
  async event void RadioRx.enableRxDone() { m_lock = FALSE; updateState();}
  event void RxEnableStateChange.notify(bool whatever) { updateState();}

  event void IndirectTxWaitTimer.fired() 
  { 
    atomic {
      if (m_indirectTxPending) {
        m_indirectTxPending = FALSE; 
        post signalTxDoneTask(); 
      }
    }
  }

  task void startIndirectTxTimerTask()
  {
    call IndirectTxWaitTimer.startOneShot(m_macMaxFrameTotalWaitTime); 
  }

  async event void UnslottedCsmaCa.transmitDone(ieee154_txframe_t *frame, 
      ieee154_csma_t *csma, bool ackPendingFlag, error_t result)
  {
    bool done = TRUE;
    dbg("DispatchUnslottedCsmaP", "UnslottedCsmaCa.transmitDone() -> %lu\n", (uint32_t) result);
    m_resume = FALSE;

    switch (result)
    {
      case SUCCESS:
        // frame was successfully transmitted, if ACK was requested
        // then a matching ACK was successfully received as well   
        m_txStatus = IEEE154_SUCCESS;
        if (frame->payload[0] == CMD_FRAME_DATA_REQUEST &&
            ((frame->header->mhr[MHR_INDEX_FC1]) & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD) {
          // this was a data request frame
          m_txStatus = IEEE154_NO_DATA; // pessimistic 
          if (ackPendingFlag) {
            // the coordinator has data for us; switch to Rx 
            // to complete the indirect transmission         
            m_indirectTxPending = TRUE;
            m_lastFrame = m_currentFrame;
            m_currentFrame = NULL;
            ASSERT(call RadioRx.enableRx(0, 0) == SUCCESS);
            return;
          }
        }
        break;
      case FAIL:
        // The CSMA-CA algorithm failed: the frame was not transmitted,
        // because channel was never idle                              
        m_txStatus = IEEE154_CHANNEL_ACCESS_FAILURE;
        break;
      case ENOACK:
        // frame was transmitted, but we didn't receive an ACK (although
        // we requested an one). note: coordinator never retransmits an 
        // indirect transmission (see above) 
        if (m_macMaxFrameRetries > 0) {
          // retransmit: reinitialize CSMA-CA parameters
          done = FALSE;
          m_csma.NB = 0;
          m_csma.macMaxCsmaBackoffs = m_macMaxCSMABackoffs;
          m_csma.macMaxBE = m_macMaxBE;
          m_csma.BE = m_BE;
          m_macMaxFrameRetries -= 1;
        } else
          m_txStatus = IEEE154_NO_ACK;
        break;
      default: 
        ASSERT(0);
        break;
    }

    if (done) {
      m_lastFrame = m_currentFrame;
      m_currentFrame = NULL;
      post signalTxDoneTask();
    }  

    m_lock = FALSE;
    updateState();
  }

  task void signalTxDoneTask()
  {
    ieee154_txframe_t *lastFrame = m_lastFrame;
    ieee154_status_t status = m_txStatus;
    m_indirectTxPending = FALSE;
    m_lastFrame = NULL; // only now the next transmission can begin 
    if (lastFrame) {
      dbg("DispatchUnslottedCsmaP", "Transmit done, DSN: %lu, result: 0x%lx\n", 
          (uint32_t) MHR(lastFrame)[MHR_INDEX_SEQNO], (uint32_t) status);
      signal FrameTx.transmitDone(lastFrame, status);
    }
    updateState();
  }

  event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp)
  {
    // received a frame -> find out frame type and
    // signal it to responsible client component
    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];
    atomic {
      if (m_indirectTxPending) {
        message_t* frameBuf;
        call IndirectTxWaitTimer.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) ??
          m_txStatus = IEEE154_SUCCESS;
        frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame);
        signal IndirectTxWaitTimer.fired();
        return frameBuf;
      } else
        return signal FrameRx.received[frameType](frame);
    }
  }

  task void wasRxEnabledTask()
  {
    signal WasRxEnabled.notify(TRUE);
  }


  default event void FrameTx.transmitDone(ieee154_txframe_t *data, ieee154_status_t status) {}
  default event message_t* FrameRx.received[uint8_t client](message_t* data) {return data;}
  default async command bool IsRxEnableActive.getNow() {return FALSE;}

  default event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame) {return msg;}

  command error_t WasRxEnabled.enable() {return FAIL;}
  command error_t WasRxEnabled.disable() {return FAIL;}
  default event void MLME_START.confirm(ieee154_status_t status) {}
}

Index: PibP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/lib/mac/tkn154/PibP.nc,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** PibP.nc	4 Mar 2009 18:31:24 -0000	1.5
--- PibP.nc	5 Mar 2009 10:07:12 -0000	1.6
***************
*** 63,68 ****
    {
      interface Get<bool> as PromiscuousModeGet;
!     interface Init as FrameDispatchReset;
!     interface Init as FrameDispatchQueueReset;
      interface Init as MacReset;
      interface SplitControl as RadioControl;
--- 63,68 ----
    {
      interface Get<bool> as PromiscuousModeGet;
!     interface Init as DispatchReset;
!     interface Init as DispatchQueueReset;
      interface Init as MacReset;
      interface SplitControl as RadioControl;
***************
*** 207,213 ****
    {
      ASSERT(result == SUCCESS);
!     call FrameDispatchReset.init();       // resets the CAP component(s), spool out frames
!     call FrameDispatchQueueReset.init();  // resets the CAP queue component(s), spool out frames
!     call MacReset.init();       // resets the remaining components
      m_resetSpin = 5;
      post resetSpinTask();
--- 207,213 ----
    {
      ASSERT(result == SUCCESS);
!     call DispatchReset.init();       // resets the dispatch component(s), spools out frames
!     call DispatchQueueReset.init();  // resets the dispatch queue component(s), spools out frames
!     call MacReset.init();            // resets the remaining components
      m_resetSpin = 5;
      post resetSpinTask();
***************
*** 218,223 ****
      if (m_resetSpin == 2) {
        // just to be safe...
!       call FrameDispatchReset.init();       
!       call FrameDispatchQueueReset.init();  
        call MacReset.init();       
      }
--- 218,223 ----
      if (m_resetSpin == 2) {
        // just to be safe...
!       call DispatchReset.init();       
!       call DispatchQueueReset.init();  
        call MacReset.init();       
      }

Index: TKN154BeaconEnabledP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/lib/mac/tkn154/TKN154BeaconEnabledP.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** TKN154BeaconEnabledP.nc	4 Mar 2009 18:31:32 -0000	1.1
--- TKN154BeaconEnabledP.nc	5 Mar 2009 10:07:13 -0000	1.2
***************
*** 137,146 ****
  #ifndef IEEE154_BEACON_SYNC_DISABLED
               BeaconSynchronizeP,
!              new FrameDispatchQueueP() as DeviceCapQueue,
!              new SlottedFrameDispatchP(INCOMING_SUPERFRAME) as DeviceCap,
  #else
               NoBeaconSynchronizeP as BeaconSynchronizeP,
!              new NoFrameDispatchQueueP() as DeviceCapQueue,
!              new NoSlottedFrameDispatchP(INCOMING_SUPERFRAME) as DeviceCap,
  #endif
               NoDeviceCfpP as DeviceCfp,
--- 137,146 ----
  #ifndef IEEE154_BEACON_SYNC_DISABLED
               BeaconSynchronizeP,
!              new DispatchQueueP() as DeviceCapQueue,
!              new DispatchSlottedCsmaP(INCOMING_SUPERFRAME) as DeviceCap,
  #else
               NoBeaconSynchronizeP as BeaconSynchronizeP,
!              new NoDispatchQueueP() as DeviceCapQueue,
!              new NoDispatchSlottedCsmaP(INCOMING_SUPERFRAME) as DeviceCap,
  #endif
               NoDeviceCfpP as DeviceCfp,
***************
*** 148,157 ****
  #ifndef IEEE154_BEACON_TX_DISABLED
               BeaconTransmitP,
!              new FrameDispatchQueueP() as CoordCapQueue,
!              new SlottedFrameDispatchP(OUTGOING_SUPERFRAME) as CoordCap,
  #else
               NoBeaconTransmitP as BeaconTransmitP,
!              new NoFrameDispatchQueueP() as CoordCapQueue,
!              new NoSlottedFrameDispatchP(OUTGOING_SUPERFRAME) as CoordCap,
  #endif
               NoCoordCfpP as CoordCfp,
--- 148,157 ----
  #ifndef IEEE154_BEACON_TX_DISABLED
               BeaconTransmitP,
!              new DispatchQueueP() as CoordCapQueue,
!              new DispatchSlottedCsmaP(OUTGOING_SUPERFRAME) as CoordCap,
  #else
               NoBeaconTransmitP as BeaconTransmitP,
!              new NoDispatchQueueP() as CoordCapQueue,
!              new NoDispatchSlottedCsmaP(OUTGOING_SUPERFRAME) as CoordCap,
  #endif
               NoCoordCfpP as CoordCfp,
***************
*** 403,416 ****
    /* --------------------- CAP (incoming superframe) -------------------- */
  
!   PibP.FrameDispatchQueueReset -> DeviceCapQueue;
    DeviceCapQueue.Queue -> DeviceCapQueueC;
    DeviceCapQueue.FrameTxCsma -> DeviceCap;
  
!   PibP.FrameDispatchQueueReset -> CoordCapQueue;
    CoordCapQueue.Queue -> CoordCapQueueC;
    CoordCapQueue.FrameTxCsma -> CoordCap;
    
    components new RadioClientC() as DeviceCapRadioClient;
!   PibP.FrameDispatchReset -> DeviceCap;
    DeviceCap.CapEndAlarm = Alarm3;
    DeviceCap.BLEAlarm = Alarm4;
--- 403,416 ----
    /* --------------------- CAP (incoming superframe) -------------------- */
  
!   PibP.DispatchQueueReset -> DeviceCapQueue;
    DeviceCapQueue.Queue -> DeviceCapQueueC;
    DeviceCapQueue.FrameTxCsma -> DeviceCap;
  
!   PibP.DispatchQueueReset -> CoordCapQueue;
    CoordCapQueue.Queue -> CoordCapQueueC;
    CoordCapQueue.FrameTxCsma -> CoordCap;
    
    components new RadioClientC() as DeviceCapRadioClient;
!   PibP.DispatchReset -> DeviceCap;
    DeviceCap.CapEndAlarm = Alarm3;
    DeviceCap.BLEAlarm = Alarm4;
***************
*** 441,445 ****
    components new RadioClientC() as CoordCapRadioClient, 
               new BackupP(ieee154_cap_frame_backup_t);
!   PibP.FrameDispatchReset -> CoordCap;
    CoordCap.CapEndAlarm = Alarm7;
    CoordCap.BLEAlarm = Alarm8;
--- 441,445 ----
    components new RadioClientC() as CoordCapRadioClient, 
               new BackupP(ieee154_cap_frame_backup_t);
!   PibP.DispatchReset -> CoordCap;
    CoordCap.CapEndAlarm = Alarm7;
    CoordCap.BLEAlarm = Alarm8;

Index: TKN154NonBeaconEnabledP.nc
===================================================================
RCS file: /cvsroot/tinyos/tinyos-2.x/tos/lib/mac/tkn154/TKN154NonBeaconEnabledP.nc,v
retrieving revision 1.1
retrieving revision 1.2
diff -C2 -d -r1.1 -r1.2
*** TKN154NonBeaconEnabledP.nc	4 Mar 2009 18:31:37 -0000	1.1
--- TKN154NonBeaconEnabledP.nc	5 Mar 2009 10:07:13 -0000	1.2
***************
*** 119,124 ****
               NoDisassociateP as DisassociateP,
  #endif
!              new FrameDispatchQueueP() as FrameDispatchQueueP,
!              UnslottedFrameDispatchP as FrameDispatchP,
  
  #ifndef IEEE154_RXENABLE_DISABLED
--- 119,124 ----
               NoDisassociateP as DisassociateP,
  #endif
!              new DispatchQueueP() as DispatchQueueP,
!              DispatchUnslottedCsmaP as DispatchP,
  
  #ifndef IEEE154_RXENABLE_DISABLED
***************
*** 143,147 ****
               new PoolC(ieee154_txframe_t, TXFRAME_POOL_SIZE) as TxFramePoolP,
               new PoolC(ieee154_txcontrol_t, TXCONTROL_POOL_SIZE) as TxControlPoolP,
!              new QueueC(ieee154_txframe_t*, CAP_TX_QUEUE_SIZE) as FrameDispatchQueueC;
  
    components MainC;
--- 143,147 ----
               new PoolC(ieee154_txframe_t, TXFRAME_POOL_SIZE) as TxFramePoolP,
               new PoolC(ieee154_txcontrol_t, TXCONTROL_POOL_SIZE) as TxControlPoolP,
!              new QueueC(ieee154_txframe_t*, CAP_TX_QUEUE_SIZE) as DispatchQueueC;
  
    components MainC;
***************
*** 152,156 ****
  
    /* MLME */
!   MLME_START = FrameDispatchP;
    MLME_ASSOCIATE = AssociateP;
    MLME_DISASSOCIATE = DisassociateP;
--- 152,156 ----
  
    /* MLME */
!   MLME_START = DispatchP;
    MLME_ASSOCIATE = AssociateP;
    MLME_DISASSOCIATE = DisassociateP;
***************
*** 195,201 ****
  
    PibP.MacReset -> AssociateP;
!   AssociateP.AssociationRequestRx -> FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_REQUEST];
!   AssociateP.AssociationRequestTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   AssociateP.AssociationResponseExtracted -> FrameDispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_RESPONSE];
    AssociateP.AssociationResponseTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)];
    AssociateP.DataRequest -> PollP.DataRequest[ASSOCIATE_POLL_CLIENT];
--- 195,201 ----
  
    PibP.MacReset -> AssociateP;
!   AssociateP.AssociationRequestRx -> DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_REQUEST];
!   AssociateP.AssociationRequestTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   AssociateP.AssociationResponseExtracted -> DispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_ASSOCIATION_RESPONSE];
    AssociateP.AssociationResponseTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)];
    AssociateP.DataRequest -> PollP.DataRequest[ASSOCIATE_POLL_CLIENT];
***************
*** 213,222 ****
    PibP.MacReset -> DisassociateP;
    DisassociateP.DisassociationIndirectTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)];
!   DisassociateP.DisassociationDirectTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   DisassociateP.DisassociationToCoord -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
    DisassociateP.DisassociationExtractedFromCoord -> 
!     FrameDispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
    DisassociateP.DisassociationRxFromDevice -> 
!     FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
    DisassociateP.TxFramePool -> TxFramePoolP;
    DisassociateP.TxControlPool -> TxControlPoolP;
--- 213,222 ----
    PibP.MacReset -> DisassociateP;
    DisassociateP.DisassociationIndirectTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)];
!   DisassociateP.DisassociationDirectTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   DisassociateP.DisassociationToCoord -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
    DisassociateP.DisassociationExtractedFromCoord -> 
!     DispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
    DisassociateP.DisassociationRxFromDevice -> 
!     DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
    DisassociateP.TxFramePool -> TxFramePoolP;
    DisassociateP.TxControlPool -> TxControlPoolP;
***************
*** 228,233 ****
    /* ------------------ Data Transmission (MCPS-DATA) ------------------- */
  
!   DataP.DeviceCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   DataP.CoordCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
    DataP.DeviceCapRx -> PollP.DataRx;                          
    DataP.DeviceCapRx -> PromiscuousModeP.FrameRx;              
--- 228,233 ----
    /* ------------------ Data Transmission (MCPS-DATA) ------------------- */
  
!   DataP.DeviceCapTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   DataP.CoordCapTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
    DataP.DeviceCapRx -> PollP.DataRx;                          
    DataP.DeviceCapRx -> PromiscuousModeP.FrameRx;              
***************
*** 236,240 ****
    DataP.FrameUtility -> PibP;
    DataP.Frame -> PibP;
!   DataP.PurgeDirect -> FrameDispatchQueueP;
    DataP.PurgeIndirect -> IndirectTxP;
    DataP.MLME_GET -> PibP;
--- 236,240 ----
    DataP.FrameUtility -> PibP;
    DataP.Frame -> PibP;
!   DataP.PurgeDirect -> DispatchQueueP;
    DataP.PurgeIndirect -> IndirectTxP;
    DataP.MLME_GET -> PibP;
***************
*** 245,250 ****
  
    PibP.MacReset -> PollP;
!   PollP.PollTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   PollP.DataExtracted -> FrameDispatchP.FrameExtracted[FC1_FRAMETYPE_DATA];
    PollP.FrameUtility -> PibP;
    PollP.TxFramePool -> TxFramePoolP;
--- 245,250 ----
  
    PibP.MacReset -> PollP;
!   PollP.PollTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   PollP.DataExtracted -> DispatchP.FrameExtracted[FC1_FRAMETYPE_DATA];
    PollP.FrameUtility -> PibP;
    PollP.TxFramePool -> TxFramePoolP;
***************
*** 256,261 ****
  
    PibP.MacReset -> IndirectTxP;
!   IndirectTxP.CoordCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   IndirectTxP.DataRequestRx -> FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DATA_REQUEST];
    IndirectTxP.MLME_GET -> PibP;
    IndirectTxP.FrameUtility -> PibP;
--- 256,261 ----
  
    PibP.MacReset -> IndirectTxP;
!   IndirectTxP.CoordCapTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   IndirectTxP.DataRequestRx -> DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DATA_REQUEST];
    IndirectTxP.MLME_GET -> PibP;
    IndirectTxP.FrameUtility -> PibP;
***************
*** 267,272 ****
  
    PibP.MacReset -> CoordRealignmentP;
!   CoordRealignmentP.CoordRealignmentTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   CoordRealignmentP.OrphanNotificationRx -> FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ORPHAN_NOTIFICATION];
    CoordRealignmentP.FrameUtility -> PibP;
    CoordRealignmentP.Frame -> PibP;
--- 267,272 ----
  
    PibP.MacReset -> CoordRealignmentP;
!   CoordRealignmentP.CoordRealignmentTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
!   CoordRealignmentP.OrphanNotificationRx -> DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ORPHAN_NOTIFICATION];
    CoordRealignmentP.FrameUtility -> PibP;
    CoordRealignmentP.Frame -> PibP;
***************
*** 276,304 ****
    CoordRealignmentP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress;
  
!   /* --------------------- FrameDispatchP -------------------- */
  
!   PibP.FrameDispatchReset -> FrameDispatchP;
!   PibP.FrameDispatchQueueReset -> FrameDispatchQueueP;
!   FrameDispatchQueueP.Queue -> FrameDispatchQueueC;
!   FrameDispatchQueueP.FrameTxCsma -> FrameDispatchP;
    
!   components new RadioClientC() as FrameDispatchRadioClient;
!   PibP.FrameDispatchReset -> FrameDispatchP;
!   FrameDispatchP.IndirectTxWaitTimer = Timer4;
!   FrameDispatchP.Token -> FrameDispatchRadioClient;
!   FrameDispatchP.SetMacSuperframeOrder -> PibP.SetMacSuperframeOrder;
!   FrameDispatchP.SetMacPanCoordinator -> PibP.SetMacPanCoordinator;
!   FrameDispatchP.IsTokenRequested -> FrameDispatchRadioClient;
!   FrameDispatchP.IsRxEnableActive -> RxEnableP.IsRxEnableActive;
!   FrameDispatchP.GetIndirectTxFrame -> IndirectTxP;
!   FrameDispatchP.RxEnableStateChange -> RxEnableP.RxEnableStateChange;  
!   FrameDispatchP.FrameUtility -> PibP;
!   FrameDispatchP.UnslottedCsmaCa -> FrameDispatchRadioClient;
!   FrameDispatchP.RadioRx -> FrameDispatchRadioClient;
!   FrameDispatchP.RadioOff -> FrameDispatchRadioClient;
!   FrameDispatchP.MLME_GET -> PibP;
!   FrameDispatchP.MLME_SET -> PibP.MLME_SET;
!   FrameDispatchP.TimeCalc -> PibP;
!   FrameDispatchP.Leds = Leds;
  
    /* -------------------------- promiscuous mode ------------------------ */
--- 276,304 ----
    CoordRealignmentP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress;
  
!   /* --------------------- DispatchP -------------------- */
  
!   PibP.DispatchReset -> DispatchP;
!   PibP.DispatchQueueReset -> DispatchQueueP;
!   DispatchQueueP.Queue -> DispatchQueueC;
!   DispatchQueueP.FrameTxCsma -> DispatchP;
    
!   components new RadioClientC() as DispatchRadioClient;
!   PibP.DispatchReset -> DispatchP;
!   DispatchP.IndirectTxWaitTimer = Timer4;
!   DispatchP.Token -> DispatchRadioClient;
!   DispatchP.SetMacSuperframeOrder -> PibP.SetMacSuperframeOrder;
!   DispatchP.SetMacPanCoordinator -> PibP.SetMacPanCoordinator;
!   DispatchP.IsTokenRequested -> DispatchRadioClient;
!   DispatchP.IsRxEnableActive -> RxEnableP.IsRxEnableActive;
!   DispatchP.GetIndirectTxFrame -> IndirectTxP;
!   DispatchP.RxEnableStateChange -> RxEnableP.RxEnableStateChange;  
!   DispatchP.FrameUtility -> PibP;
!   DispatchP.UnslottedCsmaCa -> DispatchRadioClient;
!   DispatchP.RadioRx -> DispatchRadioClient;
!   DispatchP.RadioOff -> DispatchRadioClient;
!   DispatchP.MLME_GET -> PibP;
!   DispatchP.MLME_SET -> PibP.MLME_SET;
!   DispatchP.TimeCalc -> PibP;
!   DispatchP.Leds = Leds;
  
    /* -------------------------- promiscuous mode ------------------------ */
***************
*** 315,320 ****
    PibP.MacReset -> RxEnableP;
    RxEnableP.TimeCalc -> PibP.TimeCalc;
!   RxEnableP.WasRxEnabled -> FrameDispatchP.WasRxEnabled;
!   RxEnableP.WasRxEnabled -> FrameDispatchP.WasRxEnabled;
    RxEnableP.RxEnableTimer = Timer5;
  
--- 315,320 ----
    PibP.MacReset -> RxEnableP;
    RxEnableP.TimeCalc -> PibP.TimeCalc;
!   RxEnableP.WasRxEnabled -> DispatchP.WasRxEnabled;
!   RxEnableP.WasRxEnabled -> DispatchP.WasRxEnabled;
    RxEnableP.RxEnableTimer = Timer5;
  

--- FrameDispatchQueueP.nc DELETED ---

--- SlottedFrameDispatchP.nc DELETED ---

--- UnslottedFrameDispatchP.nc DELETED ---



More information about the Tinyos-2-commits mailing list