--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@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) {}
+}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@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;}
+}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@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) {}
+}
+++ /dev/null
-/*
- * 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$
- * $Date$
- * @author Jan Hauer <hauer@tkn.tu-berlin.de>
- * ========================================================================
- */
-#include "TKN154_MAC.h"
-generic module FrameDispatchQueueP() {
- 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) {}
-}
uses
{
interface Get<bool> as PromiscuousModeGet;
- interface Init as FrameDispatchReset;
- interface Init as FrameDispatchQueueReset;
+ interface Init as DispatchReset;
+ interface Init as DispatchQueueReset;
interface Init as MacReset;
interface SplitControl as RadioControl;
interface Random;
event void RadioControl.stopDone(error_t result)
{
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
+ 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();
}
{
if (m_resetSpin == 2) {
// just to be safe...
- call FrameDispatchReset.init();
- call FrameDispatchQueueReset.init();
+ call DispatchReset.init();
+ call DispatchQueueReset.init();
call MacReset.init();
}
if (m_resetSpin--) {
+++ /dev/null
-/*
- * 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$
- * $Date$
- * @author Jan Hauer <hauer@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 SlottedFrameDispatchP(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("SlottedFrameDispatchP",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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "Overflow\n");
- return IEEE154_TRANSACTION_OVERFLOW;
- } else {
- setCurrentFrame(frame);
- dbg("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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("SlottedFrameDispatchP", "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;}
-}
#ifndef IEEE154_BEACON_SYNC_DISABLED
BeaconSynchronizeP,
- new FrameDispatchQueueP() as DeviceCapQueue,
- new SlottedFrameDispatchP(INCOMING_SUPERFRAME) as DeviceCap,
+ new DispatchQueueP() as DeviceCapQueue,
+ new DispatchSlottedCsmaP(INCOMING_SUPERFRAME) as DeviceCap,
#else
NoBeaconSynchronizeP as BeaconSynchronizeP,
- new NoFrameDispatchQueueP() as DeviceCapQueue,
- new NoSlottedFrameDispatchP(INCOMING_SUPERFRAME) as DeviceCap,
+ new NoDispatchQueueP() as DeviceCapQueue,
+ new NoDispatchSlottedCsmaP(INCOMING_SUPERFRAME) as DeviceCap,
#endif
NoDeviceCfpP as DeviceCfp,
#ifndef IEEE154_BEACON_TX_DISABLED
BeaconTransmitP,
- new FrameDispatchQueueP() as CoordCapQueue,
- new SlottedFrameDispatchP(OUTGOING_SUPERFRAME) as CoordCap,
+ new DispatchQueueP() as CoordCapQueue,
+ new DispatchSlottedCsmaP(OUTGOING_SUPERFRAME) as CoordCap,
#else
NoBeaconTransmitP as BeaconTransmitP,
- new NoFrameDispatchQueueP() as CoordCapQueue,
- new NoSlottedFrameDispatchP(OUTGOING_SUPERFRAME) as CoordCap,
+ new NoDispatchQueueP() as CoordCapQueue,
+ new NoDispatchSlottedCsmaP(OUTGOING_SUPERFRAME) as CoordCap,
#endif
NoCoordCfpP as CoordCfp,
/* --------------------- CAP (incoming superframe) -------------------- */
- PibP.FrameDispatchQueueReset -> DeviceCapQueue;
+ PibP.DispatchQueueReset -> DeviceCapQueue;
DeviceCapQueue.Queue -> DeviceCapQueueC;
DeviceCapQueue.FrameTxCsma -> DeviceCap;
- PibP.FrameDispatchQueueReset -> CoordCapQueue;
+ PibP.DispatchQueueReset -> CoordCapQueue;
CoordCapQueue.Queue -> CoordCapQueueC;
CoordCapQueue.FrameTxCsma -> CoordCap;
components new RadioClientC() as DeviceCapRadioClient;
- PibP.FrameDispatchReset -> DeviceCap;
+ PibP.DispatchReset -> DeviceCap;
DeviceCap.CapEndAlarm = Alarm3;
DeviceCap.BLEAlarm = Alarm4;
DeviceCap.IndirectTxWaitAlarm = Alarm5;
components new RadioClientC() as CoordCapRadioClient,
new BackupP(ieee154_cap_frame_backup_t);
- PibP.FrameDispatchReset -> CoordCap;
+ PibP.DispatchReset -> CoordCap;
CoordCap.CapEndAlarm = Alarm7;
CoordCap.BLEAlarm = Alarm8;
CoordCap.Token -> CoordCapRadioClient;
#else
NoDisassociateP as DisassociateP,
#endif
- new FrameDispatchQueueP() as FrameDispatchQueueP,
- UnslottedFrameDispatchP as FrameDispatchP,
+ new DispatchQueueP() as DispatchQueueP,
+ DispatchUnslottedCsmaP as DispatchP,
#ifndef IEEE154_RXENABLE_DISABLED
RxEnableP,
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;
+ new QueueC(ieee154_txframe_t*, CAP_TX_QUEUE_SIZE) as DispatchQueueC;
components MainC;
MCPS_PURGE = DataP;
/* MLME */
- MLME_START = FrameDispatchP;
+ MLME_START = DispatchP;
MLME_ASSOCIATE = AssociateP;
MLME_DISASSOCIATE = DisassociateP;
MLME_BEACON_NOTIFY = ScanP;
/* -------------------- Association (MLME-ASSOCIATE) -------------------- */
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.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];
AssociateP.ResponseTimeout = Timer2;
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.DisassociationDirectTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
+ DisassociateP.DisassociationToCoord -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
DisassociateP.DisassociationExtractedFromCoord ->
- FrameDispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
+ DispatchP.FrameExtracted[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
DisassociateP.DisassociationRxFromDevice ->
- FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
+ DispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DISASSOCIATION_NOTIFICATION];
DisassociateP.TxFramePool -> TxFramePoolP;
DisassociateP.TxControlPool -> TxControlPoolP;
DisassociateP.MLME_GET -> PibP;
/* ------------------ Data Transmission (MCPS-DATA) ------------------- */
- DataP.DeviceCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
- DataP.CoordCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
+ DataP.DeviceCapTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
+ DataP.CoordCapTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
DataP.DeviceCapRx -> PollP.DataRx;
DataP.DeviceCapRx -> PromiscuousModeP.FrameRx;
DataP.TxFramePool -> TxFramePoolP;
DataP.IndirectTx -> IndirectTxP.FrameTx[unique(INDIRECT_TX_CLIENT)];
DataP.FrameUtility -> PibP;
DataP.Frame -> PibP;
- DataP.PurgeDirect -> FrameDispatchQueueP;
+ DataP.PurgeDirect -> DispatchQueueP;
DataP.PurgeIndirect -> IndirectTxP;
DataP.MLME_GET -> PibP;
DataP.Packet -> PibP;
/* ------------------------ Polling (MLME-POLL) ----------------------- */
PibP.MacReset -> PollP;
- PollP.PollTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
- PollP.DataExtracted -> FrameDispatchP.FrameExtracted[FC1_FRAMETYPE_DATA];
+ PollP.PollTx -> DispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
+ PollP.DataExtracted -> DispatchP.FrameExtracted[FC1_FRAMETYPE_DATA];
PollP.FrameUtility -> PibP;
PollP.TxFramePool -> TxFramePoolP;
PollP.TxControlPool -> TxControlPoolP;
/* ---------------------- Indirect transmission ----------------------- */
PibP.MacReset -> IndirectTxP;
- IndirectTxP.CoordCapTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
- IndirectTxP.DataRequestRx -> FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_DATA_REQUEST];
+ 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;
IndirectTxP.IndirectTxTimeout = Timer3;
/* ---------------------------- Realignment --------------------------- */
PibP.MacReset -> CoordRealignmentP;
- CoordRealignmentP.CoordRealignmentTx -> FrameDispatchQueueP.FrameTx[unique(CAP_TX_CLIENT)];
- CoordRealignmentP.OrphanNotificationRx -> FrameDispatchP.FrameRx[FC1_FRAMETYPE_CMD + CMD_FRAME_ORPHAN_NOTIFICATION];
+ 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;
CoordRealignmentP.TxFramePool -> TxFramePoolP;
CoordRealignmentP.MLME_GET -> PibP;
CoordRealignmentP.LocalExtendedAddress -> PibP.GetLocalExtendedAddress;
- /* --------------------- FrameDispatchP -------------------- */
+ /* --------------------- DispatchP -------------------- */
- PibP.FrameDispatchReset -> FrameDispatchP;
- PibP.FrameDispatchQueueReset -> FrameDispatchQueueP;
- FrameDispatchQueueP.Queue -> FrameDispatchQueueC;
- FrameDispatchQueueP.FrameTxCsma -> FrameDispatchP;
+ PibP.DispatchReset -> DispatchP;
+ PibP.DispatchQueueReset -> DispatchQueueP;
+ DispatchQueueP.Queue -> DispatchQueueC;
+ DispatchQueueP.FrameTxCsma -> DispatchP;
- 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;
+ 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 ------------------------ */
PibP.MacReset -> RxEnableP;
RxEnableP.TimeCalc -> PibP.TimeCalc;
- RxEnableP.WasRxEnabled -> FrameDispatchP.WasRxEnabled;
- RxEnableP.WasRxEnabled -> FrameDispatchP.WasRxEnabled;
+ RxEnableP.WasRxEnabled -> DispatchP.WasRxEnabled;
+ RxEnableP.WasRxEnabled -> DispatchP.WasRxEnabled;
RxEnableP.RxEnableTimer = Timer5;
/* ------------------------------- PIB -------------------------------- */
+++ /dev/null
-/*
- * 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$
- * $Date$
- * @author Jan Hauer <hauer@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 UnslottedFrameDispatchP
-{
- 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("UnslottedFrameDispatchP", "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("UnslottedFrameDispatchP", "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("UnslottedFrameDispatchP", "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("UnslottedFrameDispatchP", "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("UnslottedFrameDispatchP", "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("UnslottedFrameDispatchP", "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) {}
-}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+ /** Empty placeholder component for DispatchQueueP. */
+
+#include "TKN154_MAC.h"
+generic module NoDispatchQueueP() {
+ 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
+{
+ command error_t Reset.init() { return SUCCESS; }
+
+ command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame)
+ {
+ return IEEE154_TRANSACTION_OVERFLOW;
+ }
+
+ event void FrameTxCsma.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) { }
+
+ event message_t* SubFrameExtracted.received(message_t* frame) { return 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)
+ {
+ return IEEE154_INVALID_HANDLE;
+ }
+
+ default event void Purge.purgeDone(ieee154_txframe_t *txFrame, ieee154_status_t status){}
+}
--- /dev/null
+/*
+ * 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$
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+ /** Empty placeholder component for DispatchSlottedCsmaP. */
+
+#include "TKN154_PHY.h"
+#include "TKN154_MAC.h"
+
+generic module NoDispatchSlottedCsmaP(uint8_t superframeDirection)
+{
+ 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
+{
+ command error_t Reset.init() { return SUCCESS; }
+
+ async event void TokenTransferred.transferred() { }
+
+ command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) { return IEEE154_TRANSACTION_OVERFLOW; }
+
+ async event void RadioOff.offDone(){ }
+
+ async event void RadioRx.enableRxDone(){}
+
+ async event void CapEndAlarm.fired(){ }
+
+ async event void BLEAlarm.fired(){ }
+
+ event void RxEnableStateChange.notify(bool whatever){ }
+
+ async event void BroadcastAlarm.fired(){ }
+
+ async event void IndirectTxWaitAlarm.fired() { }
+
+ async event void SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma,
+ bool ackPendingFlag, uint16_t remainingBackoff, error_t result) { }
+
+ event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp) { return frame; }
+
+ async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame) { }
+
+ event void Token.granted() { }
+
+ command error_t WasRxEnabled.enable(){return FAIL;}
+ command error_t WasRxEnabled.disable(){return FAIL;}
+}
+++ /dev/null
-/*
- * 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$
- * $Date$
- * @author Jan Hauer <hauer@tkn.tu-berlin.de>
- * ========================================================================
- */
-
- /** Empty placeholder component for FrameDispatchQueueP. */
-
-#include "TKN154_MAC.h"
-generic module NoFrameDispatchQueueP() {
- 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
-{
- command error_t Reset.init() { return SUCCESS; }
-
- command ieee154_status_t FrameTx.transmit[uint8_t client](ieee154_txframe_t *txFrame)
- {
- return IEEE154_TRANSACTION_OVERFLOW;
- }
-
- event void FrameTxCsma.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status) { }
-
- event message_t* SubFrameExtracted.received(message_t* frame) { return 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)
- {
- return IEEE154_INVALID_HANDLE;
- }
-
- default event void Purge.purgeDone(ieee154_txframe_t *txFrame, ieee154_status_t status){}
-}
+++ /dev/null
-/*
- * 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$
- * $Date$
- * @author Jan Hauer <hauer@tkn.tu-berlin.de>
- * ========================================================================
- */
-
- /** Empty placeholder component for SlottedFrameDispatchP. */
-
-#include "TKN154_PHY.h"
-#include "TKN154_MAC.h"
-
-generic module NoSlottedFrameDispatchP(uint8_t superframeDirection)
-{
- 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
-{
- command error_t Reset.init() { return SUCCESS; }
-
- async event void TokenTransferred.transferred() { }
-
- command ieee154_status_t FrameTx.transmit(ieee154_txframe_t *frame) { return IEEE154_TRANSACTION_OVERFLOW; }
-
- async event void RadioOff.offDone(){ }
-
- async event void RadioRx.enableRxDone(){}
-
- async event void CapEndAlarm.fired(){ }
-
- async event void BLEAlarm.fired(){ }
-
- event void RxEnableStateChange.notify(bool whatever){ }
-
- async event void BroadcastAlarm.fired(){ }
-
- async event void IndirectTxWaitAlarm.fired() { }
-
- async event void SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma,
- bool ackPendingFlag, uint16_t remainingBackoff, error_t result) { }
-
- event message_t* RadioRx.received(message_t* frame, const ieee154_timestamp_t *timestamp) { return frame; }
-
- async command ieee154_status_t BroadcastTx.transmitNow(ieee154_txframe_t *frame) { }
-
- event void Token.granted() { }
-
- command error_t WasRxEnabled.enable(){return FAIL;}
- command error_t WasRxEnabled.disable(){return FAIL;}
-}