* 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 Alarm<TSymbolIEEE802154,uint32_t> as CapEndAlarm;
interface Alarm<TSymbolIEEE802154,uint32_t> as BLEAlarm;
- interface Alarm<TSymbolIEEE802154,uint32_t> as IndirectTxWaitAlarm;
- interface Alarm<TSymbolIEEE802154,uint32_t> as BroadcastAlarm;
+ interface Alarm<TSymbolIEEE802154,uint32_t> as RxWaitAlarm;
interface TransferableResource as RadioToken;
+ interface ResourceRequested as RadioTokenRequested;
interface SuperframeStructure;
interface GetNow<token_requested_t> as IsRadioTokenRequested;
interface GetNow<bool> as IsRxEnableActive;
interface Get<ieee154_txframe_t*> as GetIndirectTxFrame;
interface Notify<bool> as RxEnableStateChange;
interface GetNow<bool> as IsTrackingBeacons;
+ interface Notify<const void*> as PIBUpdateMacRxOnWhenIdle;
interface FrameUtility;
interface SlottedCsmaCa;
interface RadioRx;
interface Leds;
interface SetNow<ieee154_cap_frame_backup_t*> as FrameBackup;
interface GetNow<ieee154_cap_frame_backup_t*> as FrameRestore;
- interface StdControl as TrackSingleBeacon;
+ interface SplitControl as TrackSingleBeacon;
+ interface MLME_SYNC_LOSS;
}
}
implementation
norace ieee154_txframe_t *m_bcastFrame;
norace ieee154_txframe_t *m_lastFrame;
norace uint16_t m_remainingBackoff;
+ ieee154_macRxOnWhenIdle_t macRxOnWhenIdle;
/* variables for the slotted CSMA-CA */
norace ieee154_csma_t m_csma;
/* function / task prototypes */
void stopAllAlarms();
- next_state_t tryReceive(rx_alarm_t alarmType);
+ next_state_t tryReceive();
next_state_t tryTransmit();
next_state_t trySwitchOff();
void backupCurrentFrame();
#define dbg_flush_state()
#endif
- command error_t Reset.init()
+ error_t reset(error_t error)
{
+ if (call RadioToken.isOwner()) // internal error! this must not happen!
+ return FAIL;
if (m_currentFrame)
- signal FrameTx.transmitDone(m_currentFrame, IEEE154_TRANSACTION_OVERFLOW);
+ signal FrameTx.transmitDone(m_currentFrame, error);
if (m_lastFrame)
- signal FrameTx.transmitDone(m_lastFrame, IEEE154_TRANSACTION_OVERFLOW);
+ signal FrameTx.transmitDone(m_lastFrame, error);
if (m_bcastFrame)
- signalTxBroadcastDone(m_bcastFrame, IEEE154_TRANSACTION_OVERFLOW);
+ signalTxBroadcastDone(m_bcastFrame, error);
m_currentFrame = m_lastFrame = m_bcastFrame = NULL;
+ m_macMaxFrameTotalWaitTime = call MLME_GET.macMaxFrameTotalWaitTime();
stopAllAlarms();
return SUCCESS;
}
+ command error_t Reset.init()
+ {
+ return reset(IEEE154_TRANSACTION_OVERFLOW);
+ }
+
+ event void MLME_SYNC_LOSS.indication (
+ ieee154_status_t lossReason,
+ uint16_t PANId,
+ uint8_t LogicalChannel,
+ uint8_t ChannelPage,
+ ieee154_security_t *security
+ )
+ {
+ // we lost sync to the coordinator -> spool out current packet
+ reset(IEEE154_NO_BEACON);
+ }
+
async event void RadioToken.transferredFrom(uint8_t fromClient)
{
// we got the token, i.e. CAP has just started
dbg_serial("DispatchSlottedCsmaP", "Got token, remaining CAP time: %lu\n",
call SuperframeStructure.sfStartTime() + capDuration - guardTime - call CapEndAlarm.getNow());
- if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) {
- // very rare case:
- // this can only happen, if we're on a beacon-enabled PAN, not tracking beacons,
- // and searched but didn't find a beacon for aBaseSuperframeDuration*(2n+1) symbols
- // we'd actually have to transmit the current frame using unslotted CSMA-CA
- // but we don't have that functionality available... signal FAIL...
- m_lastFrame = m_currentFrame;
- m_currentFrame = NULL;
- m_txStatus = IEEE154_NO_BEACON;
- dbg_serial("DispatchSlottedCsmaP", "CAP component got token, remaining time: %lu\n");
- post signalTxDoneTask();
- return;
- } else if (capDuration < guardTime) {
- // CAP is too short to do anything practical
+
+ if (capDuration < guardTime) {
+ // CAP is too short to do anything useful
dbg_serial("DispatchSlottedCsmaP", "CAP too short!\n");
call RadioToken.transferTo(RADIO_CLIENT_CFP);
return;
// in task context and then continue
m_lock = TRUE;
post setupTxBroadcastTask();
- dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast.\n");
+ dbg_serial("DispatchSlottedCsmaP", "Preparing broadcast...\n");
}
}
call CapEndAlarm.startAt(call SuperframeStructure.sfStartTime(), capDuration);
if (DEVICE_ROLE && !call IsTrackingBeacons.getNow()) {
call TrackSingleBeacon.start();
dbg_serial("DispatchSlottedCsmaP", "Tracking single beacon now\n");
- // we'll receive the Token after a beacon was found or after
- // aBaseSuperframeDuration*(2n+1) symbols if none was found
+ // we'll get the Token after a beacon was found or a SYNC_LOSS event
+ // if none was found during the next aBaseSuperframeDuration*(2n+1) symbols
}
updateState();
return IEEE154_SUCCESS;
}
}
+ event void TrackSingleBeacon.startDone(error_t error)
+ {
+ if (error != SUCCESS) // beacon could not be tracked
+ reset(IEEE154_NO_BEACON);
+ // else: we'll get the RadioToken and continue as usual ...
+ }
+
task void setupTxBroadcastTask()
{
ieee154_macDSN_t tmp;
void stopAllAlarms()
{
call CapEndAlarm.stop();
- if (DEVICE_ROLE) {
- call IndirectTxWaitAlarm.stop();
- call BroadcastAlarm.stop();
- }
+ if (DEVICE_ROLE)
+ call RxWaitAlarm.stop();
call BLEAlarm.stop();
}
(uint32_t) call SuperframeStructure.sfSlotDuration();
// Check 1: has the CAP finished?
- if ((COORD_ROLE || call IsTrackingBeacons.getNow()) &&
- (call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(),
+ if ((call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(),
capDuration - call SuperframeStructure.guardTime()) ||
!call CapEndAlarm.isRunning())) {
dbg_push_state(1);
if (call RadioOff.isOff()) {
stopAllAlarms(); // may still fire, but is locked through isOwner()
if (DEVICE_ROLE && m_indirectTxPending)
- signal IndirectTxWaitAlarm.fired();
+ signal RxWaitAlarm.fired();
m_broadcastRxPending = FALSE;
if (COORD_ROLE && m_bcastFrame) {
// didn't manage to transmit a broadcast
else if (DEVICE_ROLE && m_broadcastRxPending) {
// receive a broadcast from coordinator
dbg_push_state(2);
- next = tryReceive(BROADCAST_ALARM);
+ next = tryReceive();
} else if (COORD_ROLE && m_bcastFrame) {
dbg_push_state(2);
next = tryTransmit();
// and are we now waiting for a frame from the coordinator?
else if (DEVICE_ROLE && m_indirectTxPending) {
dbg_push_state(3);
- next = tryReceive(INDIRECT_TX_ALARM);
+ next = tryReceive();
}
// Check 4: is some other operation (like MLME-SCAN or MLME-RESET) pending?
else if (call SuperframeStructure.battLifeExtDuration() > 0 &&
call TimeCalc.hasExpired(call SuperframeStructure.sfStartTime(),
call SuperframeStructure.battLifeExtDuration()) &&
- !call IsRxEnableActive.getNow()) {
+ !call IsRxEnableActive.getNow() && !macRxOnWhenIdle) {
dbg_push_state(5);
next = trySwitchOff();
}
}
// Check 7: should we be in receive mode?
- else if (COORD_ROLE || call IsRxEnableActive.getNow()) {
+ else if (COORD_ROLE || call IsRxEnableActive.getNow() || macRxOnWhenIdle) {
dbg_push_state(7);
- next = tryReceive(NO_ALARM);
+ next = tryReceive();
if (next == DO_NOTHING) {
- // this means there is an active MLME_RX_ENABLE.request
- // and the radio was just switched to Rx mode - signal
- // a notify event to inform the respective component
+ // if there was an active MLME_RX_ENABLE.request then we'll
+ // inform the next higher layer that radio is now in Rx mode
post wasRxEnabledTask();
}
}
return next;
}
- next_state_t tryReceive(rx_alarm_t alarmType)
+ next_state_t tryReceive()
{
next_state_t next;
if (call RadioRx.isReceiving())
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;
return next;
}
- async event void RadioOff.offDone() { m_lock = FALSE; updateState();}
- async event void RadioRx.enableRxDone() { m_lock = FALSE; updateState();}
+ async event void RadioOff.offDone()
+ {
+ m_lock = FALSE;
+ updateState();
+ }
+
+ async event void RadioRx.enableRxDone()
+ {
+ if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending))
+ call RxWaitAlarm.start(m_macMaxFrameTotalWaitTime);
+ m_lock = FALSE;
+ updateState();
+ }
async event void CapEndAlarm.fired() {
dbg_serial("DispatchSlottedCsmaP", "CapEndAlarm.fired()\n");
}
async event void BLEAlarm.fired() { updateState();}
event void RxEnableStateChange.notify(bool whatever) { updateState();}
- async event void BroadcastAlarm.fired() { m_broadcastRxPending = FALSE; updateState();}
+ event void PIBUpdateMacRxOnWhenIdle.notify( const void* val ) {
+ atomic macRxOnWhenIdle = *((ieee154_macRxOnWhenIdle_t*) val);
+ updateState();
+ }
- async event void IndirectTxWaitAlarm.fired()
+ async event void RxWaitAlarm.fired()
{
- atomic {
- if (m_indirectTxPending) {
- m_indirectTxPending = FALSE;
- post signalTxDoneTask();
+ if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending))
+ atomic {
+ if (m_indirectTxPending) {
+ m_indirectTxPending = FALSE;
+ post signalTxDoneTask();
+ } else if (m_broadcastRxPending) {
+ m_broadcastRxPending = FALSE;
+ updateState();
+ }
}
- }
}
async event void SlottedCsmaCa.transmitDone(ieee154_txframe_t *frame, ieee154_csma_t *csma,
uint8_t *payload = (uint8_t *) frame->data;
uint8_t *mhr = MHR(frame);
uint8_t frameType = mhr[MHR_INDEX_FC1] & FC1_FRAMETYPE_MASK;
+
if (frameType == FC1_FRAMETYPE_CMD)
frameType += payload[0];
+ dbg("DispatchSlottedCsmaP", "Received frame, DSN: %lu, type: 0x%lu\n",
+ (uint32_t) mhr[MHR_INDEX_SEQNO], (uint32_t) frameType);
atomic {
- if (DEVICE_ROLE && m_indirectTxPending) {
+ if (DEVICE_ROLE && (m_indirectTxPending || m_broadcastRxPending)) {
message_t* frameBuf;
- call IndirectTxWaitAlarm.stop();
- // TODO: check!
- //if (frame->payloadLen)
- // is this frame from our coordinator? hmm... we cannot say/ with
- // certainty, because we might only know either the coordinator
- // extended or short address (and the frame could/ have been sent
- // with the other addressing mode) ??
+ call RxWaitAlarm.stop();
+ // TODO: check the following:
+ // is this frame from our coordinator? hmm... we cannot say/ with
+ // certainty, because we might only know either the coordinator
+ // extended or short address (and the frame could/ have been sent
+ // with the other addressing mode) ??
m_txStatus = IEEE154_SUCCESS;
- frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame);
- signal IndirectTxWaitAlarm.fired();
+ if (m_indirectTxPending)
+ frameBuf = signal FrameExtracted.received[frameType](frame, m_lastFrame); // indirect tx from coord
+ else
+ frameBuf = signal FrameRx.received[frameType](frame); // broadcast from coordinator
+ signal RxWaitAlarm.fired();
return frameBuf;
} else
return signal FrameRx.received[frameType](frame);
default event message_t* FrameRx.received[uint8_t client](message_t* data) {return data;}
default async command bool IsRxEnableActive.getNow() {return FALSE;}
- default async command void IndirectTxWaitAlarm.start(uint32_t dt) {ASSERT(0);}
- default async command void IndirectTxWaitAlarm.stop() {ASSERT(0);}
- default async command void IndirectTxWaitAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);}
+ default async command void RxWaitAlarm.start(uint32_t dt) {ASSERT(0);}
+ default async command void RxWaitAlarm.stop() {ASSERT(0);}
+ default async command void RxWaitAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);}
- default async command void BroadcastAlarm.start(uint32_t dt) {ASSERT(0);}
- default async command void BroadcastAlarm.stop() {ASSERT(0);}
- default async command void BroadcastAlarm.startAt(uint32_t t0, uint32_t dt) {ASSERT(0);}
-
default async command bool SuperframeStructure.isBroadcastPending() { return FALSE;}
default async event void BroadcastTx.transmitNowDone(ieee154_txframe_t *frame, ieee154_status_t status) {}
default event message_t* FrameExtracted.received[uint8_t client](message_t* msg, ieee154_txframe_t *txFrame) {return msg;}
default async command error_t FrameBackup.setNow(ieee154_cap_frame_backup_t* val) {return FAIL;}
default async command ieee154_cap_frame_backup_t* FrameRestore.getNow() {return NULL;}
- default command error_t TrackSingleBeacon.start() {return FAIL;}
+ event void TrackSingleBeacon.stopDone(error_t error){}
+ default command error_t TrackSingleBeacon.start() {if (DEVICE_ROLE) ASSERT(0); return SUCCESS;}
command error_t WasRxEnabled.enable() {return FAIL;}
command error_t WasRxEnabled.disable() {return FAIL;}
+ async event void RadioTokenRequested.requested(){ updateState(); }
+ async event void RadioTokenRequested.immediateRequested(){ updateState(); }
}