event void Token.granted()
{
bool missed = FALSE;
+ call Debug.flush();
call Debug.log(LEVEL_INFO,SyncP_GOT_RESOURCE, m_lastBeaconRxTime+m_beaconInterval,
m_beaconInterval, (m_updatePending<<1)+m_tracking);
if (m_updatePending){
async event void TrackAlarm.fired()
{
- call Debug.log(LEVEL_IMPORTANT,SyncP_SWITCHOFF, 0,0,0);
+ call Debug.log(LEVEL_IMPORTANT,SyncP_TRACK_ALARM, m_state,m_lastBeaconRxTime,m_dt);
atomic {
switch (m_state)
{
call BeaconRx.prepare();
break;
case S_RADIO_OFF:
- call Debug.log(LEVEL_INFO, SyncP_SWITCHOFF, 0, 0,0);
call RadioOff.off();
break;
}
async event void BeaconRx.prepareDone()
{
+ error_t result;
if (m_state == S_FIRST_SCAN){
m_state = S_RADIO_OFF;
atomic {
}
} else {
m_state = S_RADIO_OFF;
- call BeaconRx.receive(&m_lastBeaconRxRefTime, m_dt-RX_LAG);
- call Debug.log(LEVEL_IMPORTANT,SyncP_RX_ON, call TrackAlarm.getNow(),m_lastBeaconRxTime+m_dt,RX_LAG);
+ result = call BeaconRx.receive(&m_lastBeaconRxRefTime, m_dt-RX_LAG);
+ call Debug.log(LEVEL_IMPORTANT,SyncP_RX_ON, m_lastBeaconRxTime, call TrackAlarm.getNow(), m_dt+RX_DURATION);
+ if (result != SUCCESS)
+ call Debug.log(LEVEL_IMPORTANT,SyncP_RADIO_BUSY, result, 0, 0);
call TrackAlarm.startAt(m_lastBeaconRxTime, m_dt + RX_DURATION);
}
}
mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK,mhr[MHR_INDEX_SEQNO]);
if (!m_beaconSwapBufferReady || !call FrameUtility.isBeaconFromCoord(frame))
{
+ call Debug.log(LEVEL_IMPORTANT,SyncP_RX_GARBAGE, m_beaconSwapBufferReady, 0, 0);
return frame;
} else {
message_t *tmp = m_beaconBufferPtr;
event void Token.granted()
{
+ call Debug.flush();
call Debug.log(LEVEL_INFO, StartP_GOT_RESOURCE, m_lastBeaconTxTime, m_beaconInterval, m_requests);
if (m_requests & REQUEST_REALIGNMENT_DONE_PENDING){
// unlikely to occur: we have not yet received a done()
m_framePendingBit = TRUE;
else
m_framePendingBit = FALSE;
- memcpy(m_gtsField, &frame->payload[0], gtsFieldLength);
+ memcpy(m_gtsField, &frame->payload[2], gtsFieldLength);
if (frame->payload[1] & 0x10){
// BLE is active; calculate the time offset from slot0
m_BLELen = IEEE154_SHR_DURATION +
norace ieee154_txframe_t *m_bcastFrame;
norace ieee154_txframe_t *m_lastFrame;
norace ieee154_macMaxBE_t m_BE;
+ norace ieee154_macMaxBE_t m_NB;
norace ieee154_macMaxBE_t m_numCCA;
- norace ieee154_macMaxCSMABackoffs_t m_allowedBackoffs;
+ norace ieee154_macMaxCSMABackoffs_t m_macMaxCSMABackoffs;
+ norace ieee154_macMaxFrameRetries_t m_macMaxFrameRetries;
norace ieee154_macMaxBE_t m_macMaxBE;
+ norace ieee154_macMinBE_t m_macMinBE;
norace uint16_t m_backoff;
norace uint16_t m_backoffElapsed;
norace ieee154_status_t m_result;
actualCapLen, call CapStart.getNow()+ actualCapLen);
}
updateState();
+ call Debug.flush();
}
command ieee154_status_t CapTx.transmit(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_allowedBackoffs will be decreased in every iteration (at zero the transmission failed)
- m_allowedBackoffs = call MLME_GET.macMaxCSMABackoffs();
+ m_macMaxCSMABackoffs = call MLME_GET.macMaxCSMABackoffs();
+ m_macMaxFrameRetries = call MLME_GET.macMaxFrameRetries();
m_macMaxBE = call MLME_GET.macMaxBE();
- m_BE = call MLME_GET.macMinBE();
- if (call MLME_GET.macBattLifeExt() && m_BE > 2)
- m_BE = 2;
+ m_macMinBE = call MLME_GET.macMinBE();
+ if (call MLME_GET.macBattLifeExt() && m_macMinBE > 2)
+ m_macMinBE = 2;
+ m_BE = m_macMinBE;
if (m_isBeaconEnabledPAN)
m_numCCA = 2;
else
m_numCCA = 1;
+ m_NB = 0;
m_transactionTime = IEEE154_SHR_DURATION +
(frame->headerLen + frame->payloadLen) * IEEE154_SYMBOLS_PER_OCTET;
- if (frame->header->mhr[0] & FC1_ACK_REQUEST)
+ if (frame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST)
m_transactionTime += (IEEE154_aTurnaroundTime + IEEE154_aUnitBackoffPeriod +
11 * IEEE154_SYMBOLS_PER_OCTET);
if (frame->headerLen + frame->payloadLen > IEEE154_aMaxSIFSFrameSize)
m_lock = FALSE; // unlock
call TokenToCfp.transfer();
return;
-
- }
+ }
}
// if there is nothing to do, then we must clear the lock
// the frame is already loaded -> transmit it now
if (m_numCCA == 1){
// unslotted CSMA-CA
- call RadioTx.transmit(NULL, m_backoff, m_numCCA, m_currentFrame->header->mhr[0] & FC1_ACK_REQUEST ? TRUE : FALSE);
+ call RadioTx.transmit(NULL, m_backoff, m_numCCA, m_currentFrame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST ? TRUE : FALSE);
next = WAIT_FOR_TXDONE; // this will NOT clear the lock
} else {
// slotted CSMA-CA
call RadioTx.transmit(call CapStartRefTime.getNow(),
elapsed + IEEE154_RADIO_TX_SEND_DELAY + m_backoff - m_backoffElapsed,
m_numCCA,
- m_currentFrame->header->mhr[0] & FC1_ACK_REQUEST ? TRUE : FALSE);
+ m_currentFrame->header->mhr[MHR_INDEX_FC1] & FC1_ACK_REQUEST ? TRUE : FALSE);
next = WAIT_FOR_TXDONE; // this will NOT clear the lock
} else {
// frame does not fit in remaing portion of the CAP
next = SWITCH_OFF;
else {
if (m_lastFrame){
- // we just transmitted a frame and have not yet
- // signalled the done to the upper layer -> wait
+ // the done event for the previous frame has not yet been
+ // signalled to the upper layer -> wait
next = DO_NOTHING;
} else
next = LOAD_TX;
async event void RadioTx.transmitDone(ieee154_txframe_t *frame,
ieee154_reftime_t *referenceTime, bool ackPendingFlag, error_t error)
- {
+ {
+ bool retry = FALSE;
switch (error)
{
- case SUCCESS:
+ case SUCCESS:
m_result = IEEE154_SUCCESS;
if (DEVICE_ROLE && frame->payload[0] == CMD_FRAME_DATA_REQUEST &&
((frame->header->mhr[MHR_INDEX_FC1]) & FC1_FRAMETYPE_MASK) == FC1_FRAMETYPE_CMD){
}
}
break;
- case EBUSY:
+ case EBUSY:
+ // we're following the SDL Spec in IEEE 802.15.4-2003 Annex D
m_result = IEEE154_CHANNEL_ACCESS_FAILURE;
- if (m_allowedBackoffs > 0){
- m_allowedBackoffs -= 1;
+ m_NB += 1;
+ if (m_NB < m_macMaxCSMABackoffs){
m_BE += 1;
if (m_BE > m_macMaxBE)
m_BE = m_macMaxBE;
- m_backoff = generateRandomBackoff(m_BE) * IEEE154_aUnitBackoffPeriod; // next backoff
- m_backoffElapsed = 0;
- m_lock = FALSE;
- updateState();
- return;
+ retry = TRUE;
}
break;
- case ENOACK:
+ case ENOACK:
+ // we're following the SDL Spec in IEEE 802.15.4-2003 Annex D
m_result = IEEE154_NO_ACK;
+ m_NB += 1;
+ // shouldn't the next check be (m_NB-1 < m_macMaxFrameRetries)? but
+ // on the other hand, NB is used for CHANNEL_ACCESS_FAILURE and NO_ACK,
+ // i.e. m_NB does not tell us much about past retransmissions anyway...
+ if (m_NB < m_macMaxFrameRetries){
+ m_BE = m_macMinBE;
+ retry = TRUE;
+ }
break;
default: break;
}
- if (COORD_ROLE && frame == m_bcastFrame){
+ if (retry){
+ m_backoff = generateRandomBackoff(m_BE) * IEEE154_aUnitBackoffPeriod; // next backoff
+ m_backoffElapsed = 0;
+ } else if (COORD_ROLE && frame == m_bcastFrame){
// signal result of broadcast transmissions immediately
restoreFrameFromBackup();
signalTxBroadcastDone(m_bcastFrame, m_result);
void backupCurrentFrame()
{
- ieee154_cap_frame_backup_t backup = {m_currentFrame, m_BE, m_allowedBackoffs,
- m_macMaxBE, m_backoff, m_backoffElapsed, m_transactionTime};
+ ieee154_cap_frame_backup_t backup = {m_currentFrame, m_BE, m_macMaxCSMABackoffs,
+ m_macMaxBE, m_macMinBE, m_NB, m_backoff, m_backoffElapsed, m_transactionTime};
call FrameBackup.setNow(&backup);
}
if (backup != NULL){
m_currentFrame = backup->frame;
m_BE = backup->BE;
- m_allowedBackoffs = backup->allowedBackoffs;
+ m_macMaxCSMABackoffs = backup->allowedBackoffs;
m_macMaxBE = backup->macMaxBE;
+ m_macMinBE = backup->macMinBE;
+ m_NB = backup->NB;
m_backoff = backup->backoff;
m_backoffElapsed = backup->backoffElapsed;
m_transactionTime = backup->transactionTime;
event void CoordCapTx.transmitDone(ieee154_txframe_t *txFrame, ieee154_status_t status)
{
uint8_t i;
+ // TODO: if CSMA-CA algorithm failed, then frame shall remain in transaction queue
for (i=0; i<NUM_MAX_PENDING; i++)
if (m_txFrameTable[i] == txFrame){
m_txFrameTable[i] = NULL; // slot is now empty
ieee154_macMaxBE_t BE;
ieee154_macMaxCSMABackoffs_t allowedBackoffs;
ieee154_macMaxBE_t macMaxBE;
+ ieee154_macMinBE_t macMinBE;
+ uint8_t NB;
uint16_t backoff;
uint16_t backoffElapsed;
uint32_t transactionTime;
MAC.Random -> RandomC;
MAC.Leds -> LedsC;
- components NoDebugP;
- MAC.Ieee802154Debug -> NoDebugP;
+#ifdef TKN154_SERIAL_DEBUG
+ components SerialDebugC as Debug;
+#else
+ components NoDebugP as Debug;
+#endif
+ MAC.Ieee802154Debug -> Debug;
}
-// here we introduce an error
-generic module Alarm32khzTo62500hzTransformC()
+/*
+ * 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 -------------------------------------------------------------
+ * $Date$
+ * @author Jan Hauer <hauer@tkn.tu-berlin.de>
+ * ========================================================================
+ */
+
+module Alarm32khzTo62500hzTransformC
+
{
- provides interface Alarm<T62500hz,uint32_t> as Alarm;
- uses interface Alarm<T32khz,uint32_t> as AlarmFrom;
+ provides interface Alarm<T62500hz,uint32_t> as Alarm[ uint8_t num ];
+ uses interface Alarm<T32khz,uint32_t> as AlarmFrom[ uint8_t num ];
}
implementation
{
- async command void Alarm.start(uint32_t dt){ call AlarmFrom.start(dt >> 1);}
- async command void Alarm.stop(){ call AlarmFrom.stop();}
- async event void AlarmFrom.fired(){ signal Alarm.fired();}
- async command bool Alarm.isRunning(){ return call AlarmFrom.isRunning();}
- async command void Alarm.startAt(uint32_t t0, uint32_t dt){ call AlarmFrom.startAt(t0 >> 1, dt >> 1);}
- async command uint32_t Alarm.getNow(){ return call AlarmFrom.getNow() << 1;}
- async command uint32_t Alarm.getAlarm(){ return call AlarmFrom.getAlarm() << 1;}
- default async event void Alarm.fired(){}
+/**
+ * This is the place where we cheat: since we don't have a clock source
+ * running at 62500 Hz, we cast 2 symbols to 1 tick of the 32768
+ * clock, which introduces a small (5%) error.
+*/
+#warning "Warning: MAC timing is not standard compliant (the symbol clock is based on the 32768 Hz oscillator)!"
+
+ async command void Alarm.start[ uint8_t num ](uint32_t dt){ call AlarmFrom.start[num](dt >> 1);}
+ async command void Alarm.stop[ uint8_t num ](){ call AlarmFrom.stop[num]();}
+ async event void AlarmFrom.fired[ uint8_t num ](){ signal Alarm.fired[num]();}
+ async command bool Alarm.isRunning[ uint8_t num ](){ return call AlarmFrom.isRunning[num]();}
+ async command uint32_t Alarm.getAlarm[ uint8_t num ](){ return call AlarmFrom.getAlarm[num]() << 1;}
+
+ async command uint32_t Alarm.getNow[ uint8_t num ](){
+ // this might shift out the most significant bit
+ // that's why Alarm.startAt() is converted to a Alarm.start()
+ return call AlarmFrom.getNow[num]() << 1;
+ }
+
+ async command void Alarm.startAt[ uint8_t num ](uint32_t t0, uint32_t dt){
+ // t0 occured before "now"
+ uint32_t now = call Alarm.getNow[num](), elapsed;
+ if (t0 <= now)
+ elapsed = now - t0;
+ else
+ elapsed = ~(t0 - now) + 1;
+ if (elapsed > dt)
+ elapsed = dt;
+ dt -= elapsed;
+ call AlarmFrom.start[num](dt >> 1);
+ }
+
+ /******************** Defaults ****************************/
+
+ default async command void AlarmFrom.start[ uint8_t num ](uint32_t dt){ }
+ default async command void AlarmFrom.stop[ uint8_t num ](){ }
+ default async command bool AlarmFrom.isRunning[ uint8_t num ](){ return FALSE;}
+ default async event void Alarm.fired[ uint8_t num ](){}
+ default async command void AlarmFrom.startAt[ uint8_t num ](uint32_t t0, uint32_t dt){ }
+ default async command uint32_t AlarmFrom.getNow[ uint8_t num ](){ return 0;}
+ default async command uint32_t AlarmFrom.getAlarm[ uint8_t num ](){ return 0;}
}
/**
* Alarm62500hzC is the alarm for async 62500hz alarms (virtualized)
- * This is the place where we cheat: since we don't have a clock source
- * running at 62500 Hz, we cast 2 symbols to 1 tick of the 32768
- * clock, which introduces a small error.
*
* @author Cory Sharp <cssharp@eecs.berkeley.edu>
* @author Jan Hauer <hauer@tkn.tu-berlin.de>
}
implementation
{
-#warning "Warning: MAC timing is not standard compliant (the symbol clock is based on the 32768 Hz oscillator)!"
- components new Alarm32khzTo62500hzTransformC();
- components Alarm32khz32VirtualizedP;
+ components Alarm32khzTo62500hzTransformC, Alarm32khz32VirtualizedP;
+ enum {
+ CLIENT_ID = unique(UQ_ALARM_32KHZ32),
+ };
- Alarm = Alarm32khzTo62500hzTransformC;
- Alarm32khzTo62500hzTransformC.AlarmFrom -> Alarm32khz32VirtualizedP.Alarm[unique(UQ_ALARM_32KHZ32)];
+ Alarm = Alarm32khzTo62500hzTransformC.Alarm[CLIENT_ID];
+ Alarm32khzTo62500hzTransformC.AlarmFrom[CLIENT_ID] -> Alarm32khz32VirtualizedP.Alarm[CLIENT_ID];
}
+++ /dev/null
-
-/* "Copyright (c) 2000-2003 The Regents of the University of California.
- * All rights reserved.
- *
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose, without fee, and without written agreement
- * is hereby granted, provided that the above copyright notice, the following
- * two paragraphs and the author appear in all copies of this software.
- *
- * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
- * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
- * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY
- * OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
- * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO
- * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
- */
-
-/**
- * Alarm62500hzC is the alarm for async 62500hz alarms (virtualized)
- * This is the place where we cheat: since we don't have a clock source
- * running at 62500 Hz, we cast 2 symbols to 1 tick of the 32768
- * clock, which introduces a small error.
- *
- * @author Cory Sharp <cssharp@eecs.berkeley.edu>
- * @author: Jan Hauer <hauer@tkn.tu-berlin.de>
- * @see Please refer to TEP 102 for more information about this component and its
- * intended use.
- */
-
-//#include "Timer.h"
-#include "Timer62500hz.h"
-generic configuration Alarm62500hz32VirtualizedHilC()
-{
- provides interface Alarm<T62500hz,uint32_t>;
-}
-implementation
-{
- components new Alarm32khzTo62500hzTransformC();
- components Alarm62500hz32VirtualizedHilP;
-
- Alarm = Alarm32khzTo62500hzTransformC;
- Alarm32khzTo62500hzTransformC.AlarmFrom -> Alarm62500hz32VirtualizedHilP.Alarm[unique(UQ_ALARM_32KHZ32)];
-}
-
+++ /dev/null
-#include "Timer62500hz.h"
-configuration Alarm62500hz32VirtualizedHilP
-{
- provides interface Alarm<T32khz,uint32_t> as Alarm[ uint8_t num ];
-}
-implementation
-{
- components new Alarm32khz32C(), MainC;
- components new VirtualizeAlarmC(T32khz, uint32_t, uniqueCount(UQ_ALARM_32KHZ32));
-
- Alarm = VirtualizeAlarmC;
-
- MainC -> Alarm32khz32C.Init;
- MainC -> VirtualizeAlarmC.Init;
- VirtualizeAlarmC.AlarmFrom -> Alarm32khz32C;
-}
}
implementation
{
- components new Alarm62500hz32VirtualizedHilC() as Alarm;
+ components new Alarm62500hz32VirtualizedC() as Alarm;
components new AlarmToTimerC(T62500hz);
components new VirtualizeTimerC(T62500hz,uniqueCount(UQ_TIMER_62500HZ));