interface RadioTx as BeaconTx;
interface MLME_GET;
interface MLME_SET;
- interface Resource as Token;
- interface ResourceTransferred as TokenTransferred;
- interface ResourceTransfer as TokenToBroadcast;
- interface GetNow<bool> as IsTokenRequested;
+ interface TransferableResource as RadioToken;
interface FrameTx as RealignmentBeaconEnabledTx;
interface FrameTx as RealignmentNonBeaconEnabledTx;
interface FrameRx as BeaconRequestRx;
interface GetSet<ieee154_txframe_t*> as GetSetRealignmentFrame;
interface GetNow<bool> as IsBroadcastReady;
interface TimeCalc;
+ interface Random;
interface Leds;
}
}
norace uint32_t m_beaconInterval;
norace uint32_t m_previousBeaconInterval;
norace uint32_t m_dt;
- norace uint8_t m_bsn;
norace uint32_t m_lastBeaconTxTime;
norace ieee154_timestamp_t m_lastBeaconTxRefTime;
norace ieee154_macBattLifeExtPeriods_t m_battLifeExtPeriods;
/* function/task prototypes */
task void txDoneTask();
task void signalStartConfirmSuccessTask();
- void prepareNextBeaconTransmission();
+ void nextRound();
+ void prepareBeaconTransmission();
void continueStartRequest();
void finishRealignment(ieee154_txframe_t *frame, ieee154_status_t status);
{
// reset this component, will only be called while we're not owning the token
// TODO: check to signal MLME_START.confirm ?
+
+ call MLME_SET.macBSN(call Random.rand16());
m_beaconFrame.header = &m_header;
m_beaconFrame.headerLen = 0;
m_beaconFrame.payload = m_payload;
status = IEEE154_INVALID_PARAMETER;
else if (startTime && !call IsTrackingBeacons.getNow())
status = IEEE154_TRACKING_OFF;
- else if (startTime && 0xFF000000)
+ else if (startTime & 0xFF000000)
status = IEEE154_INVALID_PARAMETER;
else if (m_requestBitmap & (REQUEST_CONFIRM_PENDING | REQUEST_UPDATE_SF))
status = IEEE154_TRANSACTION_OVERFLOW;
if (m_beaconOrder == 15) {
// We're not already transmitting beacons, i.e. we have to request the token
// (otherwise we'd get the token "automatically" for the next scheduled beacon).
- call Token.request();
+ call RadioToken.request();
}
// We'll continue the MLME_START operation in continueStartRequest() once we have the token
}
}
m_dt = m_beaconInterval;
m_txState = S_TX_IDLE;
- m_bsn = call MLME_GET.macBSN()+1;
m_battLifeExtPeriods = call MLME_GET.macBattLifeExtPeriods();
// (3) update PIB
isShortAddr = (shortAddress != 0xFFFE);
m_beaconFrame.header->mhr[MHR_INDEX_FC1] = FC1_FRAMETYPE_BEACON;
m_beaconFrame.header->mhr[MHR_INDEX_FC2] = isShortAddr ? FC2_SRC_MODE_SHORT : FC2_SRC_MODE_EXTENDED;
+ m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] = call MLME_GET.macBSN() + 1;
offset = MHR_INDEX_ADDRESS;
*((nxle_uint16_t*) &m_beaconFrame.header->mhr[offset]) = m_updatePANId;
offset += sizeof(ieee154_macPANId_t);
}
}
- task void grantedTask()
+ task void signalGrantedTask()
{
- signal Token.granted();
+ signal RadioToken.granted();
}
- event void Token.granted()
+ event void RadioToken.granted()
{
- dbg_serial("BeaconSynchronizeP","Got token, will Tx beacon in %lu\n",
- (uint32_t) ((m_lastBeaconTxTime + m_dt) - call BeaconSendAlarm.getNow()));
+ dbg_serial("BeaconSynchronizeP","Token granted.\n");
if (m_requestBitmap & REQUEST_REALIGNMENT_DONE_PENDING) {
- // unlikely to occur: we have not yet received a done()
+ // very unlikely: we have not yet received a done()
// event after sending out a realignment frame
dbg_serial("BeaconTransmitP", "Realignment pending (request: %lu) !\n", (uint32_t) m_requestBitmap);
- post grantedTask(); // spin
+ post signalGrantedTask(); // spin
return;
} else if (m_requestBitmap & REQUEST_UPDATE_SF) {
dbg_serial("BeaconTransmitP","Putting new superframe spec into operation\n");
m_requestBitmap &= ~REQUEST_UPDATE_SF;
continueStartRequest();
}
+ nextRound();
+ }
+
+ void nextRound()
+ {
if (call RadioOff.isOff())
- prepareNextBeaconTransmission();
+ prepareBeaconTransmission();
else
- ASSERT(call RadioOff.off() == SUCCESS); // will continue in prepareNextBeaconTransmission()
+ ASSERT(call RadioOff.off() == SUCCESS); // will continue in prepareBeaconTransmission()
}
- async event void TokenTransferred.transferred()
+ async event void RadioToken.transferredFrom(uint8_t fromClientID)
{
- if (call IsTokenRequested.getNow()) {
- // some other component needs the token - we give it up for now,
- // but before make another request to get it back afterwards
- dbg_serial("BeaconTransmitP", "Token is requested, releasing it now.\n");
- call Token.request();
- call Token.release();
- } else
- post grantedTask();
+ dbg_serial("BeaconSynchronizeP","Token transferred, will Tx beacon in %lu\n",
+ (uint32_t) ((m_lastBeaconTxTime + m_dt) - call BeaconSendAlarm.getNow()));
+ if (m_requestBitmap & (REQUEST_REALIGNMENT_DONE_PENDING | REQUEST_UPDATE_SF))
+ post signalGrantedTask(); // need to be in sync context
+ else
+ nextRound();
}
async event void RadioOff.offDone()
{
- prepareNextBeaconTransmission();
+ prepareBeaconTransmission();
}
- void prepareNextBeaconTransmission()
+ void prepareBeaconTransmission()
{
if (m_txState == S_TX_LOCKED) {
// have not had time to finish processing the last sent beacon
dbg_serial("BeaconTransmitP", "Token was returned too fast!\n");
- post grantedTask();
+ post signalGrantedTask();
} else if (m_beaconOrder == 15) {
// we're not sending any beacons!?
dbg_serial("BeaconTransmitP", "Stop sending beacons.\n");
- call Token.release();
+ call RadioToken.release();
} else {
// get ready for next beacon transmission
atomic {
else
m_beaconFrame.header->mhr[MHR_INDEX_FC1] &= ~FC1_FRAME_PENDING;
- m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] = m_bsn; // update beacon seqno
if (m_txOneBeaconImmediately) {
m_txOneBeaconImmediately = FALSE;
timestamp = NULL;
dbg_serial("BeaconTransmitP", "Beacon Tx success at %lu\n", (uint32_t) m_lastBeaconTxTime);
} else {
// Timestamp is invalid; this is bad. We need the beacon timestamp for the
- // slotted CSMA-CA, because it defines slot reference time. We can't use this superframe
+ // slotted CSMA-CA, because it defines the slot reference time. We can't use this superframe
// TODO: check if this was the initial beacon (then m_lastBeaconTxRefTime is invalid)
dbg_serial("BeaconTransmitP", "Invalid timestamp!\n");
m_dt += m_beaconInterval;
- call Token.request();
- call Token.release();
+ call RadioToken.request();
+ call RadioToken.release();
return;
}
// update superframe-related variables
- m_numGtsSlots = (frame->payload[2] & 0x07);
+ m_numGtsSlots =
+ (frame->payload[BEACON_INDEX_GTS_SPEC] & GTS_DESCRIPTOR_COUNT_MASK) >> GTS_DESCRIPTOR_COUNT_OFFSET;
gtsFieldLength = 1 + ((m_numGtsSlots > 0) ? 1 + m_numGtsSlots * 3: 0);
- m_numCapSlots = (frame->payload[1] & 0x0F) + 1;
- m_sfSlotDuration = (((uint32_t) 1) << ((frame->payload[0] & 0xF0) >> 4)) * IEEE154_aBaseSlotDuration;
+ m_numCapSlots =
+ ((frame->payload[BEACON_INDEX_SF_SPEC2] & SF_SPEC2_FINAL_CAPSLOT_MASK) >> SF_SPEC2_FINAL_CAPSLOT_OFFSET) + 1;
+ m_sfSlotDuration =
+ (((uint32_t) 1) << ((frame->payload[BEACON_INDEX_SF_SPEC1] & SF_SPEC1_SO_MASK) >> SF_SPEC1_SO_OFFSET)) *
+ IEEE154_aBaseSlotDuration;
- if (frame->header->mhr[0] & FC1_FRAME_PENDING)
+ if (frame->header->mhr[MHR_INDEX_FC1] & FC1_FRAME_PENDING)
m_framePendingBit = TRUE;
else
m_framePendingBit = FALSE;
- memcpy(m_gtsField, &frame->payload[2], gtsFieldLength);
- if (frame->payload[1] & 0x10) {
+ memcpy(m_gtsField, &frame->payload[BEACON_INDEX_GTS_SPEC], gtsFieldLength);
+ if (frame->payload[BEACON_INDEX_SF_SPEC2] & SF_SPEC2_BATT_LIFE_EXT) {
// BLE is active; calculate the time offset from slot 0
m_battLifeExtDuration = IEEE154_SHR_DURATION +
(frame->headerLen + frame->payloadLen + 2) * IEEE154_SYMBOLS_PER_OCTET;
m_battLifeExtDuration = m_battLifeExtDuration + m_battLifeExtPeriods * 20;
} else
m_battLifeExtDuration = 0;
- call TokenToBroadcast.transfer();
+
+ // we pass on the token now, but make a reservation to get it back
+ // to transmit the next beacon (at the start of the next superframe)
+ call RadioToken.request();
+ call RadioToken.transferTo(RADIO_CLIENT_COORDBROADCAST);
post txDoneTask();
}
task void txDoneTask()
{
- call MLME_SET.macBSN(m_bsn++);
+ call MLME_SET.macBSN(m_beaconFrame.header->mhr[MHR_INDEX_SEQNO]);
+ m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] += 1; // may be overwritten by the next higher layer
call SetMacBeaconTxTime.set(m_lastBeaconTxTime); // start of slot0, ie. first preamble byte of beacon
call BeaconPayloadUpdateTimer.startOneShotAt(m_lastBeaconTxTime,
(m_beaconInterval>BEACON_PAYLOAD_UPDATE_INTERVAL) ? (m_beaconInterval - BEACON_PAYLOAD_UPDATE_INTERVAL): 0);
uint8_t getNumGtsSlots(uint8_t *gtsInfoField)
{
uint8_t i, num=0;
- for (i=0; i<(gtsInfoField[0] & GTS_DESCRIPTOR_COUNT_MASK); i++)
+ for (i=0; i<((gtsInfoField[0] & GTS_DESCRIPTOR_COUNT_MASK) >> GTS_DESCRIPTOR_COUNT_OFFSET); i++)
num += ((gtsInfoField[4+i*3] & GTS_LENGTH_MASK) >> GTS_LENGTH_OFFSET);
return num;
}
// (3) update SF spec
beaconSpecs -= 2; // sizeof SF Spec
if (m_payloadState & MODIFIED_SF_SPEC) {
- beaconSpecs[0] = m_beaconOrder | (m_superframeOrder << 4);
- beaconSpecs[1] = 0;
+ beaconSpecs[BEACON_INDEX_SF_SPEC1] =
+ (m_beaconOrder << SF_SPEC1_BO_OFFSET) | (m_superframeOrder << SF_SPEC1_SO_OFFSET);
+ beaconSpecs[BEACON_INDEX_SF_SPEC2] = 0;
if (call MLME_GET.macAssociationPermit())
- beaconSpecs[1] |= SF_SPEC2_ASSOCIATION_PERMIT;
+ beaconSpecs[BEACON_INDEX_SF_SPEC2] |= SF_SPEC2_ASSOCIATION_PERMIT;
if (call MLME_GET.macPanCoordinator())
- beaconSpecs[1] |= SF_SPEC2_PAN_COORD;
- beaconSpecs[1] |= ((15-numGtsSlots) & 0x0F); // update FinalCAPSlot field
+ beaconSpecs[BEACON_INDEX_SF_SPEC2] |= SF_SPEC2_PAN_COORD;
+ beaconSpecs[BEACON_INDEX_SF_SPEC2] |=
+ ((15-numGtsSlots) & SF_SPEC2_FINAL_CAPSLOT_MASK);
}
m_beaconFrame.payloadLen = (m_pendingAddrLen + m_pendingGtsLen + 2) + m_beaconPayloadLen;
m_beaconFrame.payload = beaconSpecs;
} // end atomic (give BeaconSendAlarm.fired() the chance to execute)
signal IEEE154TxBeaconPayload.aboutToTransmit();
+ m_beaconFrame.header->mhr[MHR_INDEX_SEQNO] = call MLME_GET.macBSN() + 1;
atomic {
// (4) try to update beacon payload